r266495 - Improve diagnostic for the case when a non-defined function-like macro is used

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 15 17:07:11 PDT 2016


Author: rsmith
Date: Fri Apr 15 19:07:09 2016
New Revision: 266495

URL: http://llvm.org/viewvc/llvm-project?rev=266495&view=rev
Log:
Improve diagnostic for the case when a non-defined function-like macro is used
in a preprocessor constant expression.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/lib/Lex/PPExpressions.cpp
    cfe/trunk/test/Preprocessor/expr_invalid_tok.c
    cfe/trunk/test/Preprocessor/has_attribute.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=266495&r1=266494&r2=266495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Fri Apr 15 19:07:09 2016
@@ -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">;

Modified: cfe/trunk/lib/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=266495&r1=266494&r2=266495&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPExpressions.cpp (original)
+++ cfe/trunk/lib/Lex/PPExpressions.cpp Fri Apr 15 19:07:09 2016
@@ -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 &Resul
                           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 &Resul
       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 &Resul
       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 &Resul
     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 &Resul
     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 &Resul
     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 &Resul
     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::Token
   }
 }
 
+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(PPV
   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(PPV
 
     // 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(PPV
     // Put the result back into 'LHS' for our next iteration.
     LHS.Val = Res;
     LHS.setEnd(RHS.getRange().getEnd());
+    RHS.setIdentifier(nullptr);
   }
 }
 

Modified: cfe/trunk/test/Preprocessor/expr_invalid_tok.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/expr_invalid_tok.c?rev=266495&r1=266494&r2=266495&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/expr_invalid_tok.c (original)
+++ cfe/trunk/test/Preprocessor/expr_invalid_tok.c Fri Apr 15 19:07:09 2016
@@ -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

Modified: cfe/trunk/test/Preprocessor/has_attribute.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/has_attribute.c?rev=266495&r1=266494&r2=266495&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/has_attribute.c (original)
+++ cfe/trunk/test/Preprocessor/has_attribute.c Fri Apr 15 19:07:09 2016
@@ -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




More information about the cfe-commits mailing list