forked from OSchip/llvm-project
Improve diagnostic for the case when a non-defined function-like macro is used
in a preprocessor constant expression. llvm-svn: 266495
This commit is contained in:
parent
60469e2ac0
commit
4d247e7012
|
@ -409,6 +409,8 @@ def err_pp_remainder_by_zero : Error<
|
|||
"remainder by zero in preprocessor expression">;
|
||||
def err_pp_expr_bad_token_binop : Error<
|
||||
"token is not a valid binary operator in a preprocessor subexpression">;
|
||||
def err_pp_expr_bad_token_lparen : Error<
|
||||
"function-like macro %0 is not defined">;
|
||||
def err_pp_expr_bad_token_start_expr : Error<
|
||||
"invalid token at start of a preprocessor expression">;
|
||||
def err_pp_invalid_poison : Error<"can only poison identifier tokens">;
|
||||
|
|
|
@ -33,12 +33,18 @@ namespace {
|
|||
/// conditional and the source range covered by it.
|
||||
class PPValue {
|
||||
SourceRange Range;
|
||||
IdentifierInfo *II;
|
||||
public:
|
||||
llvm::APSInt Val;
|
||||
|
||||
// Default ctor - Construct an 'invalid' PPValue.
|
||||
PPValue(unsigned BitWidth) : Val(BitWidth) {}
|
||||
|
||||
// If this value was produced by directly evaluating an identifier, produce
|
||||
// that identifier.
|
||||
IdentifierInfo *getIdentifier() const { return II; }
|
||||
void setIdentifier(IdentifierInfo *II) { this->II = II; }
|
||||
|
||||
unsigned getBitWidth() const { return Val.getBitWidth(); }
|
||||
bool isUnsigned() const { return Val.isUnsigned(); }
|
||||
|
||||
|
@ -209,6 +215,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
bool ValueLive, Preprocessor &PP) {
|
||||
DT.State = DefinedTracker::Unknown;
|
||||
|
||||
Result.setIdentifier(nullptr);
|
||||
|
||||
if (PeekTok.is(tok::code_completion)) {
|
||||
if (PP.getCodeCompletionHandler())
|
||||
PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
|
||||
|
@ -234,6 +242,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
|
||||
Result.Val = II->getTokenID() == tok::kw_true;
|
||||
Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
|
||||
Result.setIdentifier(II);
|
||||
Result.setRange(PeekTok.getLocation());
|
||||
PP.LexNonComment(PeekTok);
|
||||
return false;
|
||||
|
@ -392,6 +401,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
DT.State = DefinedTracker::Unknown;
|
||||
}
|
||||
Result.setRange(Start, PeekTok.getLocation());
|
||||
Result.setIdentifier(nullptr);
|
||||
PP.LexNonComment(PeekTok); // Eat the ).
|
||||
return false;
|
||||
}
|
||||
|
@ -401,6 +411,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
PP.LexNonComment(PeekTok);
|
||||
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
||||
Result.setBegin(Start);
|
||||
Result.setIdentifier(nullptr);
|
||||
return false;
|
||||
}
|
||||
case tok::minus: {
|
||||
|
@ -408,6 +419,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
PP.LexNonComment(PeekTok);
|
||||
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
||||
Result.setBegin(Loc);
|
||||
Result.setIdentifier(nullptr);
|
||||
|
||||
// C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
|
||||
Result.Val = -Result.Val;
|
||||
|
@ -428,6 +440,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
PP.LexNonComment(PeekTok);
|
||||
if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
|
||||
Result.setBegin(Start);
|
||||
Result.setIdentifier(nullptr);
|
||||
|
||||
// C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
|
||||
Result.Val = ~Result.Val;
|
||||
|
@ -443,6 +456,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
|
|||
Result.Val = !Result.Val;
|
||||
// C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
|
||||
Result.Val.setIsUnsigned(false);
|
||||
Result.setIdentifier(nullptr);
|
||||
|
||||
if (DT.State == DefinedTracker::DefinedMacro)
|
||||
DT.State = DefinedTracker::NotDefinedMacro;
|
||||
|
@ -491,6 +505,15 @@ static unsigned getPrecedence(tok::TokenKind Kind) {
|
|||
}
|
||||
}
|
||||
|
||||
static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,
|
||||
Token &Tok) {
|
||||
if (Tok.is(tok::l_paren) && LHS.getIdentifier())
|
||||
PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
|
||||
<< LHS.getIdentifier();
|
||||
else
|
||||
PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
|
||||
<< LHS.getRange();
|
||||
}
|
||||
|
||||
/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
|
||||
/// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS.
|
||||
|
@ -504,8 +527,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
|
|||
unsigned PeekPrec = getPrecedence(PeekTok.getKind());
|
||||
// If this token isn't valid, report the error.
|
||||
if (PeekPrec == ~0U) {
|
||||
PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
|
||||
<< LHS.getRange();
|
||||
diagnoseUnexpectedOperator(PP, LHS, PeekTok);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -548,8 +570,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
|
|||
|
||||
// If this token isn't valid, report the error.
|
||||
if (PeekPrec == ~0U) {
|
||||
PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
|
||||
<< RHS.getRange();
|
||||
diagnoseUnexpectedOperator(PP, RHS, PeekTok);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -769,6 +790,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
|
|||
// Put the result back into 'LHS' for our next iteration.
|
||||
LHS.Val = Res;
|
||||
LHS.setEnd(RHS.getRange().getEnd());
|
||||
RHS.setIdentifier(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
// RUN: not %clang_cc1 -E %s 2>&1 | grep 'invalid token at start of a preprocessor expression'
|
||||
// RUN: not %clang_cc1 -E %s 2>&1 | grep 'token is not a valid binary operator in a preprocessor subexpression'
|
||||
// RUN: not %clang_cc1 -E %s 2>&1 | grep ':14: error: expected end of line in preprocessor expression'
|
||||
// RUN: not %clang_cc1 -E %s 2>&1 | FileCheck %s
|
||||
// PR2220
|
||||
|
||||
// CHECK: invalid token at start of a preprocessor expression
|
||||
#if 1 * * 2
|
||||
#endif
|
||||
|
||||
// CHECK: token is not a valid binary operator in a preprocessor subexpression
|
||||
#if 4 [ 2
|
||||
#endif
|
||||
|
||||
|
||||
// PR2284 - The constant-expr production does not including comma.
|
||||
// CHECK: [[@LINE+1]]:14: error: expected end of line in preprocessor expression
|
||||
#if 1 ? 2 : 0, 1
|
||||
#endif
|
||||
|
||||
// CHECK: [[@LINE+1]]:5: error: function-like macro 'FOO' is not defined
|
||||
#if FOO(1, 2, 3)
|
||||
#endif
|
||||
|
||||
// CHECK: [[@LINE+1]]:9: error: function-like macro 'BAR' is not defined
|
||||
#if 1 + BAR(1, 2, 3)
|
||||
#endif
|
||||
|
||||
// CHECK: [[@LINE+1]]:10: error: token is not a valid binary operator
|
||||
#if (FOO)(1, 2, 3)
|
||||
#endif
|
||||
|
|
|
@ -54,5 +54,5 @@ int has_no_volatile_attribute();
|
|||
int does_not_have_uuid
|
||||
#endif
|
||||
|
||||
#if __has_cpp_attribute(selectany) // expected-error {{token is not a valid binary operator in a preprocessor subexpression}}
|
||||
#if __has_cpp_attribute(selectany) // expected-error {{function-like macro '__has_cpp_attribute' is not defined}}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue