Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -27,6 +27,9 @@ class DiagnosticsEngine; class Preprocessor; class LangOptions; +namespace ento { +class CheckerBase; +} /// Analysis - Set of available source code analyses. enum Analyses { @@ -245,18 +248,25 @@ /// \sa getMaxNodesPerTopLevelFunction Optional MaxNodesPerTopLevelFunction; + StringRef getCheckerOption(const StringRef &CheckerName, + const StringRef &OptionName, + const StringRef &Default) const; + public: /// Interprets an option's string value as a boolean. /// /// Accepts the strings "true" and "false". /// If an option value is not provided, returns the given \p DefaultVal. - bool getBooleanOption(StringRef Name, bool DefaultVal); + bool getBooleanOption(StringRef Name, bool DefaultVal, + const ento::CheckerBase *C = nullptr); /// Variant that accepts a Optional value to cache the result. - bool getBooleanOption(Optional &V, StringRef Name, bool DefaultVal); + bool getBooleanOption(Optional &V, StringRef Name, bool DefaultVal, + const ento::CheckerBase *C = nullptr); /// Interprets an option's string value as an integer value. - int getOptionAsInteger(StringRef Name, int DefaultVal); + int getOptionAsInteger(StringRef Name, int DefaultVal, + const ento::CheckerBase *C = nullptr); /// \brief Retrieves and sets the UserMode. This is a high-level option, /// which is used to set other low-level options. It is not accessible Index: lib/StaticAnalyzer/Core/AnalyzerOptions.cpp =================================================================== --- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -13,12 +13,14 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; +using namespace ento; using namespace llvm; AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { @@ -98,11 +100,33 @@ static StringRef toString(bool b) { return b ? "true" : "false"; } -bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) { +StringRef AnalyzerOptions::getCheckerOption(const StringRef &CheckerName, + const StringRef &OptionName, + const StringRef &Default) const { + std::string Name = CheckerName; + std::string Suffix = ":" + OptionName.str(); + // Search for a category option if option for checker is not specified + ConfigTable::const_iterator e = Config.end(); + while (!Name.empty()) { + ConfigTable::const_iterator i = Config.find(Name + Suffix); + if (i != e) + return StringRef(i->getValue()); + size_t pos = Name.rfind('.'); + if (pos == std::string::npos) + return Default; + Name = Name.substr(0, pos); + } + return Default; +} + +bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal, + const CheckerBase *C) { // 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 V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue()); + StringRef Default = toString(DefaultVal); + StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, Default) + : StringRef(Config.GetOrCreateValue(Name,Default).getValue()); return llvm::StringSwitch(V) .Case("true", true) .Case("false", false) @@ -110,9 +134,9 @@ } bool AnalyzerOptions::getBooleanOption(Optional &V, StringRef Name, - bool DefaultVal) { + bool DefaultVal, const CheckerBase *C) { if (!V.hasValue()) - V = getBooleanOption(Name, DefaultVal); + V = getBooleanOption(Name, DefaultVal, C); return V.getValue(); } @@ -196,12 +220,14 @@ /* Default = */ false); } -int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { +int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal, + const CheckerBase *C) { SmallString<10> StrBuf; llvm::raw_svector_ostream OS(StrBuf); OS << DefaultVal; - StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); + StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str()) + : StringRef(Config.GetOrCreateValue(Name,OS.str()).getValue()); int Res = DefaultVal; bool b = V.getAsInteger(10, Res); assert(!b && "analyzer-config option should be numeric");