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.

llvm-svn: 136748
This commit is contained in:
Eli Friedman 2011-08-03 00:04:13 +00:00
parent d41f032a45
commit b3bfd84ebb
4 changed files with 32 additions and 10 deletions

View File

@ -556,6 +556,14 @@ public:
DisableMacroExpansion = OldVal; 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 /// LookAhead - This peeks ahead N tokens and returns that token without
/// consuming any tokens. LookAhead(0) returns the next token that would be /// consuming any tokens. LookAhead(0) returns the next token that would be
/// returned by Lex(), LookAhead(1) returns the token after it, etc. This /// returned by Lex(), LookAhead(1) returns the token after it, etc. This

View File

@ -83,20 +83,20 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
Result.setBegin(PeekTok.getLocation()); Result.setBegin(PeekTok.getLocation());
// Get the next token, don't expand it. // 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 (. // Two options, it can either be a pp-identifier or a (.
SourceLocation LParenLoc; SourceLocation LParenLoc;
if (PeekTok.is(tok::l_paren)) { if (PeekTok.is(tok::l_paren)) {
// Found a paren, remember we saw it and skip it. // Found a paren, remember we saw it and skip it.
LParenLoc = PeekTok.getLocation(); LParenLoc = PeekTok.getLocation();
PP.LexUnexpandedToken(PeekTok); PP.LexUnexpandedNonComment(PeekTok);
} }
if (PeekTok.is(tok::code_completion)) { if (PeekTok.is(tok::code_completion)) {
if (PP.getCodeCompletionHandler()) if (PP.getCodeCompletionHandler())
PP.getCodeCompletionHandler()->CodeCompleteMacroName(false); PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
PP.LexUnexpandedToken(PeekTok); PP.LexUnexpandedNonComment(PeekTok);
} }
// If we don't have a pp-identifier now, this is an error. // 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); PP.markMacroAsUsed(Macro);
} }
// Consume identifier.
Result.setEnd(PeekTok.getLocation());
PP.LexUnexpandedToken(PeekTok);
// If we are in parens, ensure we have a trailing ). // If we are in parens, ensure we have a trailing ).
if (LParenLoc.isValid()) { if (LParenLoc.isValid()) {
// Consume identifier.
Result.setEnd(PeekTok.getLocation());
PP.LexUnexpandedNonComment(PeekTok);
if (PeekTok.isNot(tok::r_paren)) { if (PeekTok.isNot(tok::r_paren)) {
PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined"; PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
PP.Diag(LParenLoc, diag::note_matching) << "("; PP.Diag(LParenLoc, diag::note_matching) << "(";
@ -129,6 +129,10 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// Consume the ). // Consume the ).
Result.setEnd(PeekTok.getLocation()); Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok); PP.LexNonComment(PeekTok);
} else {
// Consume identifier.
Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok);
} }
// Success, remember that we saw defined(X). // 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 (PeekTok.is(tok::code_completion)) {
if (PP.getCodeCompletionHandler()) if (PP.getCodeCompletionHandler())
PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression(); PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
PP.LexUnexpandedToken(PeekTok); PP.LexNonComment(PeekTok);
} }
// If this token's spelling is a pp-identifier, check to see if it is // 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. // Peek ahead one token.
Token Tok; Token Tok;
Lex(Tok); LexNonComment(Tok);
// C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t. // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
unsigned BitWidth = getTargetInfo().getIntMaxTWidth(); unsigned BitWidth = getTargetInfo().getIntMaxTWidth();

View File

@ -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 */ #if 1 /*bar */
#endif /*foo*/ #endif /*foo*/
#if /*foo*/ defined /*foo*/ FOO /*foo*/
#if /*foo*/ defined /*foo*/ ( /*foo*/ FOO /*foo*/ ) /*foo*/
#endif
#endif

View File

@ -0,0 +1,5 @@
// RUN: %clang_cc1 %s -E -CC -pedantic -verify
#define FOO && 1
#if defined FOO FOO
#endif