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 19using 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 29SanitizerMask 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 39void 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 47SanitizerMask 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 56llvm::hash_code SanitizerMask::hash_value() const { 57 return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]); 58} 59 60namespace clang { 61unsigned SanitizerMask::countPopulation() const { 62 unsigned total = 0; 63 for (const auto &Val : maskLoToHigh) 64 total += llvm::popcount(Val); 65 return total; 66} 67 68llvm::hash_code hash_value(const clang::SanitizerMask &Arg) { 69 return Arg.hash_value(); 70} 71 72StringRef 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 84llvm::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 91StringRef 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 106llvm::AsanDetectStackUseAfterReturnMode 107AsanDetectStackUseAfterReturnModeFromString(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