[cfe-commits] r50638 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Lex/Preprocessor.h lib/Lex/PPExpressions.cpp lib/Lex/Preprocessor.cpp

Chris Lattner sabre at nondot.org
Sun May 4 23:45:50 PDT 2008


Author: lattner
Date: Mon May  5 01:45:50 2008
New Revision: 50638

URL: http://llvm.org/viewvc/llvm-project?rev=50638&view=rev
Log:
Neil pointed out that clang doesn't generate ranges from diagnostics
related to pp-expressions.  Doing so is pretty simple and this
patch implements it, yielding nice diagnostics like:

t.c:2:7: error: division by zero in preprocessor expression
#if 1 / (0 + 0)
    ~ ^ ~~~~~~~
t.c:5:14: error: expected ')' in preprocessor expression
#if (412 + 42
     ~~~~~~~~^
t.c:5:5: error: to match this '('
#if (412 + 42
    ^
t.c:10:10: warning: left side of operator converted from negative value to unsigned: -42 to 18446744073709551574
#if (-42 + 0U) / -2
     ~~~ ^ ~~
t.c:10:16: warning: right side of operator converted from negative value to unsigned: -2 to 18446744073709551614
#if (-42 + 0U) / -2
    ~~~~~~~~~~ ^ ~~
5 diagnostics generated.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Lex/PPExpressions.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=50638&r1=50637&r2=50638&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon May  5 01:45:50 2008
@@ -201,8 +201,6 @@
      "missing ')' after \"defined\"")
 DIAG(err_pp_colon_without_question, ERROR,
      "':' without preceding '?'")
-DIAG(err_pp_question_without_colon, ERROR,
-     "'?' without following ':'")
 DIAG(err_pp_division_by_zero, ERROR,
      "division by zero in preprocessor expression")
 DIAG(err_pp_remainder_by_zero, ERROR,

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=50638&r1=50637&r2=50638&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Mon May  5 01:45:50 2008
@@ -300,6 +300,11 @@
   /// position in the current buffer into a SourcePosition object for rendering.
   void Diag(SourceLocation Loc, unsigned DiagID);  
   void Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg);
+  void Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
+            const SourceRange &R1, const SourceRange &R2);
+  void Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R);
+  void Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R1,
+            const SourceRange &R2);
   void Diag(const Token &Tok, unsigned DiagID) {
     Diag(Tok.getLocation(), DiagID);
   }

Modified: cfe/trunk/lib/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=50638&r1=50637&r2=50638&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/PPExpressions.cpp (original)
+++ cfe/trunk/lib/Lex/PPExpressions.cpp Mon May  5 01:45:50 2008
@@ -26,7 +26,30 @@
 #include "llvm/ADT/SmallString.h"
 using namespace clang;
 
-static bool EvaluateDirectiveSubExpr(llvm::APSInt &LHS, unsigned MinPrec,
+/// PPValue - Represents the value of a subexpression of a preprocessor
+/// conditional and the source range covered by it.
+class PPValue {
+  SourceRange Range;
+public:
+  llvm::APSInt Val;
+  
+  // Default ctor - Construct an 'invalid' PPValue.
+  PPValue(unsigned BitWidth) : Val(BitWidth) {}
+  
+  unsigned getBitWidth() const { return Val.getBitWidth(); }
+  bool isUnsigned() const { return Val.isUnsigned(); }
+  
+  const SourceRange &getRange() const { return Range; }
+  
+  void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
+  void setRange(SourceLocation B, SourceLocation E) {
+    Range.setBegin(B); Range.setEnd(E); 
+  }
+  void setBegin(SourceLocation L) { Range.setBegin(L); }
+  void setEnd(SourceLocation L) { Range.setEnd(L); }
+};
+
+static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
                                      Token &PeekTok, bool ValueLive,
                                      Preprocessor &PP);
 
@@ -50,8 +73,6 @@
   IdentifierInfo *TheMacro;
 };
 
