From a3e008abc51933d567303a1b4bd17e68c798f60e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 14 Dec 2009 05:00:18 +0000 Subject: [PATCH] fix rdar://7466570 - Be more bug compatible with GCC when it comes to expanding directives withing macro expansions. This is undefined behavior according to 6.10.3p11, so we might as well be undefined in ways similar to GCC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91266 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/PPExpressions.cpp | 23 +++++++++++++++++++-- test/Preprocessor/macro_fn_disable_expand.c | 20 ++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 6422752ae9..2a6b2a7294 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -72,8 +72,8 @@ struct DefinedTracker { }; /// EvaluateDefined - Process a 'defined(sym)' expression. -static bool EvaluateDefined(PPValue &Result, Token &PeekTok, - DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { +static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, + bool ValueLive, Preprocessor &PP) { IdentifierInfo *II; Result.setBegin(PeekTok.getLocation()); @@ -676,6 +676,15 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, /// to "!defined(X)" return X in IfNDefMacro. bool Preprocessor:: EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { + // Save the current state of 'DisableMacroExpansion' and reset it to false. If + // 'DisableMacroExpansion' is true, then we must be in a macro argument list + // in which case a directive is undefined behavior. We want macros to be able + // to recursively expand in order to get more gcc-list behavior, so we force + // DisableMacroExpansion to false and restore it when we're done parsing the + // expression. + bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion; + DisableMacroExpansion = false; + // Peek ahead one token. Token Tok; Lex(Tok); @@ -689,6 +698,9 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Parse error, skip the rest of the macro line. if (Tok.isNot(tok::eom)) DiscardUntilEndOfDirective(); + + // Restore 'DisableMacroExpansion'. + DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; return false; } @@ -701,6 +713,8 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { if (DT.State == DefinedTracker::NotDefinedMacro) IfNDefMacro = DT.TheMacro; + // Restore 'DisableMacroExpansion'. + DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; return ResVal.Val != 0; } @@ -711,6 +725,9 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Parse error, skip the rest of the macro line. if (Tok.isNot(tok::eom)) DiscardUntilEndOfDirective(); + + // Restore 'DisableMacroExpansion'. + DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; return false; } @@ -721,6 +738,8 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { DiscardUntilEndOfDirective(); } + // Restore 'DisableMacroExpansion'. + DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; return ResVal.Val != 0; } diff --git a/test/Preprocessor/macro_fn_disable_expand.c b/test/Preprocessor/macro_fn_disable_expand.c index 2c24d696d5..e2c666e6a2 100644 --- a/test/Preprocessor/macro_fn_disable_expand.c +++ b/test/Preprocessor/macro_fn_disable_expand.c @@ -8,3 +8,23 @@ foo(foo) (2) #define w ABCD m(m) // CHECK: m(ABCD) + + + +// rdar://7466570 + +// We should get '42' in the argument list for gcc compatibility. +#define A 1 +#define B 2 +#define C(x) (x + 1) + +X: C( +#ifdef A +#if A == 1 +#if B + 42 +#endif +#endif +#endif + ) +// CHECK: X: (42 + 1) -- 2.50.1