Revert r351209 (which was a revert of r350891) with a fix.

The test case had a parse error that was causing the condition string to be misreported. We now have better fallback code for error cases.

llvm-svn: 351470
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index d62a351..3bee026 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -76,18 +76,24 @@
                                                bool isPublic) {
   return new (BP) VisibilityMacroDirective(Loc, isPublic);
 }
-
-/// Read and discard all tokens remaining on the current line until
-/// the tok::eod token is found.
-void Preprocessor::DiscardUntilEndOfDirective() {
-  Token Tmp;
-  do {
-    LexUnexpandedToken(Tmp);
-    assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
-  } while (Tmp.isNot(tok::eod));
-}
-
-/// Enumerates possible cases of #define/#undef a reserved identifier.
+

+/// Read and discard all tokens remaining on the current line until

+/// the tok::eod token is found.

+SourceRange Preprocessor::DiscardUntilEndOfDirective() {

+  Token Tmp;

+  SourceRange Res;

+

+  LexUnexpandedToken(Tmp);

+  Res.setBegin(Tmp.getLocation());

+  while (Tmp.isNot(tok::eod)) {

+    assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");

+    LexUnexpandedToken(Tmp);

+  }

+  Res.setEnd(Tmp.getLocation());

+  return Res;

+}

+

+/// Enumerates possible cases of #define/#undef a reserved identifier.

 enum MacroDiag {
   MD_NoWarn,        //> Not a reserved identifier
   MD_KeywordDef,    //> Macro hides keyword, enabled by default
@@ -535,25 +541,25 @@
 
         // If this is in a skipping block or if we're already handled this #if
         // block, don't bother parsing the condition.
-        if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {
-          DiscardUntilEndOfDirective();
-        } else {
-          const SourceLocation CondBegin = CurPPLexer->getSourceLocation();
-          // Restore the value of LexingRawMode so that identifiers are
-          // looked up, etc, inside the #elif expression.
-          assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
-          CurPPLexer->LexingRawMode = false;
-          IdentifierInfo *IfNDefMacro = nullptr;
-          const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro).Conditional;
-          CurPPLexer->LexingRawMode = true;
-          if (Callbacks) {
-            const SourceLocation CondEnd = CurPPLexer->getSourceLocation();
-            Callbacks->Elif(Tok.getLocation(),
-                            SourceRange(CondBegin, CondEnd),
-                            (CondValue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False), CondInfo.IfLoc);
-          }
-          // If this condition is true, enter it!
-          if (CondValue) {
+        if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {

+          DiscardUntilEndOfDirective();

+        } else {

+          // Restore the value of LexingRawMode so that identifiers are

+          // looked up, etc, inside the #elif expression.

+          assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");

+          CurPPLexer->LexingRawMode = false;

+          IdentifierInfo *IfNDefMacro = nullptr;

+          DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);

+          const bool CondValue = DER.Conditional;

+          CurPPLexer->LexingRawMode = true;

+          if (Callbacks) {

+            Callbacks->Elif(

+                Tok.getLocation(), DER.ExprRange,

+                (CondValue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False),

+                CondInfo.IfLoc);

+          }

+          // If this condition is true, enter it!

+          if (CondValue) {

             CondInfo.FoundNonSkip = true;
             break;
           }
@@ -1113,25 +1119,30 @@
   // If the StrTok is "eod", then it wasn't present.  Otherwise, it must be a
   // string followed by eod.
   if (StrTok.is(tok::eod))
-    ; // ok
-  else if (StrTok.isNot(tok::string_literal)) {
-    Diag(StrTok, diag::err_pp_line_invalid_filename);
-    return DiscardUntilEndOfDirective();
-  } else if (StrTok.hasUDSuffix()) {
-    Diag(StrTok, diag::err_invalid_string_udl);
-    return DiscardUntilEndOfDirective();
-  } else {
-    // Parse and validate the string, converting it into a unique ID.
-    StringLiteralParser Literal(StrTok, *this);
-    assert(Literal.isAscii() && "Didn't allow wide strings in");
-    if (Literal.hadError)
-      return DiscardUntilEndOfDirective();
-    if (Literal.Pascal) {
-      Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
-      return DiscardUntilEndOfDirective();
-    }
-    FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
-
+    ; // ok

+  else if (StrTok.isNot(tok::string_literal)) {

+    Diag(StrTok, diag::err_pp_line_invalid_filename);

+    DiscardUntilEndOfDirective();

+    return;

+  } else if (StrTok.hasUDSuffix()) {

+    Diag(StrTok, diag::err_invalid_string_udl);

+    DiscardUntilEndOfDirective();

+    return;

+  } else {

+    // Parse and validate the string, converting it into a unique ID.

+    StringLiteralParser Literal(StrTok, *this);

+    assert(Literal.isAscii() && "Didn't allow wide strings in");

+    if (Literal.hadError) {

+      DiscardUntilEndOfDirective();

+      return;

+    }

+    if (Literal.Pascal) {

+      Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

+      DiscardUntilEndOfDirective();

+      return;

+    }

+    FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());

+

     // Verify that there is nothing after the string, other than EOD.  Because
     // of C99 6.10.4p5, macros that expand to empty tokens are ok.
     CheckEndOfDirective("line", true);
@@ -1258,25 +1269,30 @@
   // string followed by eod.
   if (StrTok.is(tok::eod)) {
     // Treat this like "#line NN", which doesn't change file characteristics.
-    FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());
-  } else if (StrTok.isNot(tok::string_literal)) {
-    Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
-    return DiscardUntilEndOfDirective();
-  } else if (StrTok.hasUDSuffix()) {
-    Diag(StrTok, diag::err_invalid_string_udl);
-    return DiscardUntilEndOfDirective();
-  } else {
-    // Parse and validate the string, converting it into a unique ID.
-    StringLiteralParser Literal(StrTok, *this);
-    assert(Literal.isAscii() && "Didn't allow wide strings in");
-    if (Literal.hadError)
-      return DiscardUntilEndOfDirective();
-    if (Literal.Pascal) {
-      Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
-      return DiscardUntilEndOfDirective();
-    }
-    FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
-
+    FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());

+  } else if (StrTok.isNot(tok::string_literal)) {

+    Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

+    DiscardUntilEndOfDirective();

+    return;

+  } else if (StrTok.hasUDSuffix()) {

+    Diag(StrTok, diag::err_invalid_string_udl);

+    DiscardUntilEndOfDirective();

+    return;

+  } else {

+    // Parse and validate the string, converting it into a unique ID.

+    StringLiteralParser Literal(StrTok, *this);

+    assert(Literal.isAscii() && "Didn't allow wide strings in");

+    if (Literal.hadError) {

+      DiscardUntilEndOfDirective();

+      return;

+    }

+    if (Literal.Pascal) {

+      Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

+      DiscardUntilEndOfDirective();

+      return;

+    }

+    FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());

+

     // If a filename was present, read any flags that are present.
     if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this))
       return;
