Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:50

0001 //===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// \file
0010 /// Defines the clang::SanitizerKind enum.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_BASIC_SANITIZERS_H
0015 #define LLVM_CLANG_BASIC_SANITIZERS_H
0016 
0017 #include "clang/Basic/LLVM.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/Support/HashBuilder.h"
0020 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
0021 #include <cassert>
0022 #include <cstdint>
0023 
0024 namespace llvm {
0025 class hash_code;
0026 class Triple;
0027 namespace opt {
0028 class ArgList;
0029 }
0030 } // namespace llvm
0031 
0032 namespace clang {
0033 
0034 class SanitizerMask {
0035   // NOTE: this class assumes kNumElem == 2 in most of the constexpr functions,
0036   // in order to work within the C++11 constexpr function constraints. If you
0037   // change kNumElem, you'll need to update those member functions as well.
0038 
0039   /// Number of array elements.
0040   static constexpr unsigned kNumElem = 2;
0041   /// Mask value initialized to 0.
0042   uint64_t maskLoToHigh[kNumElem]{};
0043   /// Number of bits in a mask.
0044   static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
0045   /// Number of bits in a mask element.
0046   static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
0047 
0048   constexpr SanitizerMask(uint64_t mask1, uint64_t mask2)
0049       : maskLoToHigh{mask1, mask2} {}
0050 
0051 public:
0052   SanitizerMask() = default;
0053 
0054   static constexpr bool checkBitPos(const unsigned Pos) {
0055     return Pos < kNumBits;
0056   }
0057 
0058   /// Create a mask with a bit enabled at position Pos.
0059   static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
0060     uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
0061     uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
0062                          ? 1ULL << (Pos % kNumBitElem)
0063                          : 0;
0064     return SanitizerMask(mask1, mask2);
0065   }
0066 
0067   unsigned countPopulation() const;
0068 
0069   void flipAllBits() {
0070     for (auto &Val : maskLoToHigh)
0071       Val = ~Val;
0072   }
0073 
0074   bool isPowerOf2() const {
0075     return countPopulation() == 1;
0076   }
0077 
0078   llvm::hash_code hash_value() const;
0079 
0080   template <typename HasherT, llvm::endianness Endianness>
0081   friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
0082                       const SanitizerMask &SM) {
0083     HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]);
0084   }
0085 
0086   constexpr explicit operator bool() const {
0087     return maskLoToHigh[0] || maskLoToHigh[1];
0088   }
0089 
0090   constexpr bool operator==(const SanitizerMask &V) const {
0091     return maskLoToHigh[0] == V.maskLoToHigh[0] &&
0092            maskLoToHigh[1] == V.maskLoToHigh[1];
0093   }
0094 
0095   SanitizerMask &operator&=(const SanitizerMask &RHS) {
0096     for (unsigned k = 0; k < kNumElem; k++)
0097       maskLoToHigh[k] &= RHS.maskLoToHigh[k];
0098     return *this;
0099   }
0100 
0101   SanitizerMask &operator|=(const SanitizerMask &RHS) {
0102     for (unsigned k = 0; k < kNumElem; k++)
0103       maskLoToHigh[k] |= RHS.maskLoToHigh[k];
0104     return *this;
0105   }
0106 
0107   constexpr bool operator!() const { return !bool(*this); }
0108 
0109   constexpr bool operator!=(const SanitizerMask &RHS) const {
0110     return !((*this) == RHS);
0111   }
0112 
0113   friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
0114     return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
0115   }
0116 
0117   friend constexpr inline SanitizerMask operator&(SanitizerMask a,
0118                                                   const SanitizerMask &b) {
0119     return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
0120                          a.maskLoToHigh[1] & b.maskLoToHigh[1]);
0121   }
0122 
0123   friend constexpr inline SanitizerMask operator|(SanitizerMask a,
0124                                                   const SanitizerMask &b) {
0125     return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
0126                          a.maskLoToHigh[1] | b.maskLoToHigh[1]);
0127   }
0128 };
0129 
0130 // Declaring in clang namespace so that it can be found by ADL.
0131 llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
0132 
0133 // Define the set of sanitizer kinds, as well as the set of sanitizers each
0134 // sanitizer group expands into.
0135 struct SanitizerKind {
0136   // Assign ordinals to possible values of -fsanitize= flag, which we will use
0137   // as bit positions.
0138   enum SanitizerOrdinal : uint64_t {
0139 #define SANITIZER(NAME, ID) SO_##ID,
0140 #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
0141 #include "clang/Basic/Sanitizers.def"
0142     SO_Count
0143   };
0144 
0145 #define SANITIZER(NAME, ID)                                                    \
0146   static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \
0147   static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
0148 #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
0149   static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \
0150   static constexpr SanitizerMask ID##Group =                                   \
0151       SanitizerMask::bitPosToMask(SO_##ID##Group);                             \
0152   static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
0153                 "Bit position too big.");
0154 #include "clang/Basic/Sanitizers.def"
0155 }; // SanitizerKind
0156 
0157 class SanitizerMaskCutoffs {
0158   std::vector<double> Cutoffs;
0159 
0160 public:
0161   std::optional<double> operator[](unsigned Kind) const;
0162 
0163   void set(SanitizerMask K, double V);
0164   void clear(SanitizerMask K = SanitizerKind::All);
0165 };
0166 
0167 struct SanitizerSet {
0168   /// Check if a certain (single) sanitizer is enabled.
0169   bool has(SanitizerMask K) const {
0170     assert(K.isPowerOf2() && "Has to be a single sanitizer.");
0171     return static_cast<bool>(Mask & K);
0172   }
0173 
0174   bool has(SanitizerKind::SanitizerOrdinal O) const {
0175     return has(SanitizerMask::bitPosToMask(O));
0176   }
0177 
0178   /// Check if one or more sanitizers are enabled.
0179   bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
0180 
0181   /// Enable or disable a certain (single) sanitizer.
0182   void set(SanitizerMask K, bool Value) {
0183     assert(K.isPowerOf2() && "Has to be a single sanitizer.");
0184     Mask = Value ? (Mask | K) : (Mask & ~K);
0185   }
0186 
0187   void set(SanitizerMask K) { Mask = K; }
0188 
0189   /// Disable the sanitizers specified in \p K.
0190   void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
0191 
0192   /// Returns true if no sanitizers are enabled.
0193   bool empty() const { return !Mask; }
0194 
0195   /// Bitmask of enabled sanitizers.
0196   SanitizerMask Mask;
0197 };
0198 
0199 /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
0200 /// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
0201 SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
0202 
0203 /// Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or
0204 /// -fno-sanitize= value list.
0205 /// The relevant weight(s) are updated in the passed Cutoffs parameter.
0206 /// Individual Cutoffs are never reset to zero unless explicitly set
0207 /// (e.g., 'null=0.0').
0208 /// Returns \c false if \p Value is not known or the weight is not valid.
0209 bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
0210                                  SanitizerMaskCutoffs &Cutoffs);
0211 
0212 /// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
0213 void serializeSanitizerSet(SanitizerSet Set,
0214                            SmallVectorImpl<StringRef> &Values);
0215 
0216 /// Serialize a SanitizerMaskCutoffs into values for -fsanitize= or
0217 /// -fno-sanitize=.
0218 void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs,
0219                                    SmallVectorImpl<std::string> &Values);
0220 
0221 /// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
0222 /// this group enables.
0223 SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
0224 
0225 /// Return the sanitizers which do not affect preprocessing.
0226 inline SanitizerMask getPPTransparentSanitizers() {
0227   return SanitizerKind::CFI | SanitizerKind::Integer |
0228          SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
0229          SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
0230 }
0231 
0232 StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
0233 
0234 llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
0235 
0236 StringRef AsanDetectStackUseAfterReturnModeToString(
0237     llvm::AsanDetectStackUseAfterReturnMode mode);
0238 
0239 llvm::AsanDetectStackUseAfterReturnMode
0240 AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
0241 
0242 } // namespace clang
0243 
0244 #endif // LLVM_CLANG_BASIC_SANITIZERS_H