Skip to content

[Preprocessor] Do not expand macros if the input is already preprocessed #137665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Frontend/FrontendAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class FrontendAction {
/// \return True on success; on failure ExecutionAction() and
/// EndSourceFileAction() will not be called.
virtual bool BeginSourceFileAction(CompilerInstance &CI) {
if (CurrentInput.isPreprocessed())
CI.getPreprocessor().SetDisableMacroExpansion();
Comment on lines +87 to +88
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should (save and) restore the previous state in EndSourceFileAction,
Did you check if any subclass of FrontendAction would need to be modified?

return true;
}

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1831,6 +1831,11 @@ class Preprocessor {
MacroExpansionInDirectivesOverride = true;
}

void SetDisableMacroExpansion() {
DisableMacroExpansion = true;
MacroExpansionInDirectivesOverride = false;
}

/// Peeks ahead N tokens and returns that token without consuming any
/// tokens.
///
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
const PCHContainerReader &PCHContainerRdr,
const FrontendOptions &FEOpts,
const CodeGenOptions &CodeGenOpts) {

const LangOptions &LangOpts = PP.getLangOpts();
std::string PredefineBuffer;
PredefineBuffer.reserve(4080);
Expand Down
59 changes: 55 additions & 4 deletions clang/test/Modules/initializers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
// instantiation for v<int> in one of the two headers, because we will only
// parse one of the two get() functions.

#ifdef NS
#pragma clang module build m
module m {
module a {
Expand All @@ -60,9 +61,7 @@ module m {
#pragma clang module begin m.a
inline int non_trivial() { return 3; }

#ifdef NS
namespace ns {
#endif

int a = non_trivial();
inline int b = non_trivial();
Expand Down Expand Up @@ -102,12 +101,64 @@ inline void use(bool b, ...) {
X<int>::e<int>, X<int>::f<int>, X<int>::g<int>, X<int>::h<int>);
}

#ifdef NS
}
#endif

#pragma clang module end
#pragma clang module endbuild
#else
#pragma clang module build m
module m {
module a {
header "foo.h" { size 123 mtime 456789 }
}
module b {}
}

#pragma clang module contents
#pragma clang module begin m.a
inline int non_trivial() { return 3; }

int a = non_trivial();
inline int b = non_trivial();
thread_local int c = non_trivial();
inline thread_local int d = non_trivial();

template<typename U> int e = non_trivial();
template<typename U> inline int f = non_trivial();
template<typename U> thread_local int g = non_trivial();
template<typename U> inline thread_local int h = non_trivial();

inline int unused = 123; // should not be emitted

template<typename T> struct X {
static int a;
static inline int b = non_trivial();
static thread_local int c;
static inline thread_local int d = non_trivial();

template<typename U> static int e;
template<typename U> static inline int f = non_trivial();
template<typename U> static thread_local int g;
template<typename U> static inline thread_local int h = non_trivial();

static inline int unused = 123; // should not be emitted
};

template<typename T> int X<T>::a = non_trivial();
template<typename T> thread_local int X<T>::c = non_trivial();
template<typename T> template<typename U> int X<T>::e = non_trivial();
template<typename T> template<typename U> thread_local int X<T>::g = non_trivial();

inline void use(bool b, ...) {
if (b) return;
use(true, e<int>, f<int>, g<int>, h<int>,
X<int>::a, X<int>::b, X<int>::c, X<int>::d,
X<int>::e<int>, X<int>::f<int>, X<int>::g<int>, X<int>::h<int>);
}

#pragma clang module end
#pragma clang module endbuild
#endif

#if IMPORT == 1
// Import the module and the m.a submodule; runs the ordered initializers and
Expand Down
10 changes: 10 additions & 0 deletions clang/test/Preprocessor/preprocess-cpp-output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -E -x c %s | FileCheck %s --check-prefixes=EXPANDED
// RUN: %clang_cc1 -E -x cpp-output %s | FileCheck %s --check-prefixes=NOT-EXPANDED

// EXPANDED: void __attribute__((__attribute__((always_inline)))) foo()
// NOT-EXPANDED: void __attribute__((always_inline)) foo()

#define always_inline __attribute__((always_inline))
void __attribute__((always_inline)) foo() {
return 4;
}