@@ -1340,13 +1356,14 @@
       DiscardUntilEndOfDirective();
     return;
   }
-
-  if (StrTok.hasUDSuffix()) {
-    Diag(StrTok, diag::err_invalid_string_udl);
-    return DiscardUntilEndOfDirective();
-  }
-
-  // Verify that there is nothing after the string, other than EOD.
+

+  if (StrTok.hasUDSuffix()) {

+    Diag(StrTok, diag::err_invalid_string_udl);

+    DiscardUntilEndOfDirective();

+    return;

+  }

+

+  // Verify that there is nothing after the string, other than EOD.

   CheckEndOfDirective("ident");
 
   if (Callbacks) {
@@ -2788,31 +2805,29 @@
                                      const Token &HashToken,
                                      bool ReadAnyTokensBeforeDirective) {
   ++NumIf;
-
-  // Parse and evaluate the conditional expression.
-  IdentifierInfo *IfNDefMacro = nullptr;
-  const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
-  const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
-  const bool ConditionalTrue = DER.Conditional;
-  const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
-
-  // If this condition is equivalent to #ifndef X, and if this is the first
-  // directive seen, handle it for the multiple-include optimization.
+

+  // Parse and evaluate the conditional expression.

+  IdentifierInfo *IfNDefMacro = nullptr;

+  const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);

+  const bool ConditionalTrue = DER.Conditional;

+

+  // If this condition is equivalent to #ifndef X, and if this is the first

+  // directive seen, handle it for the multiple-include optimization.

   if (CurPPLexer->getConditionalStackDepth() == 0) {
     if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
       // FIXME: Pass in the location of the macro name, not the 'if' token.
       CurPPLexer->MIOpt.EnterTopLevelIfndef(IfNDefMacro, IfToken.getLocation());
     else
       CurPPLexer->MIOpt.EnterTopLevelConditional();
-  }
-
-  if (Callbacks)
-    Callbacks->If(IfToken.getLocation(),
-                  SourceRange(ConditionalBegin, ConditionalEnd),
-                  (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
-
-  // Should we include the stuff contained by this directive?
-  if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
+  }

+

+  if (Callbacks)

+    Callbacks->If(

+        IfToken.getLocation(), DER.ExprRange,

+        (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));

+

+  // Should we include the stuff contained by this directive?

+  if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {

     // In 'single-file-parse mode' undefined identifiers trigger parsing of all
     // the directive blocks.
     CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
@@ -2899,15 +2914,13 @@
                                        const Token &HashToken) {
   ++NumElse;
 
-  // #elif directive in a non-skipping conditional... start skipping.
-  // We don't care what the condition is, because we will always skip it (since
-  // the block immediately before it was included).
-  const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
-  DiscardUntilEndOfDirective();
-  const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
-
-  PPConditionalInfo CI;
-  if (CurPPLexer->popConditionalLevel(CI)) {
+  // #elif directive in a non-skipping conditional... start skipping.

+  // We don't care what the condition is, because we will always skip it (since

+  // the block immediately before it was included).

+  SourceRange ConditionRange = DiscardUntilEndOfDirective();

+

+  PPConditionalInfo CI;

+  if (CurPPLexer->popConditionalLevel(CI)) {

     Diag(ElifToken, diag::pp_err_elif_without_if);
     return;
   }
@@ -2917,14 +2930,13 @@
     CurPPLexer->MIOpt.EnterTopLevelConditional();
 
   // If this is a #elif with a #else before it, report the error.
-  if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else);
-
-  if (Callbacks)
-    Callbacks->Elif(ElifToken.getLocation(),
-                    SourceRange(ConditionalBegin, ConditionalEnd),
-                    PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
-
-  if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
+  if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else);

+

+  if (Callbacks)

+    Callbacks->Elif(ElifToken.getLocation(), ConditionRange,

+                    PPCallbacks::CVK_NotEvaluated, CI.IfLoc);

+

+  if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {

     // In 'single-file-parse mode' undefined identifiers trigger parsing of all
     // the directive blocks.
     CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false,
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index ac01efad..01ded9c 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -152,8 +152,8 @@
       return true;
     }
     // Consume the ).
-    Result.setEnd(PeekTok.getLocation());
     PP.LexNonComment(PeekTok);
+    Result.setEnd(PeekTok.getLocation());
   } else {
     // Consume identifier.
     Result.setEnd(PeekTok.getLocation());
@@ -842,14 +842,22 @@
 
   PPValue ResVal(BitWidth);
   DefinedTracker DT;
+  SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation());
   if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
     // Parse error, skip the rest of the macro line.
+    SourceRange ConditionRange = ExprStartLoc;
     if (Tok.isNot(tok::eod))
-      DiscardUntilEndOfDirective();
+      ConditionRange = DiscardUntilEndOfDirective();
 
     // Restore 'DisableMacroExpansion'.
     DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
-    return {false, DT.IncludedUndefinedIds};
+
+    // We cannot trust the source range from the value because there was a
+    // parse error. Track the range manually -- the end of the directive is the
+    // end of the condition range.
+    return {false,
+            DT.IncludedUndefinedIds,
+            {ExprStartLoc, ConditionRange.getEnd()}};
   }
 
   // If we are at the end of the expression after just parsing a value, there
@@ -863,7 +871,7 @@
 
     // Restore 'DisableMacroExpansion'.
     DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
-    return {ResVal.Val != 0, DT.IncludedUndefinedIds};
+    return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()};
   }
 
   // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
@@ -876,7 +884,7 @@
 
     // Restore 'DisableMacroExpansion'.
     DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
-    return {false, DT.IncludedUndefinedIds};
+    return {false, DT.IncludedUndefinedIds, ResVal.getRange()};
   }
 
   // If we aren't at the tok::eod token, something bad happened, like an extra
@@ -888,5 +896,5 @@
 
   // Restore 'DisableMacroExpansion'.
   DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
-  return {ResVal.Val != 0, DT.IncludedUndefinedIds};
+  return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()};
 }