diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 40 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp | 22 |
4 files changed, 64 insertions, 43 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index fb5f1cc5ac7..66684e5c961 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -324,18 +324,18 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth, Opts.InlineMaxStackDepth, Diags); - Opts.CheckersControlList.clear(); + Opts.CheckersAndPackages.clear(); for (const Arg *A : Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) { A->claim(); - bool enable = (A->getOption().getID() == OPT_analyzer_checker); + bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker; // We can have a list of comma separated checker names, e.g: // '-analyzer-checker=cocoa,unix' - StringRef checkerList = A->getValue(); - SmallVector<StringRef, 4> checkers; - checkerList.split(checkers, ","); - for (auto checker : checkers) - Opts.CheckersControlList.emplace_back(checker, enable); + StringRef CheckerAndPackageList = A->getValue(); + SmallVector<StringRef, 16> CheckersAndPackages; + CheckerAndPackageList.split(CheckersAndPackages, ","); + for (const StringRef CheckerOrPackage : CheckersAndPackages) + Opts.CheckersAndPackages.emplace_back(CheckerOrPackage, IsEnabled); } // Go through the analyzer configuration options. @@ -479,6 +479,32 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, !llvm::sys::fs::is_directory(AnOpts.ModelPath)) Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path" << "a filename"; + + // FIXME: Here we try to validate the silenced checkers or packages are valid. + // The current approach only validates the registered checkers which does not + // contain the runtime enabled checkers and optimally we would validate both. + if (!AnOpts.RawSilencedCheckersAndPackages.empty()) { + std::vector<StringRef> Checkers = + AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true); + std::vector<StringRef> Packages = + AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true); + + SmallVector<StringRef, 16> CheckersAndPackages; + AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";"); + + for (const StringRef CheckerOrPackage : CheckersAndPackages) { + bool IsChecker = CheckerOrPackage.contains('.'); + bool IsValidName = + IsChecker ? llvm::find(Checkers, CheckerOrPackage) != Checkers.end() + : llvm::find(Packages, CheckerOrPackage) != Packages.end(); + + if (!IsValidName) + Diags->Report(diag::err_unknown_analyzer_checker_or_package) + << CheckerOrPackage; + + AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage); + } + } } static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) { diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 71abe2ae6c0..01ac2bc83bb 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -30,25 +30,6 @@ using namespace clang; using namespace ento; using namespace llvm; -std::vector<StringRef> -AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) { - static const StringRef StaticAnalyzerChecks[] = { -#define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ - FULLNAME, -#include "clang/StaticAnalyzer/Checkers/Checkers.inc" -#undef CHECKER -#undef GET_CHECKERS - }; - std::vector<StringRef> Result; - for (StringRef CheckName : StaticAnalyzerChecks) { - if (!CheckName.startswith("debug.") && - (IncludeExperimental || !CheckName.startswith("alpha."))) - Result.push_back(CheckName); - } - return Result; -} - void AnalyzerOptions::printFormattedEntry( llvm::raw_ostream &Out, std::pair<StringRef, StringRef> EntryDescPair, diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 4cfcdee1c3a..37a3ddecf7a 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1924,15 +1924,22 @@ PathDiagnosticBuilder::PathDiagnosticBuilder( std::unique_ptr<PathDiagnostic> PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { - - if (!PDC->shouldGenerateDiagnostics()) - return generateEmptyDiagnosticForReport(R, getSourceManager()); - PathDiagnosticConstruct Construct(PDC, ErrorNode, R); const SourceManager &SM = getSourceManager(); const BugReport *R = getBugReport(); const AnalyzerOptions &Opts = getAnalyzerOptions(); + StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription(); + + // See whether we need to silence the checker/package. + // FIXME: This will not work if the report was emitted with an incorrect tag. + for (const std::string &CheckerOrPackage : Opts.SilencedCheckersAndPackages) { + if (ErrorTag.startswith(CheckerOrPackage)) + return nullptr; + } + + if (!PDC->shouldGenerateDiagnostics()) + return generateEmptyDiagnosticForReport(R, getSourceManager()); // Construct the final (warning) event for the bug report. auto EndNotes = VisitorsDiagnostics->find(ErrorNode); @@ -2029,7 +2036,6 @@ PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { return std::move(Construct.PD); } - //===----------------------------------------------------------------------===// // Methods for BugType and subclasses. //===----------------------------------------------------------------------===// @@ -2646,9 +2652,13 @@ GRBugReporter::generatePathDiagnostics( Optional<PathDiagnosticBuilder> PDB = PathDiagnosticBuilder::findValidReport(bugReports, *this); - if (PDB) - for (PathDiagnosticConsumer *PC : consumers) - (*Out)[PC] = PDB->generate(PC); + if (PDB) { + for (PathDiagnosticConsumer *PC : consumers) { + if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) { + (*Out)[PC] = std::move(PD); + } + } + } return Out; } diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index 3fd4c36947c..322304b0fb7 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -200,12 +200,12 @@ CheckerRegistry::CheckerRegistry( // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the // command line. - for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersControlList) { + for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) { CheckerInfoListRange CheckerForCmdLineArg = getMutableCheckersForCmdLineArg(Opt.first); if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) { - Diags.Report(diag::err_unknown_analyzer_checker) << Opt.first; + Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first; Diags.Report(diag::note_suggest_disabling_all_checkers); } @@ -468,9 +468,10 @@ isOptionContainedIn(const CheckerRegistry::CmdLineOptionList &OptionList, void CheckerRegistry::validateCheckerOptions() const { for (const auto &Config : AnOpts.Config) { - StringRef SuppliedChecker; + StringRef SuppliedCheckerOrPackage; StringRef SuppliedOption; - std::tie(SuppliedChecker, SuppliedOption) = Config.getKey().split(':'); + std::tie(SuppliedCheckerOrPackage, SuppliedOption) = + Config.getKey().split(':'); if (SuppliedOption.empty()) continue; @@ -483,21 +484,24 @@ void CheckerRegistry::validateCheckerOptions() const { // Since lower_bound would look for the first element *not less* than "cor", // it would return with an iterator to the first checker in the core, so we // we really have to use find here, which uses operator==. - auto CheckerIt = llvm::find(Checkers, CheckerInfo(SuppliedChecker)); + auto CheckerIt = + llvm::find(Checkers, CheckerInfo(SuppliedCheckerOrPackage)); if (CheckerIt != Checkers.end()) { - isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedChecker, + isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedCheckerOrPackage, SuppliedOption, AnOpts, Diags); continue; } - auto PackageIt = llvm::find(Packages, PackageInfo(SuppliedChecker)); + auto PackageIt = + llvm::find(Packages, PackageInfo(SuppliedCheckerOrPackage)); if (PackageIt != Packages.end()) { - isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedChecker, + isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedCheckerOrPackage, SuppliedOption, AnOpts, Diags); continue; } - Diags.Report(diag::err_unknown_analyzer_checker) << SuppliedChecker; + Diags.Report(diag::err_unknown_analyzer_checker_or_package) + << SuppliedCheckerOrPackage; } } |

