blob: 877d10b276db8de91ba42e92ac04aa50dbea09ae [file] [log] [blame]
Ben Claytoneea9d352019-08-29 01:05:14 +01001// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef sw_Memset_hpp
16#define sw_Memset_hpp
17
18#include <cstring>
19#include <type_traits>
20
Nicolas Capens1885f692020-03-23 11:28:44 -040021// GCC 8+ warns that
22// "‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘T’;
23// use assignment or value-initialization instead [-Werror=class-memaccess]"
24// This is benign iff it happens before any of the base or member constructors are called.
25#if defined(__GNUC__) && (__GNUC__ >= 8)
26# pragma GCC diagnostic push
27# pragma GCC diagnostic ignored "-Wclass-memaccess"
28#endif
29
Nicolas Capens157ba262019-12-10 17:49:14 -050030namespace sw {
31
Nicolas Capens1885f692020-03-23 11:28:44 -040032// Memset<> is a helper class for clearing the memory of objects at construction.
33// It is useful as the *first* base class of map keys which may contain padding
Nicolas Capens157ba262019-12-10 17:49:14 -050034// bytes or bits otherwise left uninitialized.
35template<class T>
36struct Memset
Ben Claytoneea9d352019-08-29 01:05:14 +010037{
Nicolas Capens157ba262019-12-10 17:49:14 -050038 Memset(T *object, int val)
Ben Claytoneea9d352019-08-29 01:05:14 +010039 {
Nicolas Capens157ba262019-12-10 17:49:14 -050040 static_assert(std::is_base_of<Memset<T>, T>::value, "Memset<T> must only clear the memory of a type of which it is a base class");
Nicolas Capens1885f692020-03-23 11:28:44 -040041 ::memset(object, 0, sizeof(T));
42 }
Ben Claytoneea9d352019-08-29 01:05:14 +010043
Nicolas Capens1885f692020-03-23 11:28:44 -040044 // Don't rely on the implicitly declared copy constructor and copy assignment operator.
45 // They can leave padding bytes uninitialized.
46 Memset(const Memset &rhs)
47 {
48 ::memcpy(this, &rhs, sizeof(T));
49 }
Ben Claytoneea9d352019-08-29 01:05:14 +010050
Nicolas Capens1885f692020-03-23 11:28:44 -040051 Memset &operator=(const Memset &rhs)
52 {
53 ::memcpy(this, &rhs, sizeof(T));
54 return *this;
55 }
Ben Claytoneea9d352019-08-29 01:05:14 +010056
Nicolas Capens1885f692020-03-23 11:28:44 -040057 // The compiler won't declare an implicit move constructor and move assignment operator
58 // due to having a user-defined copy constructor and copy assignment operator. Delete
59 // them for explicitness. We always want memcpy() being called.
60 Memset(const Memset &&rhs) = delete;
61 Memset &operator=(const Memset &&rhs) = delete;
62
63 friend bool operator==(const T &a, const T &b)
64 {
65 return ::memcmp(&a, &b, sizeof(T)) == 0;
66 }
67
68 friend bool operator!=(const T &a, const T &b)
69 {
70 return ::memcmp(&a, &b, sizeof(T)) != 0;
71 }
72
73 friend bool operator<(const T &a, const T &b)
74 {
75 return ::memcmp(&a, &b, sizeof(T)) < 0;
Nicolas Capens157ba262019-12-10 17:49:14 -050076 }
77};
Ben Claytoneea9d352019-08-29 01:05:14 +010078
Nicolas Capens157ba262019-12-10 17:49:14 -050079} // namespace sw
Ben Claytoneea9d352019-08-29 01:05:14 +010080
Nicolas Capens1885f692020-03-23 11:28:44 -040081// Restore -Wclass-memaccess
82#if defined(__GNUC__) && (__GNUC__ >= 8)
83# pragma GCC diagnostic pop
84#endif
85
Ben Claytonfccfc562019-12-17 20:37:31 +000086#endif // sw_Memset_hpp