1 // 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 21 // 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 30 namespace sw { 31 32 // 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 34 // bytes or bits otherwise left uninitialized. 35 template<class T> 36 struct Memset 37 { Memsetsw::Memset38 Memset(T *object, int val) 39 { 40 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"); 41 static_assert(!std::is_polymorphic<T>::value, "Memset<T> must not be used with classes that have virtual functions"); 42 ::memset(object, 0, sizeof(T)); 43 } 44 45 // Don't rely on the implicitly declared copy constructor and copy assignment operator. 46 // They can leave padding bytes uninitialized. Memsetsw::Memset47 Memset(const Memset &rhs) 48 { 49 ::memcpy(this, &rhs, sizeof(T)); 50 } 51 operator =sw::Memset52 Memset &operator=(const Memset &rhs) 53 { 54 ::memcpy(this, &rhs, sizeof(T)); 55 return *this; 56 } 57 58 // The compiler won't declare an implicit move constructor and move assignment operator 59 // due to having a user-defined copy constructor and copy assignment operator. Delete 60 // them for explicitness. We always want memcpy() being called. 61 Memset(const Memset &&rhs) = delete; 62 Memset &operator=(const Memset &&rhs) = delete; 63 operator ==(const T & a,const T & b)64 friend bool operator==(const T &a, const T &b) 65 { 66 return ::memcmp(&a, &b, sizeof(T)) == 0; 67 } 68 operator !=(const T & a,const T & b)69 friend bool operator!=(const T &a, const T &b) 70 { 71 return ::memcmp(&a, &b, sizeof(T)) != 0; 72 } 73 operator <(const T & a,const T & b)74 friend bool operator<(const T &a, const T &b) 75 { 76 return ::memcmp(&a, &b, sizeof(T)) < 0; 77 } 78 }; 79 80 } // namespace sw 81 82 // Restore -Wclass-memaccess 83 #if defined(__GNUC__) && (__GNUC__ >= 8) 84 # pragma GCC diagnostic pop 85 #endif 86 87 #endif // sw_Memset_hpp