Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. /// \file
  10. /// Defines the clang::SanitizerKind enum.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_BASIC_SANITIZERS_H
  15. #define LLVM_CLANG_BASIC_SANITIZERS_H
  16.  
  17. #include "clang/Basic/LLVM.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Support/HashBuilder.h"
  20. #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
  21. #include <cassert>
  22. #include <cstdint>
  23.  
  24. namespace llvm {
  25. class hash_code;
  26. }
  27.  
  28. namespace clang {
  29.  
  30. class SanitizerMask {
  31.   // NOTE: this class assumes kNumElem == 2 in most of the constexpr functions,
  32.   // in order to work within the C++11 constexpr function constraints. If you
  33.   // change kNumElem, you'll need to update those member functions as well.
  34.  
  35.   /// Number of array elements.
  36.   static constexpr unsigned kNumElem = 2;
  37.   /// Mask value initialized to 0.
  38.   uint64_t maskLoToHigh[kNumElem]{};
  39.   /// Number of bits in a mask.
  40.   static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
  41.   /// Number of bits in a mask element.
  42.   static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
  43.  
  44.   constexpr SanitizerMask(uint64_t mask1, uint64_t mask2)
  45.       : maskLoToHigh{mask1, mask2} {}
  46.  
  47. public:
  48.   SanitizerMask() = default;
  49.  
  50.   static constexpr bool checkBitPos(const unsigned Pos) {
  51.     return Pos < kNumBits;
  52.   }
  53.  
  54.   /// Create a mask with a bit enabled at position Pos.
  55.   static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
  56.     uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
  57.     uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
  58.                          ? 1ULL << (Pos % kNumBitElem)
  59.                          : 0;
  60.     return SanitizerMask(mask1, mask2);
  61.   }
  62.  
  63.   unsigned countPopulation() const;
  64.  
  65.   void flipAllBits() {
  66.     for (auto &Val : maskLoToHigh)
  67.       Val = ~Val;
  68.   }
  69.  
  70.   bool isPowerOf2() const {
  71.     return countPopulation() == 1;
  72.   }
  73.  
  74.   llvm::hash_code hash_value() const;
  75.  
  76.   template <typename HasherT, llvm::support::endianness Endianness>
  77.   friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
  78.                       const SanitizerMask &SM) {
  79.     HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]);
  80.   }
  81.  
  82.   constexpr explicit operator bool() const {
  83.     return maskLoToHigh[0] || maskLoToHigh[1];
  84.   }
  85.  
  86.   constexpr bool operator==(const SanitizerMask &V) const {
  87.     return maskLoToHigh[0] == V.maskLoToHigh[0] &&
  88.            maskLoToHigh[1] == V.maskLoToHigh[1];
  89.   }
  90.  
  91.   SanitizerMask &operator&=(const SanitizerMask &RHS) {
  92.     for (unsigned k = 0; k < kNumElem; k++)
  93.       maskLoToHigh[k] &= RHS.maskLoToHigh[k];
  94.     return *this;
  95.   }
  96.  
  97.   SanitizerMask &operator|=(const SanitizerMask &RHS) {
  98.     for (unsigned k = 0; k < kNumElem; k++)
  99.       maskLoToHigh[k] |= RHS.maskLoToHigh[k];
  100.     return *this;
  101.   }
  102.  
  103.   constexpr bool operator!() const { return !bool(*this); }
  104.  
  105.   constexpr bool operator!=(const SanitizerMask &RHS) const {
  106.     return !((*this) == RHS);
  107.   }
  108.  
  109.   friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
  110.     return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
  111.   }
  112.  
  113.   friend constexpr inline SanitizerMask operator&(SanitizerMask a,
  114.                                                   const SanitizerMask &b) {
  115.     return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
  116.                          a.maskLoToHigh[1] & b.maskLoToHigh[1]);
  117.   }
  118.  
  119.   friend constexpr inline SanitizerMask operator|(SanitizerMask a,
  120.                                                   const SanitizerMask &b) {
  121.     return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
  122.                          a.maskLoToHigh[1] | b.maskLoToHigh[1]);
  123.   }
  124. };
  125.  
  126. // Declaring in clang namespace so that it can be found by ADL.
  127. llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
  128.  
  129. // Define the set of sanitizer kinds, as well as the set of sanitizers each
  130. // sanitizer group expands into.
  131. struct SanitizerKind {
  132.   // Assign ordinals to possible values of -fsanitize= flag, which we will use
  133.   // as bit positions.
  134.   enum SanitizerOrdinal : uint64_t {
  135. #define SANITIZER(NAME, ID) SO_##ID,
  136. #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
  137. #include "clang/Basic/Sanitizers.def"
  138.     SO_Count
  139.   };
  140.  
  141. #define SANITIZER(NAME, ID)                                                    \
  142.   static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \
  143.   static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
  144. #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
  145.   static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \
  146.   static constexpr SanitizerMask ID##Group =                                   \
  147.       SanitizerMask::bitPosToMask(SO_##ID##Group);                             \
  148.   static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
  149.                 "Bit position too big.");
  150. #include "clang/Basic/Sanitizers.def"
  151. }; // SanitizerKind
  152.  
  153. struct SanitizerSet {
  154.   /// Check if a certain (single) sanitizer is enabled.
  155.   bool has(SanitizerMask K) const {
  156.     assert(K.isPowerOf2() && "Has to be a single sanitizer.");
  157.     return static_cast<bool>(Mask & K);
  158.   }
  159.  
  160.   /// Check if one or more sanitizers are enabled.
  161.   bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
  162.  
  163.   /// Enable or disable a certain (single) sanitizer.
  164.   void set(SanitizerMask K, bool Value) {
  165.     assert(K.isPowerOf2() && "Has to be a single sanitizer.");
  166.     Mask = Value ? (Mask | K) : (Mask & ~K);
  167.   }
  168.  
  169.   /// Disable the sanitizers specified in \p K.
  170.   void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
  171.  
  172.   /// Returns true if no sanitizers are enabled.
  173.   bool empty() const { return !Mask; }
  174.  
  175.   /// Bitmask of enabled sanitizers.
  176.   SanitizerMask Mask;
  177. };
  178.  
  179. /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
  180. /// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
  181. SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
  182.  
  183. /// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
  184. void serializeSanitizerSet(SanitizerSet Set,
  185.                            SmallVectorImpl<StringRef> &Values);
  186.  
  187. /// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
  188. /// this group enables.
  189. SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
  190.  
  191. /// Return the sanitizers which do not affect preprocessing.
  192. inline SanitizerMask getPPTransparentSanitizers() {
  193.   return SanitizerKind::CFI | SanitizerKind::Integer |
  194.          SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
  195.          SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
  196. }
  197.  
  198. StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
  199.  
  200. llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
  201.  
  202. StringRef AsanDetectStackUseAfterReturnModeToString(
  203.     llvm::AsanDetectStackUseAfterReturnMode mode);
  204.  
  205. llvm::AsanDetectStackUseAfterReturnMode
  206. AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
  207.  
  208. } // namespace clang
  209.  
  210. #endif // LLVM_CLANG_BASIC_SANITIZERS_H
  211.