-
-
 /// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
 /// return the computed value in Result.  Return true if there was an error
 /// parsing.  This function also returns information about the form of the
@@ -60,10 +81,8 @@
 /// If ValueLive is false, then this value is being evaluated in a context where
 /// the result is not used.  As such, avoid diagnostics that relate to
 /// evaluation.
-static bool EvaluateValue(llvm::APSInt &Result, Token &PeekTok,
-                          DefinedTracker &DT, bool ValueLive,
-                          Preprocessor &PP) {
-  Result = 0;
+static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
+                          bool ValueLive, Preprocessor &PP) {
   DT.State = DefinedTracker::Unknown;
   
   // If this token's spelling is a pp-identifier, check to see if it is
@@ -75,22 +94,24 @@
     // turns into "1".
     if (II->getPPKeywordID() != tok::pp_defined) {
       PP.Diag(PeekTok, diag::warn_pp_undef_identifier, II->getName());
-      Result = II->getTokenID() == tok::kw_true;
-      Result.setIsUnsigned(false);  // "0" is signed intmax_t 0.
+      Result.Val = II->getTokenID() == tok::kw_true;
+      Result.Val.setIsUnsigned(false);  // "0" is signed intmax_t 0.
+      Result.setRange(PeekTok.getLocation());
       PP.LexNonComment(PeekTok);
       return false;
     }
 
     // Handle "defined X" and "defined(X)".
+    Result.setBegin(PeekTok.getLocation());
 
     // Get the next token, don't expand it.
     PP.LexUnexpandedToken(PeekTok);
 
     // Two options, it can either be a pp-identifier or a (.
-    bool InParens = false;
+    SourceLocation LParenLoc;
     if (PeekTok.is(tok::l_paren)) {
       // Found a paren, remember we saw it and skip it.
-      InParens = true;
+      LParenLoc = PeekTok.getLocation();
       PP.LexUnexpandedToken(PeekTok);
     }
     
@@ -101,25 +122,28 @@
     }
     
     // Otherwise, we got an identifier, is it defined to something?
-    Result = II->hasMacroDefinition();
-    Result.setIsUnsigned(false);  // Result is signed intmax_t.
+    Result.Val = II->hasMacroDefinition();
+    Result.Val.setIsUnsigned(false);  // Result is signed intmax_t.
 
     // If there is a macro, mark it used.
