diff options
-rw-r--r-- | clang/lib/Lex/PPExpressions.cpp | 36 | ||||
-rw-r--r-- | clang/test/Preprocessor/expr_invalid_tok.c | 5 | ||||
-rw-r--r-- | clang/test/Preprocessor/expr_liveness.c | 4 |
3 files changed, 33 insertions, 12 deletions
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index fb8bae535d1..5ced05c446e 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -362,8 +362,8 @@ static unsigned getPrecedence(tok::TokenKind Kind) { case tok::pipe: return 7; case tok::ampamp: return 6; case tok::pipepipe: return 5; - case tok::comma: return 4; - case tok::question: return 3; + case tok::question: return 4; + case tok::comma: return 3; case tok::colon: return 2; case tok::r_paren: return 0; // Lowest priority, end of expr. case tok::eom: return 0; // Lowest priority, end of macro. @@ -432,14 +432,25 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, return true; } - bool isRightAssoc = Operator == tok::question; + // Decide whether to include the next binop in this subexpression. For + // example, when parsing x+y*z and looking at '*', we want to recursively + // handling y*z as a single subexpression. We do this because the + // precedence of * is higher than that of +. The only strange case we have + // to handle here is for the ?: operator, where the precedence is actually + // lower than the LHS of the '?'. The grammar rule is: + // + // conditional-expression ::= + // logical-OR-expression ? expression : conditional-expression + // where 'expression' is actually comma-expression. + unsigned RHSPrec; + if (Operator == tok::question) + // The RHS of "?" should be maximally consumed as an expression. + RHSPrec = getPrecedence(tok::comma); + else // All others should munch while higher precedence. + RHSPrec = ThisPrec+1; - // Get the precedence of the operator to the right of the RHS. If it binds - // more tightly with RHS than we do, evaluate it completely first. - if (ThisPrec < PeekPrec || - (ThisPrec == PeekPrec && isRightAssoc)) { - if (EvaluateDirectiveSubExpr(RHS, ThisPrec+!isRightAssoc, - PeekTok, RHSIsLive, PP)) + if (PeekPrec >= RHSPrec) { + if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, PP)) return true; PeekPrec = getPrecedence(PeekTok.getKind()); } @@ -609,8 +620,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP)) return true; - // Parse anything after the : RHS that has a higher precedence than ?. - if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1, + // Parse anything after the : with the same precedence as ?. + if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec, PeekTok, AfterColonLive, PP)) return true; @@ -681,7 +692,8 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the // operator and the stuff after it. - if (EvaluateDirectiveSubExpr(ResVal, 1, Tok, true, *this)) { + if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question), + Tok, true, *this)) { // Parse error, skip the rest of the macro line. if (Tok.isNot(tok::eom)) DiscardUntilEndOfDirective(); diff --git a/clang/test/Preprocessor/expr_invalid_tok.c b/clang/test/Preprocessor/expr_invalid_tok.c index 2918bc6536c..82bfca36b8f 100644 --- a/clang/test/Preprocessor/expr_invalid_tok.c +++ b/clang/test/Preprocessor/expr_invalid_tok.c @@ -1,5 +1,6 @@ // RUN: not clang -E %s 2>&1 | grep 'invalid token at start of a preprocessor expression' // RUN: not clang -E %s 2>&1 | grep 'token is not a valid binary operator in a preprocessor subexpression' +// RUN: not clang -E %s 2>&1 | grep ':14: error: expected end of line in preprocessor expression' // PR2220 #if 1 * * 2 @@ -8,3 +9,7 @@ #if 4 [ 2 #endif + +// PR2284 - The constant-expr production does not including comma. +#if 1 ? 2 : 0, 1 +#endif diff --git a/clang/test/Preprocessor/expr_liveness.c b/clang/test/Preprocessor/expr_liveness.c index da30616284c..3f4003ea3af 100644 --- a/clang/test/Preprocessor/expr_liveness.c +++ b/clang/test/Preprocessor/expr_liveness.c @@ -30,6 +30,10 @@ bar #if 1 ? 2 ? 3 : 4 : 5 #endif +// PR2284 +#if 1 ? 0: 1 ? 1/0: 1/0 +#endif + #else |