From 1208fe7429a0fe6c7d892f0b96355c90d9b96048 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Mon, 14 Oct 2019 20:15:01 +0000 Subject: [PATCH 1/2] [clang-scan-deps] Support for clang --analyze in clang-scan-deps The goal is to have 100% fidelity in clang-scan-deps behavior when --analyze is present in compilation command. At the same time I don't want to break clang-tidy which expects __static_analyzer__ macro defined as built-in. I introduce new cc1 options (-setup-static-analyzer) that controls the macro definition and is conditionally set in driver. Differential Revision: https://reviews.llvm.org/D68093 llvm-svn: 374815 --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 7 +++---- clang/include/clang/Driver/CC1Options.td | 2 ++ clang/include/clang/Lex/PreprocessorOptions.h | 3 +++ clang/lib/Driver/ToolChains/Clang.cpp | 4 ++++ clang/lib/Frontend/CompilerInvocation.cpp | 2 ++ clang/lib/Frontend/InitPreprocessor.cpp | 9 +++++---- clang/test/Analysis/preprocessor-setup.c | 5 +++++ .../Inputs/static-analyzer-cdb.json | 7 +++++++ clang/test/ClangScanDeps/static-analyzer.c | 16 ++++++++++++++++ llvm/utils/lit/lit/llvm/config.py | 2 +- 10 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 clang/test/Analysis/preprocessor-setup.c create mode 100644 clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json create mode 100644 clang/test/ClangScanDeps/static-analyzer.c diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f0ef809338bbb7..69d758e9750ed9 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/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" @@ -536,10 +537,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, 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); } diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 92159372171057..80f6d9e3b29bf7 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -853,6 +853,8 @@ def preamble_bytes_EQ : Joined<["-"], "preamble-bytes=">, "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 diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index e13cab38ff9eb9..251c4b3b26ccb3 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -178,6 +178,9 @@ class PreprocessorOptions { ExcludedPreprocessorDirectiveSkipMapping *ExcludedConditionalDirectiveSkipMappings = nullptr; + /// Set up preprocessor for RunAnalysis action. + bool SetUpStaticAnalyzer = false; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a126b764dea776..9d311b4cb6f1a2 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3856,6 +3856,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (isa(JA)) RenderAnalyzerOptions(Args, CmdArgs, Triple, Input); + if (isa(JA) || + (isa(JA) && Args.hasArg(options::OPT__analyze))) + CmdArgs.push_back("-setup-static-analyzer"); + // Enable compatilibily mode to avoid analyzer-config related errors. // Since we can't access frontend flags through hasArg, let's manually iterate // through them. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2bebf07a00a8ac..dfc74e7ffb09f8 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3273,6 +3273,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, // "editor placeholder in source file" error in PP only mode. if (isStrictlyPreprocessorAction(Action)) Opts.LexEditorPlaceholders = false; + + Opts.SetUpStaticAnalyzer = Args.hasArg(OPT_setup_static_analyzer); } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 1741ba5e5203e6..2758ed1bc72c58 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -556,6 +556,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, 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 @@ -988,8 +989,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, 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) @@ -1113,9 +1113,10 @@ void clang::InitializePreprocessor( // 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. diff --git a/clang/test/Analysis/preprocessor-setup.c b/clang/test/Analysis/preprocessor-setup.c new file mode 100644 index 00000000000000..57f13e6e7d3b58 --- /dev/null +++ b/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 diff --git a/clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json b/clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json new file mode 100644 index 00000000000000..a466d87afaa432 --- /dev/null +++ b/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" +} +] diff --git a/clang/test/ClangScanDeps/static-analyzer.c b/clang/test/ClangScanDeps/static-analyzer.c new file mode 100644 index 00000000000000..dca35039d83141 --- /dev/null +++ b/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/header.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 + diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py index 6a0bfa1b207397..d94269f8b3d3fd 100644 --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -404,7 +404,7 @@ def use_clang(self, additional_tool_dirs=[], additional_flags=[], required=True) builtin_include_dir = self.get_clang_builtin_include_dir(self.config.clang) tool_substitutions = [ ToolSubst('%clang', command=self.config.clang, extra_args=additional_flags), - ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze']+additional_flags), + ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze', '-setup-static-analyzer']+additional_flags), ToolSubst('%clang_cc1', command=self.config.clang, extra_args=['-cc1', '-internal-isystem', builtin_include_dir, '-nostdsysteminc']+additional_flags), ToolSubst('%clang_cpp', command=self.config.clang, extra_args=['--driver-mode=cpp']+additional_flags), ToolSubst('%clang_cl', command=self.config.clang, extra_args=['--driver-mode=cl']+additional_flags), From b1fa060b92fbda1a59dbbc5aa81d73101a8a4ebd Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Mon, 14 Oct 2019 21:06:11 +0000 Subject: [PATCH 2/2] [NFC] Fix ClangScanDeps/static-analyzer.c test on Windows Follow-up to c5d14b5c6fa llvm-svn: 374821 --- clang/test/ClangScanDeps/static-analyzer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/ClangScanDeps/static-analyzer.c b/clang/test/ClangScanDeps/static-analyzer.c index dca35039d83141..c4af9b076bb2cc 100644 --- a/clang/test/ClangScanDeps/static-analyzer.c +++ b/clang/test/ClangScanDeps/static-analyzer.c @@ -1,12 +1,12 @@ // RUN: rm -rf %t.dir -// RUN: rm -rf %t.dir/cdb.json +// RUN: rm -rf %t-cdb.json // RUN: mkdir -p %t.dir // RUN: cp %s %t.dir/static-analyzer.c // RUN: mkdir %t.dir/Inputs // RUN: cp %S/Inputs/header.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: sed -e "s|DIR|%/t.dir|g" %S/Inputs/static-analyzer-cdb.json > %t-cdb.json // -// RUN: clang-scan-deps -compilation-database %t.dir/cdb.json -j 1 | FileCheck %s +// RUN: clang-scan-deps -compilation-database %t-cdb.json -j 1 | FileCheck %s #ifdef __clang_analyzer__ #include "Inputs/analyze_header_input.h"