Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -117,6 +117,12 @@ def err_drv_optimization_remark_pattern : Error< "%0 in '%1'">; +def warn_analyzer_config_incorrect_checker_option_section_count : Warning< + "analyzer-config option '%0' should have three sections but has %1; ignoring">, + InGroup; +def warn_analyzer_config_incorrect_checker_option_empty : Warning< + "analyzer-config option '%0' should have first non-empty option; ignoring">, + InGroup; def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">, InGroup; Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -103,6 +103,11 @@ def analyzer_disable_checker_EQ : Joined<["-"], "analyzer-disable-checker=">, Alias; +def analyzer_checker_option : Separate<["-"], "analyzer-checker-option">, + HelpText<"Specify checker-specific settings as \"CheckerName:CheckerOption:Value\"">; +def analyzer_checker_option_EQ : Joined<["-"], "analyzer-checker-option=">, + Alias; + def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -132,7 +132,9 @@ AnalysisPurgeMode AnalysisPurgeOpt; std::string AnalyzeSpecificFunction; - + typedef llvm::StringMap > CheckerOptionMap; + CheckerOptionMap CheckerSpecificOptions; + /// \brief The maximum number of times the analyzer visits a block. unsigned maxBlockVisitOnPath; @@ -405,6 +407,12 @@ /// This is controlled by the 'max-nodes' config option. unsigned getMaxNodesPerTopLevelFunction(); + /// Returns selected string option for selected checker + /// or default value if this option is not specified + const StringRef &getCheckerOption(const StringRef &CheckerName, + const StringRef &OptionName, + const StringRef &DefaultValue) const; + public: AnalyzerOptions() : AnalysisStoreOpt(RegionStoreModel), Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -253,7 +253,34 @@ for (unsigned i = 0, e = checkers.size(); i != e; ++i) Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable)); } - + + for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker_option), + ie = Args.filtered_end(); it != ie; ++it) { + const Arg *A = *it; + A->claim(); + // Checker option should look like "checkerName:optionName:optionValue" + StringRef optionList = A->getValue(); + SmallVector options; + optionList.split(options, ":"); + if (options.size() != 3) { + Diags.Report(SourceLocation(), + diag::warn_analyzer_config_incorrect_checker_option_section_count) + << optionList + << StringRef(llvm::APInt(8, options.size()).toString(10, false)); + continue; + } + if (options[0] == "") { + Diags.Report(SourceLocation(), + diag::warn_analyzer_config_incorrect_checker_option_empty) + << optionList; + continue; + } + + llvm::StringMap &CheckerOpts = + Opts.CheckerSpecificOptions[options[0]]; + CheckerOpts[options[1]] = options[2]; + } + // Go through the analyzer configuration options. for (arg_iterator it = Args.filtered_begin(OPT_analyzer_config), ie = Args.filtered_end(); it != ie; ++it) { Index: lib/StaticAnalyzer/Core/AnalyzerOptions.cpp =================================================================== --- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -260,6 +260,21 @@ return MaxNodesPerTopLevelFunction.getValue(); } +const StringRef & +AnalyzerOptions::getCheckerOption(const StringRef &CheckerName, + const StringRef &OptionName, + const StringRef &DefaultValue) const { + CheckerOptionMap::const_iterator CheckerOpts = + CheckerSpecificOptions.find(CheckerName); + if (CheckerOpts == CheckerSpecificOptions.end()) + return DefaultValue; + llvm::StringMap::const_iterator Option = + CheckerOpts->second.find(OptionName); + if (Option == CheckerOpts->second.end()) + return DefaultValue; + return Option->second; +} + bool AnalyzerOptions::shouldSynthesizeBodies() { return getBooleanOption("faux-bodies", true); }