Skip to content

Commit c5d14b5

Browse files
committed
[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
1 parent 7e385bd commit c5d14b5

File tree

10 files changed

+48
-9
lines changed

10 files changed

+48
-9
lines changed

clang-tools-extra/clang-tidy/ClangTidy.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "clang/Frontend/TextDiagnosticPrinter.h"
3434
#include "clang/Lex/PPCallbacks.h"
3535
#include "clang/Lex/Preprocessor.h"
36+
#include "clang/Lex/PreprocessorOptions.h"
3637
#include "clang/Rewrite/Frontend/FixItRewriter.h"
3738
#include "clang/Rewrite/Frontend/FrontendActions.h"
3839
#include "clang/Tooling/Core/Diagnostic.h"
@@ -539,10 +540,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
539540
FileManager *Files,
540541
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
541542
DiagnosticConsumer *DiagConsumer) override {
542-
// Explicitly set ProgramAction to RunAnalysis to make the preprocessor
543-
// define __clang_analyzer__ macro. The frontend analyzer action will not
544-
// be called here.
545-
Invocation->getFrontendOpts().ProgramAction = frontend::RunAnalysis;
543+
// Explicitly ask to define __clang_analyzer__ macro.
544+
Invocation->getPreprocessorOpts().SetUpStaticAnalyzer = true;
546545
return FrontendActionFactory::runInvocation(
547546
Invocation, Files, PCHContainerOps, DiagConsumer);
548547
}

clang/include/clang/Driver/CC1Options.td

+2
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,8 @@ def preamble_bytes_EQ : Joined<["-"], "preamble-bytes=">,
846846
"covering the first N bytes of the main file">;
847847
def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">,
848848
HelpText<"include a detailed record of preprocessing actions">;
849+
def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">,
850+
HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">;
849851

850852
//===----------------------------------------------------------------------===//
851853
// OpenCL Options

clang/include/clang/Lex/PreprocessorOptions.h

+3
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ class PreprocessorOptions {
181181
ExcludedPreprocessorDirectiveSkipMapping
182182
*ExcludedConditionalDirectiveSkipMappings = nullptr;
183183

184+
/// Set up preprocessor for RunAnalysis action.
185+
bool SetUpStaticAnalyzer = false;
186+
184187
public:
185188
PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
186189

clang/lib/Driver/ToolChains/Clang.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -3803,6 +3803,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
38033803
if (isa<AnalyzeJobAction>(JA))
38043804
RenderAnalyzerOptions(Args, CmdArgs, Triple, Input);
38053805

3806+
if (isa<AnalyzeJobAction>(JA) ||
3807+
(isa<PreprocessJobAction>(JA) && Args.hasArg(options::OPT__analyze)))
3808+
CmdArgs.push_back("-setup-static-analyzer");
3809+
38063810
// Enable compatilibily mode to avoid analyzer-config related errors.
38073811
// Since we can't access frontend flags through hasArg, let's manually iterate
38083812
// through them.

clang/lib/Frontend/CompilerInvocation.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3349,6 +3349,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
33493349
// "editor placeholder in source file" error in PP only mode.
33503350
if (isStrictlyPreprocessorAction(Action))
33513351
Opts.LexEditorPlaceholders = false;
3352+
3353+
Opts.SetUpStaticAnalyzer = Args.hasArg(OPT_setup_static_analyzer);
33523354
}
33533355

33543356
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,

clang/lib/Frontend/InitPreprocessor.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
560560
static void InitializePredefinedMacros(const TargetInfo &TI,
561561
const LangOptions &LangOpts,
562562
const FrontendOptions &FEOpts,
563+
const PreprocessorOptions &PPOpts,
563564
MacroBuilder &Builder) {
564565
// Compiler version introspection macros.
565566
Builder.defineMacro("__llvm__"); // LLVM Backend
@@ -997,8 +998,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
997998
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
998999
Builder.defineMacro("__SSP_ALL__", "3");
9991000

1000-
// Define a macro that exists only when using the static analyzer.
1001-
if (FEOpts.ProgramAction == frontend::RunAnalysis)
1001+
if (PPOpts.SetUpStaticAnalyzer)
10021002
Builder.defineMacro("__clang_analyzer__");
10031003

10041004
if (LangOpts.FastRelaxedMath)
@@ -1125,9 +1125,10 @@ void clang::InitializePreprocessor(
11251125
// macros. This is not the right way to handle this.
11261126
if ((LangOpts.CUDA || LangOpts.OpenMPIsDevice) && PP.getAuxTargetInfo())
11271127
InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
1128-
Builder);
1128+
PP.getPreprocessorOpts(), Builder);
11291129

1130-
InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder);
1130+
InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts,
1131+
PP.getPreprocessorOpts(), Builder);
11311132

11321133
// Install definitions to make Objective-C++ ARC work well with various
11331134
// C++ Standard Library implementations.
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %clang_cc1 -E -setup-static-analyzer %s
2+
3+
#ifndef __clang_analyzer__
4+
#error __clang_analyzer__ not defined
5+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"directory": "DIR",
4+
"command": "clang --analyze DIR/static-analyzer.c",
5+
"file": "DIR/static-analyzer.c"
6+
}
7+
]
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: rm -rf %t.dir
2+
// RUN: rm -rf %t.dir/cdb.json
3+
// RUN: mkdir -p %t.dir
4+
// RUN: cp %s %t.dir/static-analyzer.c
5+
// RUN: mkdir %t.dir/Inputs
6+
// RUN: cp %S/Inputs/header.h %t.dir/Inputs/analyze_header_input.h
7+
// RUN: sed -e "s|DIR|%t.dir|g" %S/Inputs/static-analyzer-cdb.json > %t.dir/cdb.json
8+
//
9+
// RUN: clang-scan-deps -compilation-database %t.dir/cdb.json -j 1 | FileCheck %s
10+
11+
#ifdef __clang_analyzer__
12+
#include "Inputs/analyze_header_input.h"
13+
#endif
14+
15+
// CHECK: analyze_header_input.h
16+

llvm/utils/lit/lit/llvm/config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ def use_clang(self, additional_tool_dirs=[], additional_flags=[], required=True)
402402
builtin_include_dir = self.get_clang_builtin_include_dir(self.config.clang)
403403
tool_substitutions = [
404404
ToolSubst('%clang', command=self.config.clang, extra_args=additional_flags),
405-
ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze']+additional_flags),
405+
ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze', '-setup-static-analyzer']+additional_flags),
406406
ToolSubst('%clang_cc1', command=self.config.clang, extra_args=['-cc1', '-internal-isystem', builtin_include_dir, '-nostdsysteminc']+additional_flags),
407407
ToolSubst('%clang_cpp', command=self.config.clang, extra_args=['--driver-mode=cpp']+additional_flags),
408408
ToolSubst('%clang_cl', command=self.config.clang, extra_args=['--driver-mode=cl']+additional_flags),

0 commit comments

Comments
 (0)