diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer')
12 files changed, 106 insertions, 140 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp index cc306329dc1..f9cf97e5083 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp @@ -45,8 +45,8 @@ class AnalysisOrderChecker check::LiveSymbols> { bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const { - return Opts.getBooleanOption("*", false, this) || - Opts.getBooleanOption(CallbackName, false, this); + return Opts.getCheckerBooleanOption("*", false, this) || + Opts.getCheckerBooleanOption(CallbackName, false, this); } bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { diff --git a/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp index ee517ed9777..309a29b2a45 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp @@ -63,18 +63,18 @@ void CloneChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU, // At this point, every statement in the translation unit has been analyzed by // the CloneDetector. The only thing left to do is to report the found clones. - int MinComplexity = Mgr.getAnalyzerOptions().getOptionAsInteger( + int MinComplexity = Mgr.getAnalyzerOptions().getCheckerIntegerOption( "MinimumCloneComplexity", 50, this); assert(MinComplexity >= 0); - bool ReportSuspiciousClones = Mgr.getAnalyzerOptions().getBooleanOption( - "ReportSuspiciousClones", true, this); + bool ReportSuspiciousClones = Mgr.getAnalyzerOptions() + .getCheckerBooleanOption("ReportSuspiciousClones", true, this); - bool ReportNormalClones = Mgr.getAnalyzerOptions().getBooleanOption( + bool ReportNormalClones = Mgr.getAnalyzerOptions().getCheckerBooleanOption( "ReportNormalClones", true, this); - StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions().getOptionAsString( - "IgnoredFilesPattern", "", this); + StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions() + .getCheckerStringOption("IgnoredFilesPattern", "", this); // Let the CloneDetector create a list of clones from all the analyzed // statements. We don't filter for matching variable patterns at this point diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index ec05c737ac2..103a33d39f9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -1398,8 +1398,8 @@ void ento::registerNonLocalizedStringChecker(CheckerManager &mgr) { NonLocalizedStringChecker *checker = mgr.registerChecker<NonLocalizedStringChecker>(); checker->IsAggressive = - mgr.getAnalyzerOptions().getBooleanOption("AggressiveReport", false, - checker); + mgr.getAnalyzerOptions().getCheckerBooleanOption("AggressiveReport", + false, checker); } void ento::registerEmptyLocalizationContextChecker(CheckerManager &mgr) { diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index fbd8a9d4d87..07483cd4714 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3084,7 +3084,7 @@ markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) { void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) { registerCStringCheckerBasic(mgr); MallocChecker *checker = mgr.registerChecker<MallocChecker>(); - checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( + checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( "Optimistic", false, checker); checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true; checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] = @@ -3105,7 +3105,7 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) { void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) { registerCStringCheckerBasic(mgr); MallocChecker *checker = mgr.registerChecker<MallocChecker>(); - checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( + checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( "Optimistic", false, checker); checker->ChecksEnabled[MallocChecker::CK_InnerPointerChecker] = true; checker->CheckNames[MallocChecker::CK_InnerPointerChecker] = @@ -3116,7 +3116,7 @@ void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) { void ento::register##name(CheckerManager &mgr) { \ registerCStringCheckerBasic(mgr); \ MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \ - checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \ + checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( \ "Optimistic", false, checker); \ checker->ChecksEnabled[MallocChecker::CK_##name] = true; \ checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \ diff --git a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp index 5060b0e0a6e..0d63cfe9376 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -82,7 +82,9 @@ void ento::registerMmapWriteExecChecker(CheckerManager &mgr) { MmapWriteExecChecker *Mwec = mgr.registerChecker<MmapWriteExecChecker>(); Mwec->ProtExecOv = - mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtExec", 0x04, Mwec); + mgr.getAnalyzerOptions() + .getCheckerIntegerOption("MmapProtExec", 0x04, Mwec); Mwec->ProtReadOv = - mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtRead", 0x01, Mwec); + mgr.getAnalyzerOptions() + .getCheckerIntegerOption("MmapProtRead", 0x01, Mwec); } diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index ad68dc2f49d..6345c6aac5d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -1193,7 +1193,7 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State, checker->NeedTracking = checker->NeedTracking || trackingRequired; \ checker->NoDiagnoseCallsToSystemHeaders = \ checker->NoDiagnoseCallsToSystemHeaders || \ - mgr.getAnalyzerOptions().getBooleanOption( \ + mgr.getAnalyzerOptions().getCheckerBooleanOption( \ "NoDiagnoseCallsToSystemHeaders", false, checker, true); \ } diff --git a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp index 56b42239d7c..d342bd072a4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp @@ -346,5 +346,5 @@ void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) { NumberObjectConversionChecker *Chk = Mgr.registerChecker<NumberObjectConversionChecker>(); Chk->Pedantic = - Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk); + Mgr.getAnalyzerOptions().getCheckerBooleanOption("Pedantic", false, Chk); } diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 04164a97569..dc361ad537a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -41,7 +41,8 @@ public: BugReporter &BRArg) const { BR = &BRArg; AllowedPad = - MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this); + MGR.getAnalyzerOptions() + .getCheckerIntegerOption("AllowedPad", 24, this); assert(AllowedPad >= 0 && "AllowedPad option should be non-negative"); // The calls to checkAST* from AnalysisConsumer don't diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index 89d3795b1b0..c75a7b046b9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -1397,8 +1397,8 @@ void ento::registerRetainCountChecker(CheckerManager &Mgr) { AnalyzerOptions &Options = Mgr.getAnalyzerOptions(); - Chk->IncludeAllocationLine = Options.getBooleanOption( + Chk->IncludeAllocationLine = Options.getCheckerBooleanOption( "leak-diagnostics-reference-allocation", false, Chk); - Chk->ShouldCheckOSObjectRetainCount = Options.getBooleanOption( - "CheckOSObject", true, Chk); + Chk->ShouldCheckOSObjectRetainCount = Options.getCheckerBooleanOption( + "CheckOSObject", true, Chk); } diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index d31d3a21121..e4a17a9dd28 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -488,12 +488,12 @@ void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { UninitObjCheckerOptions &ChOpts = Chk->Opts; ChOpts.IsPedantic = - AnOpts.getBooleanOption("Pedantic", /*DefaultVal*/ false, Chk); + AnOpts.getCheckerBooleanOption("Pedantic", /*DefaultVal*/ false, Chk); ChOpts.ShouldConvertNotesToWarnings = - AnOpts.getBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk); - ChOpts.CheckPointeeInitialization = AnOpts.getBooleanOption( + AnOpts.getCheckerBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk); + ChOpts.CheckPointeeInitialization = AnOpts.getCheckerBooleanOption( "CheckPointeeInitialization", /*DefaultVal*/ false, Chk); ChOpts.IgnoredRecordsWithFieldPattern = - AnOpts.getOptionAsString("IgnoreRecordsWithField", + AnOpts.getCheckerStringOption("IgnoreRecordsWithField", /*DefaultVal*/ "", Chk); } diff --git a/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp index cf673de6d47..902b325dec8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -280,5 +280,6 @@ void ento::registerVirtualCallChecker(CheckerManager &mgr) { VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>(); checker->IsPureOnly = - mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false, checker); + mgr.getAnalyzerOptions().getCheckerBooleanOption("PureOnly", false, + checker); } diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 0700bd08959..37bbcb4219f 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -51,7 +51,7 @@ AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) { UserModeKind AnalyzerOptions::getUserMode() { if (!UserMode.hasValue()) { - UserMode = getOptionAsString("mode", "deep"); + UserMode = getStringOption("mode", "deep"); } auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(*UserMode) @@ -65,7 +65,7 @@ UserModeKind AnalyzerOptions::getUserMode() { ExplorationStrategyKind AnalyzerOptions::getExplorationStrategy() { if (!ExplorationStrategy.hasValue()) { - ExplorationStrategy = getOptionAsString("exploration_strategy", + ExplorationStrategy = getStringOption("exploration_strategy", "unexplored_first_queue"); } auto K = @@ -90,10 +90,10 @@ IPAKind AnalyzerOptions::getIPAMode() { if (!IPAMode.hasValue()) { switch (getUserMode()) { case UMK_Shallow: - IPAMode = getOptionAsString("ipa", "inlining"); + IPAMode = getStringOption("ipa", "inlining"); break; case UMK_Deep: - IPAMode = getOptionAsString("ipa", "dynamic-bifurcate"); + IPAMode = getStringOption("ipa", "dynamic-bifurcate"); break; } } @@ -112,7 +112,7 @@ IPAKind AnalyzerOptions::getIPAMode() { bool AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) { if (!CXXMemberInliningMode.hasValue()) { - CXXMemberInliningMode = getOptionAsString("c++-inlining", "destructors"); + CXXMemberInliningMode = getStringOption("c++-inlining", "destructors"); } if (getIPAMode() < IPAK_Inlining) @@ -132,14 +132,62 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) { return *K >= Param; } -static StringRef toString(bool b) { return b ? "true" : "false"; } +StringRef AnalyzerOptions::getStringOption(StringRef OptionName, + StringRef DefaultVal) { + return Config.insert({OptionName, DefaultVal}).first->second; +} + +static StringRef toString(bool B) { return (B ? "true" : "false"); } + +template <typename T> +static StringRef toString(T) = delete; + +void AnalyzerOptions::initOption(Optional<StringRef> &V, StringRef Name, + StringRef DefaultVal) { + if (V.hasValue()) + return; + + V = getStringOption(Name, DefaultVal); +} -StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName, - StringRef OptionName, - StringRef Default, - bool SearchInParents) { +void AnalyzerOptions::initOption(Optional<bool> &V, StringRef Name, + bool DefaultVal) { + if (V.hasValue()) + return; + + // FIXME: We should emit a warning here if the value is something other than + // "true", "false", or the empty string (meaning the default value), + // but the AnalyzerOptions doesn't have access to a diagnostic engine. + V = llvm::StringSwitch<bool>(getStringOption(Name, toString(DefaultVal))) + .Case("true", true) + .Case("false", false) + .Default(DefaultVal); +} + +void AnalyzerOptions::initOption(Optional<unsigned> &V, StringRef Name, + unsigned DefaultVal) { + if (V.hasValue()) + return; + + V = DefaultVal; + bool HasFailed = getStringOption(Name, std::to_string(DefaultVal)) + .getAsInteger(10, *V); + assert(!HasFailed && "analyzer-config option should be numeric"); + (void)HasFailed; +} + +StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName, + StringRef DefaultVal, + const CheckerBase *C, + bool SearchInParents) const { + assert(C); // Search for a package option if the option for the checker is not specified // and search in parents is enabled. + StringRef CheckerName = C->getTagDescription(); + + assert(!CheckerName.empty() && + "Empty checker name! Make sure the checker object (including it's " + "bases!) if fully initialized before calling this function!"); ConfigTable::const_iterator E = Config.end(); do { ConfigTable::const_iterator I = @@ -148,127 +196,41 @@ StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName, return StringRef(I->getValue()); size_t Pos = CheckerName.rfind('.'); if (Pos == StringRef::npos) - return Default; + return DefaultVal; CheckerName = CheckerName.substr(0, Pos); } while (!CheckerName.empty() && SearchInParents); - return Default; + return DefaultVal; } -bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal, - const CheckerBase *C, - bool SearchInParents) { +bool AnalyzerOptions::getCheckerBooleanOption(StringRef Name, bool DefaultVal, + const CheckerBase *C, + bool SearchInParents) const { // FIXME: We should emit a warning here if the value is something other than // "true", "false", or the empty string (meaning the default value), // but the AnalyzerOptions doesn't have access to a diagnostic engine. - StringRef Default = toString(DefaultVal); - StringRef V = - C ? getCheckerOption(C->getTagDescription(), Name, Default, - SearchInParents) - : getOptionAsString(Name, Default); - return llvm::StringSwitch<bool>(V) + assert(C); + return llvm::StringSwitch<bool>( + getCheckerStringOption(Name, toString(DefaultVal), C, SearchInParents)) .Case("true", true) .Case("false", false) .Default(DefaultVal); } -bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name, - bool DefaultVal, const CheckerBase *C, - bool SearchInParents) { - if (!V.hasValue()) - V = getBooleanOption(Name, DefaultVal, C, SearchInParents); - return V.getValue(); -} - -int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal, +int AnalyzerOptions::getCheckerIntegerOption(StringRef Name, int DefaultVal, const CheckerBase *C, - bool SearchInParents) { - SmallString<10> StrBuf; - llvm::raw_svector_ostream OS(StrBuf); - OS << DefaultVal; - - StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(), - SearchInParents) - : getOptionAsString(Name, OS.str()); - - int Res = DefaultVal; - bool b = V.getAsInteger(10, Res); - assert(!b && "analyzer-config option should be numeric"); - (void)b; - return Res; -} - -unsigned AnalyzerOptions::getOptionAsUInt(Optional<unsigned> &V, StringRef Name, - unsigned DefaultVal, - const CheckerBase *C, - bool SearchInParents) { - if (!V.hasValue()) - V = getOptionAsInteger(Name, DefaultVal, C, SearchInParents); - return V.getValue(); -} - -StringRef AnalyzerOptions::getOptionAsString(StringRef Name, - StringRef DefaultVal, - const CheckerBase *C, - bool SearchInParents) { - return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal, - SearchInParents) - : StringRef( - Config.insert(std::make_pair(Name, DefaultVal)).first->second); -} - -StringRef AnalyzerOptions::getOptionAsString(Optional<StringRef> &V, - StringRef Name, - StringRef DefaultVal, - const ento::CheckerBase *C, - bool SearchInParents) { - if (!V.hasValue()) - V = getOptionAsString(Name, DefaultVal, C, SearchInParents); - return V.getValue(); -} - -static bool getOption(AnalyzerOptions &A, Optional<bool> &V, StringRef Name, - bool DefaultVal) { - return A.getBooleanOption(V, Name, DefaultVal); + bool SearchInParents) const { + int Ret = DefaultVal; + bool HasFailed = getCheckerStringOption(Name, std::to_string(DefaultVal), C, + SearchInParents) + .getAsInteger(10, Ret); + assert(!HasFailed && "analyzer-config option should be numeric"); + (void)HasFailed; + return Ret; } -static unsigned getOption(AnalyzerOptions &A, Optional<unsigned> &V, - StringRef Name, unsigned DefaultVal) { - return A.getOptionAsUInt(V, Name, DefaultVal); -} - -static StringRef getOption(AnalyzerOptions &A, Optional<StringRef> &V, - StringRef Name, StringRef DefaultVal) { - return A.getOptionAsString(V, Name, DefaultVal); -} - -#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL, \ - CREATE_FN) \ -TYPE AnalyzerOptions::CREATE_FN() { \ - return getOption(*this, NAME, CMDFLAG, DEFAULT_VAL); \ -} - -#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE( \ - TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN) \ -TYPE AnalyzerOptions::CREATE_FN() { \ - switch (getUserMode()) { \ - case UMK_Shallow: \ - return getOption(*this, NAME, CMDFLAG, SHALLOW_VAL); \ - case UMK_Deep: \ - return getOption(*this, NAME, CMDFLAG, DEEP_VAL); \ - } \ - \ - llvm_unreachable("Unknown usermode!"); \ - return {}; \ -} - -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" - -#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE -#undef ANALYZER_OPTION_WITH_FN - StringRef AnalyzerOptions::getCTUDir() { if (!CTUDir.hasValue()) { - CTUDir = getOptionAsString("ctu-dir", ""); + CTUDir = getStringOption("ctu-dir", ""); if (!llvm::sys::fs::is_directory(*CTUDir)) CTUDir = ""; } |