- //===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- /// \file 
- /// Defines the clang::SanitizerKind enum. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_BASIC_SANITIZERS_H 
- #define LLVM_CLANG_BASIC_SANITIZERS_H 
-   
- #include "clang/Basic/LLVM.h" 
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/Support/HashBuilder.h" 
- #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" 
- #include <cassert> 
- #include <cstdint> 
-   
- namespace llvm { 
- class hash_code; 
- } 
-   
- namespace clang { 
-   
- class SanitizerMask { 
-   // NOTE: this class assumes kNumElem == 2 in most of the constexpr functions, 
-   // in order to work within the C++11 constexpr function constraints. If you 
-   // change kNumElem, you'll need to update those member functions as well. 
-   
-   /// Number of array elements. 
-   static constexpr unsigned kNumElem = 2; 
-   /// Mask value initialized to 0. 
-   uint64_t maskLoToHigh[kNumElem]{}; 
-   /// Number of bits in a mask. 
-   static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8; 
-   /// Number of bits in a mask element. 
-   static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8; 
-   
-   constexpr SanitizerMask(uint64_t mask1, uint64_t mask2) 
-       : maskLoToHigh{mask1, mask2} {} 
-   
- public: 
-   SanitizerMask() = default; 
-   
-   static constexpr bool checkBitPos(const unsigned Pos) { 
-     return Pos < kNumBits; 
-   } 
-   
-   /// Create a mask with a bit enabled at position Pos. 
-   static constexpr SanitizerMask bitPosToMask(const unsigned Pos) { 
-     uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0; 
-     uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2)) 
-                          ? 1ULL << (Pos % kNumBitElem) 
-                          : 0; 
-     return SanitizerMask(mask1, mask2); 
-   } 
-   
-   unsigned countPopulation() const; 
-   
-   void flipAllBits() { 
-     for (auto &Val : maskLoToHigh) 
-       Val = ~Val; 
-   } 
-   
-   bool isPowerOf2() const { 
-     return countPopulation() == 1; 
-   } 
-   
-   llvm::hash_code hash_value() const; 
-   
-   template <typename HasherT, llvm::support::endianness Endianness> 
-   friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder, 
-                       const SanitizerMask &SM) { 
-     HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]); 
-   } 
-   
-   constexpr explicit operator bool() const { 
-     return maskLoToHigh[0] || maskLoToHigh[1]; 
-   } 
-   
-   constexpr bool operator==(const SanitizerMask &V) const { 
-     return maskLoToHigh[0] == V.maskLoToHigh[0] && 
-            maskLoToHigh[1] == V.maskLoToHigh[1]; 
-   } 
-   
-   SanitizerMask &operator&=(const SanitizerMask &RHS) { 
-     for (unsigned k = 0; k < kNumElem; k++) 
-       maskLoToHigh[k] &= RHS.maskLoToHigh[k]; 
-     return *this; 
-   } 
-   
-   SanitizerMask &operator|=(const SanitizerMask &RHS) { 
-     for (unsigned k = 0; k < kNumElem; k++) 
-       maskLoToHigh[k] |= RHS.maskLoToHigh[k]; 
-     return *this; 
-   } 
-   
-   constexpr bool operator!() const { return !bool(*this); } 
-   
-   constexpr bool operator!=(const SanitizerMask &RHS) const { 
-     return !((*this) == RHS); 
-   } 
-   
-   friend constexpr inline SanitizerMask operator~(SanitizerMask v) { 
-     return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]); 
-   } 
-   
-   friend constexpr inline SanitizerMask operator&(SanitizerMask a, 
-                                                   const SanitizerMask &b) { 
-     return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0], 
-                          a.maskLoToHigh[1] & b.maskLoToHigh[1]); 
-   } 
-   
-   friend constexpr inline SanitizerMask operator|(SanitizerMask a, 
-                                                   const SanitizerMask &b) { 
-     return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0], 
-                          a.maskLoToHigh[1] | b.maskLoToHigh[1]); 
-   } 
- }; 
-   
- // Declaring in clang namespace so that it can be found by ADL. 
- llvm::hash_code hash_value(const clang::SanitizerMask &Arg); 
-   
- // Define the set of sanitizer kinds, as well as the set of sanitizers each 
- // sanitizer group expands into. 
- struct SanitizerKind { 
-   // Assign ordinals to possible values of -fsanitize= flag, which we will use 
-   // as bit positions. 
-   enum SanitizerOrdinal : uint64_t { 
- #define SANITIZER(NAME, ID) SO_##ID, 
- #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group, 
- #include "clang/Basic/Sanitizers.def" 
-     SO_Count 
-   }; 
-   
- #define SANITIZER(NAME, ID)                                                    \ 
-   static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \ 
-   static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big."); 
- #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \ 
-   static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \ 
-   static constexpr SanitizerMask ID##Group =                                   \ 
-       SanitizerMask::bitPosToMask(SO_##ID##Group);                             \ 
-   static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \ 
-                 "Bit position too big."); 
- #include "clang/Basic/Sanitizers.def" 
- }; // SanitizerKind 
-   
- struct SanitizerSet { 
-   /// Check if a certain (single) sanitizer is enabled. 
-   bool has(SanitizerMask K) const { 
-     assert(K.isPowerOf2() && "Has to be a single sanitizer."); 
-     return static_cast<bool>(Mask & K); 
-   } 
-   
-   /// Check if one or more sanitizers are enabled. 
-   bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); } 
-   
-   /// Enable or disable a certain (single) sanitizer. 
-   void set(SanitizerMask K, bool Value) { 
-     assert(K.isPowerOf2() && "Has to be a single sanitizer."); 
-     Mask = Value ? (Mask | K) : (Mask & ~K); 
-   } 
-   
-   /// Disable the sanitizers specified in \p K. 
-   void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } 
-   
-   /// Returns true if no sanitizers are enabled. 
-   bool empty() const { return !Mask; } 
-   
-   /// Bitmask of enabled sanitizers. 
-   SanitizerMask Mask; 
- }; 
-   
- /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. 
- /// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known. 
- SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); 
-   
- /// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=. 
- void serializeSanitizerSet(SanitizerSet Set, 
-                            SmallVectorImpl<StringRef> &Values); 
-   
- /// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers 
- /// this group enables. 
- SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); 
-   
- /// Return the sanitizers which do not affect preprocessing. 
- inline SanitizerMask getPPTransparentSanitizers() { 
-   return SanitizerKind::CFI | SanitizerKind::Integer | 
-          SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | 
-          SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero; 
- } 
-   
- StringRef AsanDtorKindToString(llvm::AsanDtorKind kind); 
-   
- llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind); 
-   
- StringRef AsanDetectStackUseAfterReturnModeToString( 
-     llvm::AsanDetectStackUseAfterReturnMode mode); 
-   
- llvm::AsanDetectStackUseAfterReturnMode 
- AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr); 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_BASIC_SANITIZERS_H 
-