-    if (Result != 0 && ValueLive) {
+    if (Result.Val != 0 && ValueLive) {
       MacroInfo *Macro = PP.getMacroInfo(II);
       Macro->setIsUsed(true);
     }
 
     // Consume identifier.
+    Result.setEnd(PeekTok.getLocation());
     PP.LexNonComment(PeekTok);
 
     // If we are in parens, ensure we have a trailing ).
-    if (InParens) {
+    if (LParenLoc.isValid()) {
       if (PeekTok.isNot(tok::r_paren)) {
-        PP.Diag(PeekTok, diag::err_pp_missing_rparen);
+        PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen);
+        PP.Diag(LParenLoc, diag::err_matching, "(");
         return true;
       }
       // Consume the ).
+      Result.setEnd(PeekTok.getLocation());
       PP.LexNonComment(PeekTok);
     }
     
@@ -160,26 +184,28 @@
       PP.Diag(PeekTok, diag::ext_longlong);
 
     // Parse the integer literal into Result.
-    if (Literal.GetIntegerValue(Result)) {
+    if (Literal.GetIntegerValue(Result.Val)) {
       // Overflow parsing integer literal.
       if (ValueLive) PP.Diag(PeekTok, diag::warn_integer_too_large);
-      Result.setIsUnsigned(true);
+      Result.Val.setIsUnsigned(true);
     } else {
       // Set the signedness of the result to match whether there was a U suffix
       // or not.
-      Result.setIsUnsigned(Literal.isUnsigned);
+      Result.Val.setIsUnsigned(Literal.isUnsigned);
     
       // Detect overflow based on whether the value is signed.  If signed
       // and if the value is too large, emit a warning "integer constant is so
       // large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
       // is 64-bits.
-      if (!Literal.isUnsigned && Result.isNegative()) {
-        if (ValueLive)PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
-        Result.setIsUnsigned(true);
+      if (!Literal.isUnsigned && Result.Val.isNegative()) {
+        if (ValueLive)
+          PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
+        Result.Val.setIsUnsigned(true);
       }
     }
     
     // Consume the token.
+    Result.setRange(PeekTok.getLocation());
     PP.LexNonComment(PeekTok);
     return false;
   }
@@ -204,19 +230,21 @@
     // Set the signedness.
     Val.setIsUnsigned(!TI.isCharSigned());
     
-    if (Result.getBitWidth() > Val.getBitWidth()) {
-      Result = Val.extend(Result.getBitWidth());
+    if (Result.Val.getBitWidth() > Val.getBitWidth()) {
+      Result.Val = Val.extend(Result.Val.getBitWidth());
     } else {
-      assert(Result.getBitWidth() == Val.getBitWidth() &&
+      assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
              "intmax_t smaller than char/wchar_t?");
-      Result = Val;
+      Result.Val = Val;
     }
 
     // Consume the token.
+    Result.setRange(PeekTok.getLocation());
     PP.LexNonComment(PeekTok);
     return false;
   }
-  case tok::l_paren:
+  case tok::l_paren: {
+    SourceLocation Start = PeekTok.getLocation();
     PP.LexNonComment(PeekTok);  // Eat the (.
     // Parse the value and if there are any binary operators involved, parse
     // them.
@@ -227,63 +255,80 @@
     if (PeekTok.is(tok::r_paren)) {
       // Just use DT unmodified as our result.
     } else {
+      // Otherwise, we have something like (x+y), and we consumed '(x'.
       if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP))
         return true;
       
       if (PeekTok.isNot(tok::r_paren)) {
-        PP.Diag(PeekTok, diag::err_pp_expected_rparen);
+        PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen,
+                Result.getRange());
+        PP.Diag(Start, diag::err_matching, "(");
         return true;
       }
       DT.State = DefinedTracker::Unknown;
     }
+    Result.setRange(Start, PeekTok.getLocation());
     PP.LexNonComment(PeekTok);  // Eat the ).
     return false;
- 
-  case tok::plus:
+  }
+  case tok::plus: {
+    SourceLocation Start = PeekTok.getLocation();
     // Unary plus doesn't modify the value.
     PP.LexNonComment(PeekTok);
-    return EvaluateValue(Result, PeekTok, DT, ValueLive, PP);
+    if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+    Result.setBegin(Start);
+    return false;
+  }
   case tok::minus: {
     SourceLocation Loc = PeekTok.getLocation();
     PP.LexNonComment(PeekTok);
     if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+    Result.setBegin(Loc);
+    
     // C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
-    Result = -Result;
+    Result.Val = -Result.Val;
     
     bool Overflow = false;
     if (Result.isUnsigned())
-      Overflow = Result.isNegative();
-    else if (Result.isMinSignedValue())
+      Overflow = Result.Val.isNegative();
+    else if (Result.Val.isMinSignedValue())
       Overflow = true;   // -MININT is the only thing that overflows.
       
     // If this operator is live and overflowed, report the issue.
     if (Overflow && ValueLive)
-      PP.Diag(Loc, diag::warn_pp_expr_overflow);
+      PP.Diag(Loc, diag::warn_pp_expr_overflow, Result.getRange());
     
     DT.State = DefinedTracker::Unknown;
     return false;
   }
     
-  case tok::tilde:
+  case tok::tilde: {
+    SourceLocation Start = PeekTok.getLocation();
     PP.LexNonComment(PeekTok);
     if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+    Result.setBegin(Start);
+
     // C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
-    Result = ~Result;
+    Result.Val = ~Result.Val;
     DT.State = DefinedTracker::Unknown;
     return false;
+  }
     
-  case tok::exclaim:
+  case tok::exclaim: {
+    SourceLocation Start = PeekTok.getLocation();
     PP.LexNonComment(PeekTok);
     if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
-    Result = !Result;
+    Result.setBegin(Start);
+    Result.Val = !Result.Val;
     // C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
-    Result.setIsUnsigned(false);
+    Result.Val.setIsUnsigned(false);
     
     if (DT.State == DefinedTracker::DefinedMacro)
       DT.State = DefinedTracker::NotDefinedMacro;
     else if (DT.State == DefinedTracker::NotDefinedMacro)
       DT.State = DefinedTracker::DefinedMacro;
     return false;
+  }
     
   // FIXME: Handle #assert
   }
@@ -327,18 +372,19 @@
 
 
 /// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
-/// PeekTok, and whose precedence is PeekPrec.
+/// PeekTok, and whose precedence is PeekPrec.  This returns the result in LHS.
 ///
 /// If ValueLive is false, then this value is being evaluated in a context where
 /// the result is not used.  As such, avoid diagnostics that relate to
-/// evaluation.
-static bool EvaluateDirectiveSubExpr(llvm::APSInt &LHS, unsigned MinPrec,
+/// evaluation, such as division by zero warnings.
+static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
                                      Token &PeekTok, bool ValueLive,
                                      Preprocessor &PP) {
   unsigned PeekPrec = getPrecedence(PeekTok.getKind());
   // If this token isn't valid, report the error.
   if (PeekPrec == ~0U) {
-    PP.Diag(PeekTok, diag::err_pp_expr_bad_token_binop);
+    PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop,
+            LHS.getRange());
     return true;
   }
   
@@ -356,20 +402,20 @@
     // this example, the RHS of the && being dead does not make the rest of the
     // expr dead.
     bool RHSIsLive;
-    if (Operator == tok::ampamp && LHS == 0)
+    if (Operator == tok::ampamp && LHS.Val == 0)
       RHSIsLive = false;   // RHS of "0 && x" is dead.
-    else if (Operator == tok::pipepipe && LHS != 0)
+    else if (Operator == tok::pipepipe && LHS.Val != 0)
       RHSIsLive = false;   // RHS of "1 || x" is dead.
-    else if (Operator == tok::question && LHS == 0)
+    else if (Operator == tok::question && LHS.Val == 0)
       RHSIsLive = false;   // RHS (x) of "0 ? x : y" is dead.
     else
       RHSIsLive = ValueLive;
 
-    // Consume the operator, saving the operator token for error reporting.
-    Token OpToken = PeekTok;
+    // Consume the operator, remembering the operator's location for reporting.
+    SourceLocation OpLoc = PeekTok.getLocation();
     PP.LexNonComment(PeekTok);
 
-    llvm::APSInt RHS(LHS.getBitWidth());
+    PPValue RHS(LHS.getBitWidth());
     // Parse the RHS of the operator.
     DefinedTracker DT;
     if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
@@ -381,7 +427,8 @@
 
     // If this token isn't valid, report the error.
     if (PeekPrec == ~0U) {
-      PP.Diag(PeekTok, diag::err_pp_expr_bad_token_binop);
+      PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop,
+              RHS.getRange());
       return true;
     }
     
@@ -414,15 +461,17 @@
       // If this just promoted something from signed to unsigned, and if the
       // value was negative, warn about it.
       if (ValueLive && Res.isUnsigned()) {
-        if (!LHS.isUnsigned() && LHS.isNegative())
-          PP.Diag(OpToken, diag::warn_pp_convert_lhs_to_positive,
-                  LHS.toStringSigned() + " to " + LHS.toStringUnsigned());
-        if (!RHS.isUnsigned() && RHS.isNegative())
-          PP.Diag(OpToken, diag::warn_pp_convert_rhs_to_positive,
-                  RHS.toStringSigned() + " to " + RHS.toStringUnsigned());
+        if (!LHS.isUnsigned() && LHS.Val.isNegative())
+          PP.Diag(OpLoc, diag::warn_pp_convert_lhs_to_positive,
+                  LHS.Val.toStringSigned() + " to "+LHS.Val.toStringUnsigned(),
+                  LHS.getRange(), RHS.getRange());
+        if (!RHS.isUnsigned() && RHS.Val.isNegative())
+          PP.Diag(OpLoc, diag::warn_pp_convert_rhs_to_positive,
+                  RHS.Val.toStringSigned() + " to "+RHS.Val.toStringUnsigned(),
+                  LHS.getRange(), RHS.getRange());
       }
