Skip to content

Commit 8b020d5

Browse files
authored
[Preprocessor] Do not expand macros if the input is already preprocessed (#137665)
Preprocessing the preprocessor output again interacts poorly with some flag combinations when we perform a separate preprocessing stage. In our case, `-no-integrated-cpp -dD` triggered this issue; but I guess that other flags could also trigger problems (`-save-temps` instead of `-no-integrated-cpp`). Full context (which is quite weird I'll admit): * To cache OpenCL kernel compilation results, we use the `-no-integrated-cpp` for the driver to generate a separate preprocessing command (`clang -E`) before the rest of the compilation. * Some OpenCL C language features are implemented as macro definitions (in `opencl-c-base.h`). The semantic analysis queries the preprocessor to check if these are defined or not, for example, when we checks if a builtin is available when using `-fdeclare-opencl-builtins`. * To preserve these `#define` directives, on the preprocessor's output, we use `-dD`. However, other `#define` directives are also maintained besides OpenCL ones; which triggers the issue shown in this PR. A better fix for our particular case could have been to move the language features implemented as macros into some sort of a flag to be used together with `-fdeclare-opencl-builtins`. But I also thought that not preprocessing preprocessor outputs seemed like something desirable. I hope to work on this on a follow up.
1 parent 267eb81 commit 8b020d5

File tree

7 files changed

+49
-5
lines changed

7 files changed

+49
-5
lines changed

clang/include/clang/Frontend/FrontendAction.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class FrontendAction {
8484
/// \return True on success; on failure ExecutionAction() and
8585
/// EndSourceFileAction() will not be called.
8686
virtual bool BeginSourceFileAction(CompilerInstance &CI) {
87+
if (CurrentInput.isPreprocessed())
88+
CI.getPreprocessor().SetMacroExpansionOnlyInDirectives();
8789
return true;
8890
}
8991

@@ -98,7 +100,11 @@ class FrontendAction {
98100
///
99101
/// This is guaranteed to only be called following a successful call to
100102
/// BeginSourceFileAction (and BeginSourceFile).
101-
virtual void EndSourceFileAction() {}
103+
virtual void EndSourceFileAction() {
104+
if (CurrentInput.isPreprocessed())
105+
// Reset the preprocessor macro expansion to the default.
106+
getCompilerInstance().getPreprocessor().SetEnableMacroExpansion();
107+
}
102108

103109
/// Callback at the end of processing a single input, to determine
104110
/// if the output files should be erased or not.

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,10 @@ class Preprocessor {
18471847
MacroExpansionInDirectivesOverride = true;
18481848
}
18491849

1850+
void SetEnableMacroExpansion() {
1851+
DisableMacroExpansion = MacroExpansionInDirectivesOverride = false;
1852+
}
1853+
18501854
/// Peeks ahead N tokens and returns that token without consuming any
18511855
/// tokens.
18521856
///

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,8 @@ bool CodeGenAction::loadLinkModules(CompilerInstance &CI) {
908908
bool CodeGenAction::hasIRSupport() const { return true; }
909909

910910
void CodeGenAction::EndSourceFileAction() {
911+
ASTFrontendAction::EndSourceFileAction();
912+
911913
// If the consumer creation failed, do nothing.
912914
if (!getCompilerInstance().hasASTConsumer())
913915
return;
@@ -932,7 +934,7 @@ CodeGenerator *CodeGenAction::getCodeGenerator() const {
932934
bool CodeGenAction::BeginSourceFileAction(CompilerInstance &CI) {
933935
if (CI.getFrontendOpts().GenReducedBMI)
934936
CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
935-
return true;
937+
return ASTFrontendAction::BeginSourceFileAction(CI);
936938
}
937939

938940
static std::unique_ptr<raw_pwrite_stream>

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ bool GeneratePCHAction::shouldEraseOutputFiles() {
181181

182182
bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
183183
CI.getLangOpts().CompilingPCH = true;
184-
return true;
184+
return ASTFrontendAction::BeginSourceFileAction(CI);
185185
}
186186

187187
std::vector<std::unique_ptr<ASTConsumer>>

clang/lib/Frontend/Rewrite/FrontendActions.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,13 @@ bool FixItAction::BeginSourceFileAction(CompilerInstance &CI) {
103103
}
104104
Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
105105
CI.getLangOpts(), FixItOpts.get()));
106-
return true;
106+
return ASTFrontendAction::BeginSourceFileAction(CI);
107107
}
108108

109109
void FixItAction::EndSourceFileAction() {
110110
// Otherwise rewrite all files.
111111
Rewriter->WriteFixedFiles();
112+
ASTFrontendAction::EndSourceFileAction();
112113
}
113114

114115
bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
@@ -298,7 +299,7 @@ bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) {
298299
std::make_unique<RewriteImportsListener>(CI, OutputStream));
299300
}
300301

301-
return true;
302+
return PreprocessorFrontendAction::BeginSourceFileAction(CI);
302303
}
303304

304305
void RewriteIncludesAction::ExecuteAction() {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -E -x c %s | FileCheck %s --check-prefixes=EXPANDED
2+
// RUN: %clang_cc1 -E -x cpp-output %s | FileCheck %s --check-prefixes=NOT-EXPANDED
3+
4+
// EXPANDED: void __attribute__((__attribute__((always_inline)))) foo()
5+
// NOT-EXPANDED: void __attribute__((always_inline)) foo()
6+
7+
#define always_inline __attribute__((always_inline))
8+
void __attribute__((always_inline)) foo() {
9+
return 4;
10+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_cc1 -E -x c %s | FileCheck %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only %s -verify
3+
// RUN: %clang_cc1 -x cpp-output -fsyntax-only -verify %s
4+
// expected-no-diagnostics
5+
6+
// The preprocessor does not expand macro-identifiers in #pragma directives.
7+
// When we preprocess & parse the code, clang expands the macros in directives.
8+
// When we parse already preprocessed code, clang still has to expand the
9+
// macros in the directives.
10+
// This means that we're not always able to parse the preprocessor's output
11+
// without preserving the definitions (-dD).
12+
13+
#define FACTOR 4
14+
15+
void foo() {
16+
// CHECK: #pragma unroll FACTOR
17+
#pragma unroll FACTOR
18+
for(;;) {
19+
}
20+
return;
21+
}

0 commit comments

Comments
 (0)