Index: clang-tools-extra/clang-tidy/ClangTidy.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidy.cpp +++ clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -33,6 +33,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Rewrite/Frontend/FixItRewriter.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Tooling/Core/Diagnostic.h" @@ -539,10 +540,8 @@ FileManager *Files, std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer) override { - // Explicitly set ProgramAction to RunAnalysis to make the preprocessor - // define __clang_analyzer__ macro. The frontend analyzer action will not - // be called here. - Invocation->getFrontendOpts().ProgramAction = frontend::RunAnalysis; + // Explicitly ask to define __clang_analyzer__ macro. + Invocation->getPreprocessorOpts().SetUpStaticAnalyzer = true; return FrontendActionFactory::runInvocation( Invocation, Files, PCHContainerOps, DiagConsumer); } Index: clang/include/clang/Driver/CC1Options.td =================================================================== --- clang/include/clang/Driver/CC1Options.td +++ clang/include/clang/Driver/CC1Options.td @@ -846,6 +846,8 @@ "covering the first N bytes of the main file">; def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">, HelpText<"include a detailed record of preprocessing actions">; +def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">, + HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">; //===----------------------------------------------------------------------===// // OpenCL Options Index: clang/include/clang/Lex/PreprocessorOptions.h =================================================================== --- clang/include/clang/Lex/PreprocessorOptions.h +++ clang/include/clang/Lex/PreprocessorOptions.h @@ -181,6 +181,9 @@ ExcludedPreprocessorDirectiveSkipMapping *ExcludedConditionalDirectiveSkipMappings = nullptr; + /// Set up preprocessor for RunAnalysis action. + bool SetUpStaticAnalyzer = false; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -3326,6 +3326,9 @@ // "editor placeholder in source file" error in PP only mode. if (isStrictlyPreprocessorAction(Action)) Opts.LexEditorPlaceholders = false; + + Opts.SetUpStaticAnalyzer = + Args.hasArg(OPT_analyze) || Args.hasArg(OPT_setup_static_analyzer); } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, Index: clang/lib/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -559,6 +559,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, + const PreprocessorOptions &PPOpts, MacroBuilder &Builder) { // Compiler version introspection macros. Builder.defineMacro("__llvm__"); // LLVM Backend @@ -990,8 +991,7 @@ else if (LangOpts.getStackProtector() == LangOptions::SSPReq) Builder.defineMacro("__SSP_ALL__", "3"); - // Define a macro that exists only when using the static analyzer. - if (FEOpts.ProgramAction == frontend::RunAnalysis) + if (PPOpts.SetUpStaticAnalyzer) Builder.defineMacro("__clang_analyzer__"); if (LangOpts.FastRelaxedMath) @@ -1118,9 +1118,10 @@ // macros. This is not the right way to handle this. if ((LangOpts.CUDA || LangOpts.OpenMPIsDevice) && PP.getAuxTargetInfo()) InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts, - Builder); + PP.getPreprocessorOpts(), Builder); - InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder); + InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, + PP.getPreprocessorOpts(), Builder); // Install definitions to make Objective-C++ ARC work well with various // C++ Standard Library implementations. Index: clang/test/Analysis/preprocessor-setup.c =================================================================== --- /dev/null +++ clang/test/Analysis/preprocessor-setup.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -E -setup-static-analyzer %s + +#ifndef __clang_analyzer__ +#error __clang_analyzer__ not defined +#endif Index: clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json =================================================================== --- /dev/null +++ clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "DIR", + "command": "clang --analyze DIR/static-analyzer.c", + "file": "DIR/static-analyzer.c" +} +] Index: clang/test/ClangScanDeps/static-analyzer.c =================================================================== --- /dev/null +++ clang/test/ClangScanDeps/static-analyzer.c @@ -0,0 +1,16 @@ +// RUN: rm -rf %t.dir +// RUN: rm -rf %t.dir/cdb.json +// RUN: mkdir -p %t.dir +// RUN: cp %s %t.dir/static-analyzer.c +// RUN: mkdir %t.dir/Inputs +// RUN: cp %S/Inputs/analyze_header_input.h %t.dir/Inputs/analyze_header_input.h +// RUN: sed -e "s|DIR|%t.dir|g" %S/Inputs/static-analyzer-cdb.json > %t.dir/cdb.json +// +// RUN: clang-scan-deps -compilation-database %t.dir/cdb.json -j 1 | FileCheck %s + +#ifdef __clang_analyzer__ +#include "Inputs/analyze_header_input.h" +#endif + +// CHECK: analyze_header_input.h + Index: clang/tools/clang-scan-deps/ClangScanDeps.cpp =================================================================== --- clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -259,6 +259,11 @@ AdjustedArgs.push_back(FileName); } } + // Support for static analyzer. + auto It = find(AdjustedArgs.begin(), AdjustedArgs.end(), "--analyze"); + if (It != AdjustedArgs.end()) + *It = "-Wp,-setup-static-analyzer"; + AdjustedArgs.push_back("-Xclang"); AdjustedArgs.push_back("-Eonly"); AdjustedArgs.push_back("-Xclang");