AnalyzerOptions.cpp revision 360784
1//===- AnalyzerOptions.cpp - Analysis Engine 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 contains special accessors for analyzer configuration options 10// with string representations. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 15#include "clang/StaticAnalyzer/Core/Checker.h" 16#include "llvm/ADT/SmallString.h" 17#include "llvm/ADT/StringSwitch.h" 18#include "llvm/ADT/StringRef.h" 19#include "llvm/ADT/Twine.h" 20#include "llvm/Support/ErrorHandling.h" 21#include "llvm/Support/FileSystem.h" 22#include "llvm/Support/FormattedStream.h" 23#include "llvm/Support/raw_ostream.h" 24#include <cassert> 25#include <cstddef> 26#include <utility> 27#include <vector> 28 29using namespace clang; 30using namespace ento; 31using namespace llvm; 32 33void AnalyzerOptions::printFormattedEntry( 34 llvm::raw_ostream &Out, 35 std::pair<StringRef, StringRef> EntryDescPair, 36 size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) { 37 38 llvm::formatted_raw_ostream FOut(Out); 39 40 const size_t PadForDesc = InitialPad + EntryWidth; 41 42 FOut.PadToColumn(InitialPad) << EntryDescPair.first; 43 // If the buffer's length is greater then PadForDesc, print a newline. 44 if (FOut.getColumn() > PadForDesc) 45 FOut << '\n'; 46 47 FOut.PadToColumn(PadForDesc); 48 49 if (MinLineWidth == 0) { 50 FOut << EntryDescPair.second; 51 return; 52 } 53 54 for (char C : EntryDescPair.second) { 55 if (FOut.getColumn() > MinLineWidth && C == ' ') { 56 FOut << '\n'; 57 FOut.PadToColumn(PadForDesc); 58 continue; 59 } 60 FOut << C; 61 } 62} 63 64ExplorationStrategyKind 65AnalyzerOptions::getExplorationStrategy() const { 66 auto K = 67 llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>( 68 ExplorationStrategy) 69 .Case("dfs", ExplorationStrategyKind::DFS) 70 .Case("bfs", ExplorationStrategyKind::BFS) 71 .Case("unexplored_first", 72 ExplorationStrategyKind::UnexploredFirst) 73 .Case("unexplored_first_queue", 74 ExplorationStrategyKind::UnexploredFirstQueue) 75 .Case("unexplored_first_location_queue", 76 ExplorationStrategyKind::UnexploredFirstLocationQueue) 77 .Case("bfs_block_dfs_contents", 78 ExplorationStrategyKind::BFSBlockDFSContents) 79 .Default(None); 80 assert(K.hasValue() && "User mode is invalid."); 81 return K.getValue(); 82} 83 84IPAKind AnalyzerOptions::getIPAMode() const { 85 auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode) 86 .Case("none", IPAK_None) 87 .Case("basic-inlining", IPAK_BasicInlining) 88 .Case("inlining", IPAK_Inlining) 89 .Case("dynamic", IPAK_DynamicDispatch) 90 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 91 .Default(None); 92 assert(K.hasValue() && "IPA Mode is invalid."); 93 94 return K.getValue(); 95} 96 97bool 98AnalyzerOptions::mayInlineCXXMemberFunction( 99 CXXInlineableMemberKind Param) const { 100 if (getIPAMode() < IPAK_Inlining) 101 return false; 102 103 auto K = 104 llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>( 105 CXXMemberInliningMode) 106 .Case("constructors", CIMK_Constructors) 107 .Case("destructors", CIMK_Destructors) 108 .Case("methods", CIMK_MemberFunctions) 109 .Case("none", CIMK_None) 110 .Default(None); 111 112 assert(K.hasValue() && "Invalid c++ member function inlining mode."); 113 114 return *K >= Param; 115} 116 117StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName, 118 StringRef OptionName, 119 bool SearchInParents) const { 120 assert(!CheckerName.empty() && 121 "Empty checker name! Make sure the checker object (including it's " 122 "bases!) if fully initialized before calling this function!"); 123 124 ConfigTable::const_iterator E = Config.end(); 125 do { 126 ConfigTable::const_iterator I = 127 Config.find((Twine(CheckerName) + ":" + OptionName).str()); 128 if (I != E) 129 return StringRef(I->getValue()); 130 size_t Pos = CheckerName.rfind('.'); 131 if (Pos == StringRef::npos) 132 break; 133 134 CheckerName = CheckerName.substr(0, Pos); 135 } while (!CheckerName.empty() && SearchInParents); 136 137 llvm_unreachable("Unknown checker option! Did you call getChecker*Option " 138 "with incorrect parameters? User input must've been " 139 "verified by CheckerRegistry."); 140 141 return ""; 142} 143 144StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C, 145 StringRef OptionName, 146 bool SearchInParents) const { 147 return getCheckerStringOption( 148 C->getTagDescription(), OptionName, SearchInParents); 149} 150 151bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName, 152 StringRef OptionName, 153 bool SearchInParents) const { 154 auto Ret = llvm::StringSwitch<llvm::Optional<bool>>( 155 getCheckerStringOption(CheckerName, OptionName, 156 SearchInParents)) 157 .Case("true", true) 158 .Case("false", false) 159 .Default(None); 160 161 assert(Ret && 162 "This option should be either 'true' or 'false', and should've been " 163 "validated by CheckerRegistry!"); 164 165 return *Ret; 166} 167 168bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C, 169 StringRef OptionName, 170 bool SearchInParents) const { 171 return getCheckerBooleanOption( 172 C->getTagDescription(), OptionName, SearchInParents); 173} 174 175int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName, 176 StringRef OptionName, 177 bool SearchInParents) const { 178 int Ret = 0; 179 bool HasFailed = getCheckerStringOption(CheckerName, OptionName, 180 SearchInParents) 181 .getAsInteger(0, Ret); 182 assert(!HasFailed && 183 "This option should be numeric, and should've been validated by " 184 "CheckerRegistry!"); 185 (void)HasFailed; 186 return Ret; 187} 188 189int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C, 190 StringRef OptionName, 191 bool SearchInParents) const { 192 return getCheckerIntegerOption( 193 C->getTagDescription(), OptionName, SearchInParents); 194} 195