1 //===- Sanitizers.cpp - C Language Family Language Options ----------------===// 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 // This file defines the classes from Sanitizers.h 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Basic/Sanitizers.h" 14 #include "llvm/ADT/Hashing.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringSwitch.h" 17 #include "llvm/Support/MathExtras.h" 18 19 using namespace clang; 20 21 // Once LLVM switches to C++17, the constexpr variables can be inline and we 22 // won't need this. 23 #define SANITIZER(NAME, ID) constexpr SanitizerMask SanitizerKind::ID; 24 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 25 constexpr SanitizerMask SanitizerKind::ID; \ 26 constexpr SanitizerMask SanitizerKind::ID##Group; 27 #include "clang/Basic/Sanitizers.def" 28 29 SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) { 30 SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value) 31 #define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID) 32 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 33 .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : SanitizerMask()) 34 #include "clang/Basic/Sanitizers.def" 35 .Default(SanitizerMask()); 36 return ParsedKind; 37 } 38 39 void clang::serializeSanitizerSet(SanitizerSet Set, 40 SmallVectorImpl<StringRef> &Values) { 41 #define SANITIZER(NAME, ID) \ 42 if (Set.has(SanitizerKind::ID)) \ 43 Values.push_back(NAME); 44 #include "clang/Basic/Sanitizers.def" 45 } 46 47 SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) { 48 #define SANITIZER(NAME, ID) 49 #define SANITIZER_GROUP(NAME, ID, ALIAS) \ 50 if (Kinds & SanitizerKind::ID##Group) \ 51 Kinds |= SanitizerKind::ID; 52 #include "clang/Basic/Sanitizers.def" 53 return Kinds; 54 } 55 56 llvm::hash_code SanitizerMask::hash_value() const { 57 return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]); 58 } 59 60 namespace clang { 61 unsigned SanitizerMask::countPopulation() const { 62 unsigned total = 0; 63 for (const auto &Val : maskLoToHigh) 64 total += llvm::countPopulation(Val); 65 return total; 66 } 67 68 llvm::hash_code hash_value(const clang::SanitizerMask &Arg) { 69 return Arg.hash_value(); 70 } 71 72 StringRef AsanDtorKindToString(llvm::AsanDtorKind kind) { 73 switch (kind) { 74 case llvm::AsanDtorKind::None: 75 return "none"; 76 case llvm::AsanDtorKind::Global: 77 return "global"; 78 case llvm::AsanDtorKind::Invalid: 79 return "invalid"; 80 } 81 return "invalid"; 82 } 83 84 llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) { 85 return llvm::StringSwitch<llvm::AsanDtorKind>(kindStr) 86 .Case("none", llvm::AsanDtorKind::None) 87 .Case("global", llvm::AsanDtorKind::Global) 88 .Default(llvm::AsanDtorKind::Invalid); 89 } 90 91 StringRef AsanDetectStackUseAfterReturnModeToString( 92 llvm::AsanDetectStackUseAfterReturnMode mode) { 93 switch (mode) { 94 case llvm::AsanDetectStackUseAfterReturnMode::Always: 95 return "always"; 96 case llvm::AsanDetectStackUseAfterReturnMode::Runtime: 97 return "runtime"; 98 case llvm::AsanDetectStackUseAfterReturnMode::Never: 99 return "never"; 100 case llvm::AsanDetectStackUseAfterReturnMode::Invalid: 101 return "invalid"; 102 } 103 return "invalid"; 104 } 105 106 llvm::AsanDetectStackUseAfterReturnMode 107 AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr) { 108 return llvm::StringSwitch<llvm::AsanDetectStackUseAfterReturnMode>(modeStr) 109 .Case("always", llvm::AsanDetectStackUseAfterReturnMode::Always) 110 .Case("runtime", llvm::AsanDetectStackUseAfterReturnMode::Runtime) 111 .Case("never", llvm::AsanDetectStackUseAfterReturnMode::Never) 112 .Default(llvm::AsanDetectStackUseAfterReturnMode::Invalid); 113 } 114 115 } // namespace clang 116