-      LHS.setIsUnsigned(Res.isUnsigned());
-      RHS.setIsUnsigned(Res.isUnsigned());
+      LHS.Val.setIsUnsigned(Res.isUnsigned());
+      RHS.Val.setIsUnsigned(Res.isUnsigned());
     }
     
     // FIXME: All of these should detect and report overflow??
@@ -430,133 +479,132 @@
     switch (Operator) {
     default: assert(0 && "Unknown operator token!");
     case tok::percent:
-      if (RHS == 0) {
-        if (ValueLive) {
-          PP.Diag(OpToken, diag::err_pp_remainder_by_zero);
-          return true;
-        }
-      } else {
-        Res = LHS % RHS;
+      if (RHS.Val != 0)
+        Res = LHS.Val % RHS.Val;
+      else if (ValueLive) {
+        PP.Diag(OpLoc, diag::err_pp_remainder_by_zero, LHS.getRange(),
+                RHS.getRange());
+        return true;
       }
       break;
     case tok::slash:
-      if (RHS == 0) {
-        if (ValueLive) {
-          PP.Diag(OpToken, diag::err_pp_division_by_zero);
-          return true;
-        }
-        break;
+      if (RHS.Val != 0) {
+        Res = LHS.Val / RHS.Val;
+        if (LHS.Val.isSigned())   // MININT/-1  -->  overflow.
+          Overflow = LHS.Val.isMinSignedValue() && RHS.Val.isAllOnesValue();
+      } else if (ValueLive) {
+        PP.Diag(OpLoc, diag::err_pp_division_by_zero, LHS.getRange(),
+                RHS.getRange());
+        return true;
       }
-
-      Res = LHS / RHS;
-      if (LHS.isSigned())
-        Overflow = LHS.isMinSignedValue() && RHS.isAllOnesValue(); // MININT/-1
       break;
         
     case tok::star:
-      Res = LHS * RHS;
-      if (LHS != 0 && RHS != 0)
-        Overflow = Res/RHS != LHS || Res/LHS != RHS;
+      Res = LHS.Val * RHS.Val;
+      if (LHS.Val != 0 && RHS.Val != 0)
+        Overflow = Res/RHS.Val != LHS.Val || Res/LHS.Val != RHS.Val;
       break;
     case tok::lessless: {
       // Determine whether overflow is about to happen.
-      unsigned ShAmt = static_cast<unsigned>(RHS.getLimitedValue());
-      if (ShAmt >= LHS.getBitWidth())
-        Overflow = true, ShAmt = LHS.getBitWidth()-1;
+      unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
+      if (ShAmt >= LHS.Val.getBitWidth())
+        Overflow = true, ShAmt = LHS.Val.getBitWidth()-1;
       else if (LHS.isUnsigned())
-        Overflow = ShAmt > LHS.countLeadingZeros();
-      else if (LHS.isNonNegative())
-        Overflow = ShAmt >= LHS.countLeadingZeros(); // Don't allow sign change.
+        Overflow = ShAmt > LHS.Val.countLeadingZeros();
+      else if (LHS.Val.isNonNegative()) // Don't allow sign change.
+        Overflow = ShAmt >= LHS.Val.countLeadingZeros();
       else
-        Overflow = ShAmt >= LHS.countLeadingOnes();
+        Overflow = ShAmt >= LHS.Val.countLeadingOnes();
       
-      Res = LHS << ShAmt;
+      Res = LHS.Val << ShAmt;
       break;
     }
     case tok::greatergreater: {
       // Determine whether overflow is about to happen.
-      unsigned ShAmt = static_cast<unsigned>(RHS.getLimitedValue());
+      unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
       if (ShAmt >= LHS.getBitWidth())
         Overflow = true, ShAmt = LHS.getBitWidth()-1;
-      Res = LHS >> ShAmt;
+      Res = LHS.Val >> ShAmt;
       break;
     }
     case tok::plus:
-      Res = LHS + RHS;
+      Res = LHS.Val + RHS.Val;
       if (LHS.isUnsigned())
-        Overflow = Res.ult(LHS);
-      else if (LHS.isNonNegative() == RHS.isNonNegative() &&
-               Res.isNonNegative() != LHS.isNonNegative())
+        Overflow = Res.ult(LHS.Val);
+      else if (LHS.Val.isNonNegative() == RHS.Val.isNonNegative() &&
+               Res.isNonNegative() != LHS.Val.isNonNegative())
         Overflow = true;  // Overflow for signed addition.
       break;
     case tok::minus:
-      Res = LHS - RHS;
+      Res = LHS.Val - RHS.Val;
       if (LHS.isUnsigned())
-        Overflow = Res.ugt(LHS);
-      else if (LHS.isNonNegative() != RHS.isNonNegative() &&
-               Res.isNonNegative() != LHS.isNonNegative())
+        Overflow = Res.ugt(LHS.Val);
+      else if (LHS.Val.isNonNegative() != RHS.Val.isNonNegative() &&
+               Res.isNonNegative() != LHS.Val.isNonNegative())
         Overflow = true;  // Overflow for signed subtraction.
       break;
     case tok::lessequal:
-      Res = LHS <= RHS;
+      Res = LHS.Val <= RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.8p6, result is always int (signed)
       break;
     case tok::less:
-      Res = LHS < RHS;
+      Res = LHS.Val < RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.8p6, result is always int (signed)
       break;
     case tok::greaterequal:
-      Res = LHS >= RHS;
+      Res = LHS.Val >= RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.8p6, result is always int (signed)
       break;
     case tok::greater:
-      Res = LHS > RHS;
+      Res = LHS.Val > RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.8p6, result is always int (signed)
       break;
     case tok::exclaimequal:
-      Res = LHS != RHS;
+      Res = LHS.Val != RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.9p3, result is always int (signed)
       break;
     case tok::equalequal:
-      Res = LHS == RHS;
+      Res = LHS.Val == RHS.Val;
       Res.setIsUnsigned(false);  // C99 6.5.9p3, result is always int (signed)
       break;
     case tok::amp:
-      Res = LHS & RHS;
+      Res = LHS.Val & RHS.Val;
       break;
     case tok::caret:
-      Res = LHS ^ RHS;
+      Res = LHS.Val ^ RHS.Val;
       break;
     case tok::pipe:
-      Res = LHS | RHS;
+      Res = LHS.Val | RHS.Val;
       break;
     case tok::ampamp:
-      Res = (LHS != 0 && RHS != 0);
+      Res = (LHS.Val != 0 && RHS.Val != 0);
       Res.setIsUnsigned(false);  // C99 6.5.13p3, result is always int (signed)
       break;
     case tok::pipepipe:
-      Res = (LHS != 0 || RHS != 0);
+      Res = (LHS.Val != 0 || RHS.Val != 0);
       Res.setIsUnsigned(false);  // C99 6.5.14p3, result is always int (signed)
       break;
     case tok::comma:
       // Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99
       // if not being evaluated.
       if (!PP.getLangOptions().C99 || ValueLive)
-        PP.Diag(OpToken, diag::ext_pp_comma_expr);
-      Res = RHS; // LHS = LHS,RHS -> RHS.
+        PP.Diag(OpLoc, diag::ext_pp_comma_expr, LHS.getRange(), RHS.getRange());
+      Res = RHS.Val; // LHS = LHS,RHS -> RHS.
       break; 
     case tok::question: {
       // Parse the : part of the expression.
       if (PeekTok.isNot(tok::colon)) {
-        PP.Diag(OpToken, diag::err_pp_question_without_colon);
+        PP.Diag(PeekTok.getLocation(), diag::err_expected_colon,
+                LHS.getRange(), RHS.getRange());
+        PP.Diag(OpLoc, diag::err_matching, "?");
         return true;
       }
       // Consume the :.
       PP.LexNonComment(PeekTok);
 
       // Evaluate the value after the :.
-      bool AfterColonLive = ValueLive && LHS == 0;
-      llvm::APSInt AfterColonVal(LHS.getBitWidth());
+      bool AfterColonLive = ValueLive && LHS.Val == 0;
+      PPValue AfterColonVal(LHS.getBitWidth());
       DefinedTracker DT;
       if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
         return true;
@@ -567,7 +615,8 @@
         return true;
       
       // Now that we have the condition, the LHS and the RHS of the :, evaluate.
-      Res = LHS != 0 ? RHS : AfterColonVal;
+      Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
+      RHS.setEnd(AfterColonVal.getRange().getEnd());
 
       // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
       // either operand is unsigned.
@@ -579,16 +628,19 @@
     }
     case tok::colon:
       // Don't allow :'s to float around without being part of ?: exprs.
-      PP.Diag(OpToken, diag::err_pp_colon_without_question);
+      PP.Diag(OpLoc, diag::err_pp_colon_without_question, LHS.getRange(),
+        RHS.getRange());
       return true;
     }
 
     // If this operator is live and overflowed, report the issue.
     if (Overflow && ValueLive)
-      PP.Diag(OpToken, diag::warn_pp_expr_overflow);
+      PP.Diag(OpLoc, diag::warn_pp_expr_overflow,
+              LHS.getRange(), RHS.getRange());
     
     // Put the result back into 'LHS' for our next iteration.
-    LHS = Res;
+    LHS.Val = Res;
+    LHS.setEnd(RHS.getRange().getEnd());
   }
   
   return false;
@@ -606,7 +658,7 @@
   // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
   unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
     
-  llvm::APSInt ResVal(BitWidth);
+  PPValue ResVal(BitWidth);
   DefinedTracker DT;
   if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
     // Parse error, skip the rest of the macro line.
@@ -624,7 +676,7 @@
     if (DT.State == DefinedTracker::NotDefinedMacro)
       IfNDefMacro = DT.TheMacro;
     
-    return ResVal != 0;
+    return ResVal.Val != 0;
   }
   
   // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
@@ -643,6 +695,6 @@
     DiscardUntilEndOfDirective();
   }
   
-  return ResVal != 0;
+  return ResVal.Val != 0;
 }
 

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=50638&r1=50637&r2=50638&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Mon May  5 01:45:50 2008
@@ -124,6 +124,26 @@
   Diags.Report(getFullLoc(Loc), DiagID, &Msg, 1);
 }
 
+void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
+                        const std::string &Msg,
+                        const SourceRange &R1, const SourceRange &R2) {
+  SourceRange R[] = {R1, R2};
+  Diags.Report(getFullLoc(Loc), DiagID, &Msg, 1, R, 2);
+}
+
+
+void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
+                        const SourceRange &R) {
+  Diags.Report(getFullLoc(Loc), DiagID, 0, 0, &R, 1);
+}
+
+void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
+                        const SourceRange &R1, const SourceRange &R2) {
+  SourceRange R[] = {R1, R2};
+  Diags.Report(getFullLoc(Loc), DiagID, 0, 0, R, 2);
+}
+
+
 void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
   llvm::cerr << tok::getTokenName(Tok.getKind()) << " '"
              << getSpelling(Tok) << "'";





More information about the cfe-commits mailing list