From: Eli Friedman Date: Wed, 3 Aug 2011 00:04:13 +0000 (+0000) Subject: A couple fixes for preprocessor expressions: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88710f22be1acb04b7d812aebe87bea56394c07c;p=clang A couple fixes for preprocessor expressions: 1. Be more tolerant of comments in -CC (comment-preserving) mode. We were missing a few cases. 2. Make sure to expand the second FOO in "#if defined FOO FOO". (See also r97253, which addressed the case of "#if defined(FOO FOO".) Fixes PR10286. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136748 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 2a2f099548..a95645451e 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -556,6 +556,14 @@ public: DisableMacroExpansion = OldVal; } + /// LexUnexpandedNonComment - Like LexNonComment, but this disables macro + /// expansion of identifier tokens. + void LexUnexpandedNonComment(Token &Result) { + do + LexUnexpandedToken(Result); + while (Result.getKind() == tok::comment); + } + /// LookAhead - This peeks ahead N tokens and returns that token without /// consuming any tokens. LookAhead(0) returns the next token that would be /// returned by Lex(), LookAhead(1) returns the token after it, etc. This diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 25816923c8..7f00e6ee96 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -83,20 +83,20 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, Result.setBegin(PeekTok.getLocation()); // Get the next token, don't expand it. - PP.LexUnexpandedToken(PeekTok); + PP.LexUnexpandedNonComment(PeekTok); // Two options, it can either be a pp-identifier or a (. SourceLocation LParenLoc; if (PeekTok.is(tok::l_paren)) { // Found a paren, remember we saw it and skip it. LParenLoc = PeekTok.getLocation(); - PP.LexUnexpandedToken(PeekTok); + PP.LexUnexpandedNonComment(PeekTok); } if (PeekTok.is(tok::code_completion)) { if (PP.getCodeCompletionHandler()) PP.getCodeCompletionHandler()->CodeCompleteMacroName(false); - PP.LexUnexpandedToken(PeekTok); + PP.LexUnexpandedNonComment(PeekTok); } // If we don't have a pp-identifier now, this is an error. @@ -115,12 +115,12 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.markMacroAsUsed(Macro); } - // Consume identifier. - Result.setEnd(PeekTok.getLocation()); - PP.LexUnexpandedToken(PeekTok); - // If we are in parens, ensure we have a trailing ). if (LParenLoc.isValid()) { + // Consume identifier. + Result.setEnd(PeekTok.getLocation()); + PP.LexUnexpandedNonComment(PeekTok); + if (PeekTok.isNot(tok::r_paren)) { PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined"; PP.Diag(LParenLoc, diag::note_matching) << "("; @@ -129,6 +129,10 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // Consume the ). Result.setEnd(PeekTok.getLocation()); PP.LexNonComment(PeekTok); + } else { + // Consume identifier. + Result.setEnd(PeekTok.getLocation()); + PP.LexNonComment(PeekTok); } // Success, remember that we saw defined(X). @@ -152,7 +156,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, if (PeekTok.is(tok::code_completion)) { if (PP.getCodeCompletionHandler()) PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression(); - PP.LexUnexpandedToken(PeekTok); + PP.LexNonComment(PeekTok); } // If this token's spelling is a pp-identifier, check to see if it is @@ -712,7 +716,7 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Peek ahead one token. Token Tok; - Lex(Tok); + LexNonComment(Tok); // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t. unsigned BitWidth = getTargetInfo().getIntMaxTWidth(); diff --git a/test/Preprocessor/comment_save_if.c b/test/Preprocessor/comment_save_if.c index 2f35bcb9e8..4946122a3f 100644 --- a/test/Preprocessor/comment_save_if.c +++ b/test/Preprocessor/comment_save_if.c @@ -1,6 +1,11 @@ -// RUN: %clang_cc1 %s -E -CC -pedantic 2>&1 | grep -v '^/' | not grep warning +// RUN: %clang_cc1 %s -E -CC -pedantic -verify #if 1 /*bar */ #endif /*foo*/ +#if /*foo*/ defined /*foo*/ FOO /*foo*/ +#if /*foo*/ defined /*foo*/ ( /*foo*/ FOO /*foo*/ ) /*foo*/ +#endif +#endif + diff --git a/test/Preprocessor/expr_define_expansion.c b/test/Preprocessor/expr_define_expansion.c new file mode 100644 index 0000000000..38c0384092 --- /dev/null +++ b/test/Preprocessor/expr_define_expansion.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 %s -E -CC -pedantic -verify + +#define FOO && 1 +#if defined FOO FOO +#endif