Index: cfe/trunk/include/clang/Driver/CC1Options.td =================================================================== --- cfe/trunk/include/clang/Driver/CC1Options.td +++ cfe/trunk/include/clang/Driver/CC1Options.td @@ -166,6 +166,9 @@ def analyzer_config_compatibility_mode_EQ : Joined<["-"], "analyzer-config-compatibility-mode=">, Alias; +def analyzer_werror : Flag<["-"], "analyzer-werror">, + HelpText<"Emit analyzer results as errors rather than warnings">; + //===----------------------------------------------------------------------===// // Migrator Options //===----------------------------------------------------------------------===// Index: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -245,6 +245,9 @@ /// strategy. We get better code coverage when retry is enabled. unsigned NoRetryExhausted : 1; + /// Emit analyzer warnings as errors. + unsigned AnalyzerWerror : 1; + /// The inlining stack depth limit. // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). unsigned InlineMaxStackDepth = 5; @@ -297,7 +300,7 @@ AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), - PrintStats(false), NoRetryExhausted(false) { + PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) { llvm::sort(AnalyzerConfigCmdFlags); } Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp @@ -309,6 +309,7 @@ Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.DumpExplodedGraphTo = Args.getLastArgValue(OPT_analyzer_dump_egraph); Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted); + Opts.AnalyzerWerror = Args.hasArg(OPT_analyzer_werror); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); Opts.AnalyzeNestedBlocks = Index: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -83,10 +83,11 @@ namespace { class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer { DiagnosticsEngine &Diag; - bool IncludePath; + bool IncludePath, ShouldEmitAsError; + public: ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) - : Diag(Diag), IncludePath(false) {} + : Diag(Diag), IncludePath(false), ShouldEmitAsError(false) {} ~ClangDiagPathDiagConsumer() override {} StringRef getName() const override { return "ClangDiags"; } @@ -101,9 +102,14 @@ IncludePath = true; } + void enableWerror() { ShouldEmitAsError = true; } + void FlushDiagnosticsImpl(std::vector &Diags, FilesMade *filesMade) override { - unsigned WarnID = Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0"); + unsigned WarnID = + ShouldEmitAsError + ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0") + : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0"); unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0"); for (std::vector::iterator I = Diags.begin(), @@ -225,6 +231,9 @@ new ClangDiagPathDiagConsumer(PP.getDiagnostics()); PathConsumers.push_back(clangDiags); + if (Opts->AnalyzerWerror) + clangDiags->enableWerror(); + if (Opts->AnalysisDiagOpt == PD_TEXT) { clangDiags->enablePaths(); @@ -358,7 +367,7 @@ return true; llvm::Expected CTUDeclOrError = - CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName, + CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName, Opts->DisplayCTUProgress); if (!CTUDeclOrError) { Index: cfe/trunk/test/Analysis/override-werror.c =================================================================== --- cfe/trunk/test/Analysis/override-werror.c +++ cfe/trunk/test/Analysis/override-werror.c @@ -1,14 +1,17 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -analyzer-store=region -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -Werror %s -analyzer-store=region -analyzer-werror -verify=werror // This test case illustrates that using '-analyze' overrides the effect of // -Werror. This allows basic warnings not to interfere with producing // analyzer results. -char* f(int *p) { - return p; // expected-warning{{incompatible pointer types}} +char* f(int *p) { + return p; // expected-warning{{incompatible pointer types}} \ + werror-warning{{incompatible pointer types}} } void g(int *p) { - if (!p) *p = 0; // expected-warning{{null}} + if (!p) *p = 0; // expected-warning{{null}} \ + werror-error{{null}} }