]> granicus.if.org Git - clang/commitdiff
Support and use token kinds as diagnostic arguments
authorAlp Toker <alp@nuanti.com>
Tue, 24 Dec 2013 09:48:30 +0000 (09:48 +0000)
committerAlp Toker <alp@nuanti.com>
Tue, 24 Dec 2013 09:48:30 +0000 (09:48 +0000)
Introduce proper facilities to render token spellings using the diagnostic
formatter.

Replaces most of the hard-coded diagnostic messages related to expected tokens,
which all shared the same semantics but had to be multiply defined due to
variations in token order or quote marks.

The associated parser changes are largely mechanical but they expose
commonality in whole chunks of the parser that can now be factored away.

This commit uses C++11 typed enums along with a speculative legacy fallback
until the transition is complete.

Requires corresponding changes in LLVM r197895.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@197972 91177308-0d34-0410-b5e6-96231b3b80d8

22 files changed:
include/clang/Basic/Diagnostic.h
include/clang/Basic/DiagnosticCommonKinds.td
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/TokenKinds.h
include/clang/Parse/Parser.h
lib/Basic/Diagnostic.cpp
lib/Lex/PPExpressions.cpp
lib/Lex/PPMacroExpansion.cpp
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseInit.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParseOpenMP.cpp
lib/Parse/ParsePragma.cpp
lib/Parse/ParseStmt.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaExprObjC.cpp

index 4eb080601be45c6c51eb30f0faf30fedbfb2b2e6..2b0b3f9b28ca0f3d36cddc8a57fef71f2d4bdb9c 100644 (file)
@@ -18,6 +18,9 @@
 #include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/SourceLocation.h"
+#if !LLVM_HAS_STRONG_ENUMS
+#include "clang/Basic/TokenKinds.h"
+#endif
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -35,6 +38,11 @@ namespace clang {
   class Preprocessor;
   class DiagnosticErrorTrap;
   class StoredDiagnostic;
+#if LLVM_HAS_STRONG_ENUMS
+  namespace tok {
+  enum TokenKind : unsigned;
+  }
+#endif
 
 /// \brief Annotates a diagnostic with some code that should be
 /// inserted, removed, or replaced to fix the problem.
@@ -151,6 +159,7 @@ public:
     ak_c_string,        ///< const char *
     ak_sint,            ///< int
     ak_uint,            ///< unsigned
+    ak_tokenkind,       ///< enum TokenKind : unsigned
     ak_identifierinfo,  ///< IdentifierInfo
     ak_qualtype,        ///< QualType
     ak_declarationname, ///< DeclarationName
@@ -1027,6 +1036,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
   return DB;
 }
 
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+                                           tok::TokenKind I) {
+  DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind);
+  return DB;
+}
+
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                            const IdentifierInfo *II) {
   DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
index c54bafc07fe8d34e480f74e0f9b14cad8dce2860..12c3e759ce4d56be7b216cd7ad0ac1353a81d638 100644 (file)
@@ -30,7 +30,7 @@ def note_type_being_defined : Note<
   "definition of %0 is not complete until the closing '}'">;
 /// note_matching - this is used as a continuation of a previous diagnostic,
 /// e.g. to specify the '(' when we expected a ')'.
-def note_matching : Note<"to match this '%0'">;
+def note_matching : Note<"to match this %0">;
 
 def note_using : Note<"using">;
 def note_possibility : Note<"one possibility">;
@@ -60,6 +60,10 @@ def err_invalid_numeric_udl : Error<
 
 let CategoryName = "Parse Issue" in {
 
+def err_expected : Error<"expected %0">;
+def err_expected_either : Error<"expected %0 or %1">;
+def err_expected_after : Error<"expected %1 after %0">;
+
 def err_param_redefinition : Error<"redefinition of parameter %0">;
 def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
 def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">,
index 0aa2f32481cc6ece346256fba38b7095706cf543..2f14a50cf70b57baacc2585d1a0429c3adac86b5 100644 (file)
@@ -149,18 +149,10 @@ def err_expected_expression : Error<"expected expression">;
 def err_expected_type : Error<"expected a type">;
 def err_expected_external_declaration : Error<"expected external declaration">;
 def err_extraneous_closing_brace : Error<"extraneous closing brace ('}')">;
-def err_expected_ident : Error<"expected identifier">;
-def err_expected_ident_lparen : Error<"expected identifier or '('">;
-def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
-def err_expected_lbrace : Error<"expected '{'">;
 def err_expected_lparen : Error<"expected '('">;
-def err_expected_lparen_or_lbrace : Error<"expected '(' or '{'">;
 def err_expected_rparen : Error<"expected ')'">;
-def err_expected_lsquare : Error<"expected '['">;
 def err_expected_rsquare : Error<"expected ']'">;
-def err_expected_rbrace : Error<"expected '}'">;
 def err_expected_greater : Error<"expected '>'">;
-def err_expected_ggg : Error<"expected '>>>'">;
 def err_expected_semi_declaration : Error<
   "expected ';' at end of declaration">;
 def err_expected_semi_decl_list : Error<
@@ -186,12 +178,10 @@ def err_expected_method_body : Error<"expected method body">;
 def err_invalid_token_after_toplevel_declarator : Error<
   "expected ';' after top level declarator">;
 def err_invalid_token_after_declarator_suggest_equal : Error<
-  "invalid '%0' at end of declaration; did you mean '='?">;
+  "invalid %0 at end of declaration; did you mean '='?">;
 def err_expected_statement : Error<"expected statement">;
 def err_expected_lparen_after : Error<"expected '(' after '%0'">;
-def err_expected_lparen_after_id : Error<"expected '(' after %0">;
 def err_expected_less_after : Error<"expected '<' after '%0'">;
-def err_expected_equal_after : Error<"expected '=' after %0">;
 def err_expected_comma : Error<"expected ','">;
 def err_expected_lbrace_in_compound_literal : Error<
   "expected '{' in compound literal">;
@@ -218,7 +208,6 @@ def err_expected_semi_after_attribute_list : Error<
 def err_expected_semi_after_static_assert : Error<
   "expected ';' after static_assert">;
 def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
-def err_expected_colon_after : Error<"expected ':' after %0">;
 def warn_missing_selector_name : Warning<
   "%0 used as the name of the previous parameter rather than as part "
   "of the selector">,
@@ -481,9 +470,6 @@ def warn_cxx98_compat_noexcept_decl : Warning<
   "noexcept specifications are incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
 def err_expected_catch : Error<"expected catch">;
-def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
-def err_expected_rbrace_or_comma : Error<"expected '}' or ','">;
-def err_expected_rsquare_or_comma : Error<"expected ']' or ','">;
 def err_using_namespace_in_class : Error<
   "'using namespace' is not allowed in classes">;
 def err_constructor_bad_name : Error<
index 838ce635423e74bbafa19e0459c337bb71f4efb6..3a3c93da125352033cc052129c68e2b2232d236e 100644 (file)
@@ -5752,7 +5752,6 @@ def err_incomplete_type_used_in_type_trait_expr : Error<
   
 def err_dimension_expr_not_constant_integer : Error<
   "dimension expression does not evaluate to a constant unsigned int">;
-def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
 
 def err_typecheck_cond_incompatible_operands_null : Error<
   "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
index dcbe1da1115d98f7aebd7b8d430af4189f69c31d..029cbdd48c804769db460e8d9e3185dd3ec1ca37 100644 (file)
 #ifndef LLVM_CLANG_TOKENKINDS_H
 #define LLVM_CLANG_TOKENKINDS_H
 
+#include "llvm/Support/Compiler.h"
+
 namespace clang {
 
 namespace tok {
 
 /// \brief Provides a simple uniform namespace for tokens from all C languages.
-enum TokenKind {
+enum TokenKind LLVM_ENUM_INT_TYPE(unsigned) {
 #define TOK(X) X,
 #include "clang/Basic/TokenKinds.def"
   NUM_TOKENS
index bc33a7428f4b74e57adf5071c0c23ba6834e9b26..1383698c3f04dfc3f427e8d3bbfb4f5c29f81ac7 100644 (file)
@@ -342,16 +342,16 @@ private:
   SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
     if (isTokenParen())
       return ConsumeParen();
-    else if (isTokenBracket())
+    if (isTokenBracket())
       return ConsumeBracket();
-    else if (isTokenBrace())
+    if (isTokenBrace())
       return ConsumeBrace();
-    else if (isTokenStringLiteral())
+    if (isTokenStringLiteral())
       return ConsumeStringToken();
-    else if (ConsumeCodeCompletionTok && Tok.is(tok::code_completion))
-      return ConsumeCodeCompletionToken();
-    else
-      return ConsumeToken();
+    if (Tok.is(tok::code_completion))
+      return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
+                                      : handleUnexpectedCodeCompletionToken();
+    return ConsumeToken();
   }
 
   /// ConsumeParen - This consume method keeps the paren count up-to-date.
index 45d4b539e8c2168a17ab3cf03439ca8eb5094fa1..4a6f070af70367293809cc09f7d9a86413939f02 100644 (file)
@@ -639,6 +639,16 @@ static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
   }
 }
 
+/// \brief Returns the friendly name for a token kind that will / appear
+// without quotes in diagnostic messages.
+static const char *getTokenNameForDiagnostic(tok::TokenKind Kind) {
+  switch (Kind) {
+  case tok::identifier:
+    return "identifier";
+  default:
+    return 0;
+  }
+}
 
 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
 /// formal arguments into the %0 slots.  The result is appended onto the Str
@@ -812,6 +822,25 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
       }
       break;
     }
+    // ---- TOKEN SPELLINGS ----
+    case DiagnosticsEngine::ak_tokenkind: {
+      tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
+      assert(ModifierLen == 0 && "No modifiers for token kinds yet");
+
+      llvm::raw_svector_ostream Out(OutStr);
+      if (const char *S = getTokenNameForDiagnostic(Kind))
+        // Unquoted translatable token name.
+        Out << S;
+      else if (const char *S = tok::getTokenSimpleSpelling(Kind))
+        // Quoted token spelling, currently only covers punctuators.
+        Out << '\'' << S << '\'';
+      else if (const char *S = tok::getTokenName(Kind))
+        // Debug name, shouldn't appear in user-facing diagnostics.
+        Out << '<' << S << '>';
+      else
+        Out << "(null)";
+      break;
+    }
     // ---- NAMES and TYPES ----
     case DiagnosticsEngine::ak_identifierinfo: {
       const IdentifierInfo *II = getArgIdentifier(ArgNo);
index 87c0a6ace6cbc23c4c81c59b735658c0a317be1d..c561ec790e5f1cdc555736d7dee044b741cbdc0c 100644 (file)
@@ -131,7 +131,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
 
     if (PeekTok.isNot(tok::r_paren)) {
       PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
-      PP.Diag(LParenLoc, diag::note_matching) << "(";
+      PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
       return true;
     }
     // Consume the ).
@@ -342,7 +342,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
       if (PeekTok.isNot(tok::r_paren)) {
         PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
           << Result.getRange();
-        PP.Diag(Start, diag::note_matching) << "(";
+        PP.Diag(Start, diag::note_matching) << tok::l_paren;
         return true;
       }
       DT.State = DefinedTracker::Unknown;
@@ -682,7 +682,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
       if (PeekTok.isNot(tok::colon)) {
         PP.Diag(PeekTok.getLocation(), diag::err_expected_colon)
           << LHS.getRange(), RHS.getRange();
-        PP.Diag(OpLoc, diag::note_matching) << "?";
+        PP.Diag(OpLoc, diag::note_matching) << tok::question;
         return true;
       }
       // Consume the :.
index 49acd2515d65df5439bfc90df16d936dc8e227ac..8ad11c0a6b95cff5d8dd6131d1316217b81d16da 100644 (file)
@@ -1144,7 +1144,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
   if (Tok.isNot(tok::r_paren)) {
     PP.Diag(PP.getLocForEndOfToken(FilenameLoc), diag::err_pp_missing_rparen)
         << II->getName();
-    PP.Diag(LParenLoc, diag::note_matching) << "(";
+    PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
     return false;
   }
 
@@ -1226,7 +1226,7 @@ static bool EvaluateBuildingModule(Token &Tok,
   // Ensure we have a trailing ).
   if (Tok.isNot(tok::r_paren)) {
     PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
-    PP.Diag(LParenLoc, diag::note_matching) << "(";
+    PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
     return false;
   }
 
index 594baa1edaad5f2f219d2c8c6b8c0108c1bc986c..95502143b0f729623504e0c2889f0b62c15e9f25 100644 (file)
@@ -670,7 +670,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
                          /*StopAtSemi=*/true,
                          /*ConsumeFinalToken=*/false);
     if (Tok.isNot(tok::l_brace))
-      return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+      return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
 
     Toks.push_back(Tok);
     ConsumeBrace();
@@ -703,8 +703,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
       Toks.push_back(Tok);
       ConsumeParen();
       if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) {
-        Diag(Tok.getLocation(), diag::err_expected_rparen);
-        Diag(OpenLoc, diag::note_matching) << "(";
+        Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
+        Diag(OpenLoc, diag::note_matching) << tok::l_paren;
         return true;
       }
     }
@@ -751,13 +751,15 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
                                 /*ConsumeFinalToken=*/false)) {
         // We're not just missing the initializer, we're also missing the
         // function body!
-        return Diag(Tok.getLocation(), diag::err_expected_lbrace);
+        return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;
       }
     } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {
       // We found something weird in a mem-initializer-id.
-      return Diag(Tok.getLocation(), getLangOpts().CPlusPlus11
-                                         ? diag::err_expected_lparen_or_lbrace
-                                         : diag::err_expected_lparen);
+      if (getLangOpts().CPlusPlus11)
+        return Diag(Tok.getLocation(), diag::err_expected_either)
+               << tok::l_paren << tok::l_brace;
+      else
+        return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
     }
 
     tok::TokenKind kind = Tok.getKind();
@@ -779,11 +781,10 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
     // Grab the initializer (or the subexpression of the template argument).
     // FIXME: If we support lambdas here, we'll need to set StopAtSemi to false
     //        if we might be inside the braces of a lambda-expression.
-    if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace,
-                              Toks, /*StopAtSemi=*/true)) {
-      Diag(Tok, IsLParen ? diag::err_expected_rparen :
-                           diag::err_expected_rbrace);
-      Diag(OpenLoc, diag::note_matching) << (IsLParen ? "(" : "{");
+    tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;
+    if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) {
+      Diag(Tok, diag::err_expected) << CloseKind;
+      Diag(OpenLoc, diag::note_matching) << kind;
       return true;
     }
 
@@ -817,7 +818,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
       ConsumeBrace();
       return false;
     } else if (!MightBeTemplateArgument) {
-      return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+      return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+                                                                << tok::comma;
     }
   }
 }
index e8149d3c9fddc4b1d1090a2d17a395dcb7a09c89..27d8531c1fdb82247da1bb7ccd5cb13c6fb21746 100644 (file)
@@ -813,7 +813,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
   // Opening '('.
   BalancedDelimiterTracker T(*this, tok::l_paren);
   if (T.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lparen);
+    Diag(Tok, diag::err_expected) << tok::l_paren;
     return;
   }
 
@@ -865,8 +865,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
     }
 
     if (Tok.isNot(tok::equal)) {
-      Diag(Tok, diag::err_expected_equal_after)
-        << Keyword;
+      Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
       SkipUntil(tok::r_paren, StopAtSemi);
       return;
     }
@@ -978,7 +977,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
   // Opening '('.
   BalancedDelimiterTracker T(*this, tok::l_paren);
   if (T.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lparen);
+    Diag(Tok, diag::err_expected) << tok::l_paren;
     return;
   }
   
@@ -990,7 +989,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
   }
   IdentifierLoc *RelatedClass = ParseIdentifierLoc();
   if (!TryConsumeToken(tok::comma)) {
-    Diag(Tok, diag::err_expected_comma);
+    Diag(Tok, diag::err_expected) << tok::comma;
     SkipUntil(tok::r_paren, StopAtSemi);
     return;
   }
@@ -1009,7 +1008,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
     if (Tok.is(tok::colon))
       Diag(Tok, diag::err_objcbridge_related_selector_name);
     else
-      Diag(Tok, diag::err_expected_comma);
+      Diag(Tok, diag::err_expected) << tok::comma;
     SkipUntil(tok::r_paren, StopAtSemi);
     return;
   }
@@ -1019,7 +1018,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
   if (Tok.is(tok::identifier))
     InstanceMethod = ParseIdentifierLoc();
   else if (Tok.isNot(tok::r_paren)) {
-    Diag(Tok, diag::err_expected_rparen);
+    Diag(Tok, diag::err_expected) << tok::r_paren;
     SkipUntil(tok::r_paren, StopAtSemi);
     return;
   }
@@ -1271,14 +1270,14 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
   T.consumeOpen();
 
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident);
+    Diag(Tok, diag::err_expected) << tok::identifier;
     T.skipToEnd();
     return;
   }
   IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
 
   if (Tok.isNot(tok::comma)) {
-    Diag(Tok, diag::err_expected_comma);
+    Diag(Tok, diag::err_expected) << tok::comma;
     T.skipToEnd();
     return;
   }
@@ -1295,7 +1294,7 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
   bool MustBeNull = false;
   while (TryConsumeToken(tok::comma)) {
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       T.skipToEnd();
       return;
     }
@@ -3471,7 +3470,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
       ConsumeToken();
       ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
       if (!Tok.is(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
         SkipUntil(tok::semi);
         continue;
       }
@@ -3612,7 +3611,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
       return;
 
     if (SS.isSet() && Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       if (Tok.isNot(tok::l_brace)) {
         // Has no name and is not a definition.
         // Skip the rest of this declarator, up until the comma or semicolon.
@@ -3625,7 +3624,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
   // Must have either 'enum name' or 'enum {...}'.
   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
       !(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
-    Diag(Tok, diag::err_expected_ident_lbrace);
+    Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
 
     // Skip the rest of this declarator, up until the comma or semicolon.
     SkipUntil(tok::comma, StopAtSemi);
@@ -4924,7 +4923,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
               << getLangOpts().CPlusPlus;
       }
     } else
-      Diag(Tok, diag::err_expected_ident_lparen);
+      Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_paren;
     D.SetIdentifier(0, Tok.getLocation());
     D.setInvalidType(true);
   }
@@ -5316,7 +5315,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
   do {
     // If this isn't an identifier, report the error and skip until ')'.
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
       // Forget we parsed anything.
       ParamInfo.clear();
index 4f86ba42db2c6377567bbc27b86852605a291756..cf86b43abb9db6a12359b43ff78de96501dba602 100644 (file)
@@ -91,7 +91,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
 
   if (Tok.is(tok::equal)) {
     if (Ident == 0) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       // Skip to end of the definition and eat the ';'.
       SkipUntil(tok::semi);
       return 0;
@@ -111,8 +111,12 @@ Decl *Parser::ParseNamespace(unsigned Context,
       Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon)
           << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
     }
-    Diag(Tok, Ident ? diag::err_expected_lbrace :
-         diag::err_expected_ident_lbrace);
+
+    if (Ident)
+      Diag(Tok, diag::err_expected) << tok::l_brace;
+    else
+      Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
+
     return 0;
   }
 
@@ -649,7 +653,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
 
   BalancedDelimiterTracker T(*this, tok::l_paren);
   if (T.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lparen);
+    Diag(Tok, diag::err_expected) << tok::l_paren;
     SkipMalformedDecl();
     return 0;
   }
@@ -1202,7 +1206,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
       DS.SetTypeSpecError();
     if (SS.isSet())
       if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
   }
 
   TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
@@ -2798,7 +2802,8 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
         << FixItHint::CreateInsertion(Loc, ", ");
     } else {
       // Skip over garbage, until we get to '{'.  Don't eat the '{'.
-      Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+      Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+                                                         << tok::comma;
       SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
       break;
     }
@@ -2896,9 +2901,10 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
                                        T.getCloseLocation(), EllipsisLoc);
   }
 
-  Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace
-                                  : diag::err_expected_lparen);
-  return true;
+  if (getLangOpts().CPlusPlus11)
+    return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
+  else
+    return Diag(Tok, diag::err_expected) << tok::l_paren;
 }
 
 /// \brief Parse a C++ exception-specification if present (C++0x [except.spec]).
@@ -3261,7 +3267,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
 
       AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
       if (!AttrName) {
-        Diag(Tok.getLocation(), diag::err_expected_ident);
+        Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
         SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);
         continue;
       }
@@ -3393,7 +3399,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
   
   BalancedDelimiterTracker Braces(*this, tok::l_brace);
   if (Braces.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return;
   }
 
index db66ac52ffcab564ca6831c70979ed5b03095a1e..9abc5a3aefa3952262c3bd55e41e85e1d6dc76fe 100644 (file)
@@ -294,7 +294,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
         
         Diag(Tok, diag::err_expected_colon)
           << FixItHint::CreateInsertion(FILoc, FIText);
-        Diag(OpToken, diag::note_matching) << "?";
+        Diag(OpToken, diag::note_matching) << tok::question;
         ColonLoc = Tok.getLocation();
       }
     }
@@ -915,7 +915,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   case tok::ampamp: {      // unary-expression: '&&' identifier
     SourceLocation AmpAmpLoc = ConsumeToken();
     if (Tok.isNot(tok::identifier))
-      return ExprError(Diag(Tok, diag::err_expected_ident));
+      return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
 
     if (getCurScope()->getFnParent() == 0)
       return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
@@ -1289,8 +1289,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
           SkipUntil(tok::greatergreatergreater, StopAtSemi);
         } else {
           // There was an error closing the brackets
-          Diag(Tok, diag::err_expected_ggg);
-          Diag(OpenLoc, diag::note_matching) << "<<<";
+          Diag(Tok, diag::err_expected) << tok::greatergreatergreater;
+          Diag(OpenLoc, diag::note_matching) << tok::lesslessless;
           SkipUntil(tok::greatergreatergreater, StopAtSemi);
           LHS = ExprError();
         }
@@ -1512,7 +1512,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
 
     isCastExpr = false;
     if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
-      Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+      Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()
+                                          << tok::l_paren;
       return ExprError();
     }
 
@@ -1684,8 +1685,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
 
   // All of these start with an open paren.
   if (Tok.isNot(tok::l_paren))
-    return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
-                       << BuiltinII);
+    return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII
+                                                         << tok::l_paren);
 
   BalancedDelimiterTracker PT(*this, tok::l_paren);
   PT.consumeOpen();
@@ -1703,7 +1704,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
     TypeResult Ty = ParseTypeName();
 
     if (Tok.isNot(tok::r_paren)) {
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
       Expr = ExprError();
     }
 
@@ -1726,7 +1727,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
 
     // We must have at least one identifier here.
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       SkipUntil(tok::r_paren, StopAtSemi);
       return ExprError();
     }
@@ -1748,7 +1749,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
         Comps.back().LocStart = ConsumeToken();
 
         if (Tok.isNot(tok::identifier)) {
-          Diag(Tok, diag::err_expected_ident);
+          Diag(Tok, diag::err_expected) << tok::identifier;
           SkipUntil(tok::r_paren, StopAtSemi);
           return ExprError();
         }
@@ -1814,7 +1815,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
       return Expr2;
     }
     if (Tok.isNot(tok::r_paren)) {
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
       return ExprError();
     }
     Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
@@ -1840,7 +1841,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
     
     // Attempt to consume the r-paren.
     if (Tok.isNot(tok::r_paren)) {
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
       SkipUntil(tok::r_paren, StopAtSemi);
       return ExprError();
     }
@@ -1868,7 +1869,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
     
     // Attempt to consume the r-paren.
     if (Tok.isNot(tok::r_paren)) {
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
       SkipUntil(tok::r_paren, StopAtSemi);
       return ExprError();
     }
index 38bf76ae21340b099c8c8bfd97d1922fead8907e..61dfbc6d58c083f27751771defc1c8fdecde53e6 100644 (file)
@@ -1187,7 +1187,7 @@ ExprResult Parser::ParseCXXCasts() {
   SourceLocation RAngleBracketLoc = Tok.getLocation();
 
   if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
-    return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
+    return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less);
 
   SourceLocation LParenLoc, RParenLoc;
   BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -2163,7 +2163,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
       SuffixLoc = ConsumeToken();
       TokLocs.push_back(SuffixLoc);
     } else {
-      Diag(Tok.getLocation(), diag::err_expected_ident);
+      Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
       return true;
     }
 
index 56d8edcdb41be22024163aa9ea8b716679998b6d..c21dbba47a7ca6a738f825191281856af8e0e5c6 100644 (file)
@@ -493,7 +493,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
   
   BalancedDelimiterTracker Braces(*this, tok::l_brace);
   if (Braces.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return false;
   }
 
index 29356d0fc74bdbe1ea663faf3beaeb0f24620a21..6f83707d05b0b48bbd8a3991c801d30fc11a008c 100644 (file)
@@ -107,7 +107,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
   while (1) {
     MaybeSkipAttributes(tok::objc_class);
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       SkipUntil(tok::semi);
       return Actions.ConvertDeclToDeclGroup(0);
     }
@@ -195,7 +195,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
   MaybeSkipAttributes(tok::objc_interface);
 
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident); // missing class or category name.
+    Diag(Tok, diag::err_expected)
+        << tok::identifier; // missing class or category name.
     return 0;
   }
 
@@ -222,7 +223,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
       categoryLoc = ConsumeToken();
     }
     else if (!getLangOpts().ObjC2) {
-      Diag(Tok, diag::err_expected_ident); // missing category name.
+      Diag(Tok, diag::err_expected)
+          << tok::identifier; // missing category name.
       return 0;
     }
    
@@ -274,7 +276,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
     }
 
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident); // missing super class name.
+      Diag(Tok, diag::err_expected)
+          << tok::identifier; // missing super class name.
       return 0;
     }
     superClassId = Tok.getIdentifierInfo();
@@ -1086,7 +1089,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
     }
     
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident); // missing argument name.
+      Diag(Tok, diag::err_expected)
+          << tok::identifier; // missing argument name.
       break;
     }
 
@@ -1198,7 +1202,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
     }
 
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       SkipUntil(tok::greater, StopAtSemi);
       return true;
     }
@@ -1412,7 +1416,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
   MaybeSkipAttributes(tok::objc_protocol);
 
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident); // missing protocol name.
+    Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name.
     return DeclGroupPtrTy();
   }
   // Save the protocol name, then consume it.
@@ -1436,7 +1440,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
     while (1) {
       ConsumeToken(); // the ','
       if (Tok.isNot(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
         SkipUntil(tok::semi);
         return DeclGroupPtrTy();
       }
@@ -1505,7 +1509,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
   MaybeSkipAttributes(tok::objc_implementation);
 
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident); // missing class or category name.
+    Diag(Tok, diag::err_expected)
+        << tok::identifier; // missing class or category name.
     return DeclGroupPtrTy();
   }
   // We have a class or category name - consume it.
@@ -1529,11 +1534,12 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
       categoryId = Tok.getIdentifierInfo();
       categoryLoc = ConsumeToken();
     } else {
-      Diag(Tok, diag::err_expected_ident); // missing category name.
+      Diag(Tok, diag::err_expected)
+          << tok::identifier; // missing category name.
       return DeclGroupPtrTy();
     }
     if (Tok.isNot(tok::r_paren)) {
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
       SkipUntil(tok::r_paren); // don't stop at ';'
       return DeclGroupPtrTy();
     }
@@ -1556,7 +1562,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
       // We have a super class
       ConsumeToken();
       if (Tok.isNot(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident); // missing super class name.
+        Diag(Tok, diag::err_expected)
+            << tok::identifier; // missing super class name.
         return DeclGroupPtrTy();
       }
       superClassId = Tok.getIdentifierInfo();
@@ -1655,13 +1662,13 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
   ConsumeToken(); // consume compatibility_alias
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident);
+    Diag(Tok, diag::err_expected) << tok::identifier;
     return 0;
   }
   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
   if (Tok.isNot(tok::identifier)) {
-    Diag(Tok, diag::err_expected_ident);
+    Diag(Tok, diag::err_expected) << tok::identifier;
     return 0;
   }
   IdentifierInfo *classId = Tok.getIdentifierInfo();
@@ -1716,7 +1723,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
       }
       
       if (Tok.isNot(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
         break;
       }
       propertyIvar = Tok.getIdentifierInfo();
@@ -1751,7 +1758,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
     }
     
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_expected_ident);
+      Diag(Tok, diag::err_expected) << tok::identifier;
       SkipUntil(tok::semi);
       return 0;
     }
@@ -1806,7 +1813,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
     ConsumeParen();  // ')'
   } else {
     if (!operand.isInvalid())
-      Diag(Tok, diag::err_expected_rparen);
+      Diag(Tok, diag::err_expected) << tok::r_paren;
 
     // Skip forward until we see a left brace, but don't consume it.
     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
@@ -1815,7 +1822,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
   // Require a compound statement.
   if (Tok.isNot(tok::l_brace)) {
     if (!operand.isInvalid())
-      Diag(Tok, diag::err_expected_lbrace);
+      Diag(Tok, diag::err_expected) << tok::l_brace;
     return StmtError();
   }
 
@@ -1855,7 +1862,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
 
   ConsumeToken(); // consume try
   if (Tok.isNot(tok::l_brace)) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return StmtError();
   }
   StmtVector CatchStmts;
@@ -1905,7 +1912,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
         if (Tok.is(tok::l_brace))
           CatchBody = ParseCompoundStatementBody();
         else
-          Diag(Tok, diag::err_expected_lbrace);
+          Diag(Tok, diag::err_expected) << tok::l_brace;
         if (CatchBody.isInvalid())
           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
         
@@ -1931,7 +1938,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
       if (Tok.is(tok::l_brace))
         FinallyBody = ParseCompoundStatementBody();
       else
-        Diag(Tok, diag::err_expected_lbrace);
+        Diag(Tok, diag::err_expected) << tok::l_brace;
       if (FinallyBody.isInvalid())
         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
@@ -1957,7 +1964,7 @@ StmtResult
 Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
   ConsumeToken(); // consume autoreleasepool
   if (Tok.isNot(tok::l_brace)) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return StmtError();
   }
   // Enter a scope to hold everything within the compound stmt.  Compound
@@ -2572,7 +2579,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
       KeyExprs.push_back(Res.release());
     }
   } else if (!selIdent) {
-    Diag(Tok, diag::err_expected_ident); // missing selector name.
+    Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
 
     // We must manually skip to a ']', otherwise the expression skipper will
     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
@@ -2730,7 +2737,8 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
     if (Tok.is(tok::comma))
       ConsumeToken(); // Eat the ','.
     else if (Tok.isNot(tok::r_square))
-     return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma));
+      return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
+                                                            << tok::comma);
   }
   SourceLocation EndLoc = ConsumeBracket(); // location of ']'
   MultiExprArg Args(ElementExprs);
@@ -2755,10 +2763,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
       }
     }
 
-    if (Tok.is(tok::colon)) {
-      ConsumeToken();
-    } else {
-      Diag(Tok, diag::err_expected_colon);
+    if (!TryConsumeToken(tok::colon)) {
+      Diag(Tok, diag::err_expected) << tok::colon;
       SkipUntil(tok::r_brace, StopAtSemi);
       return ExprError();
     }
@@ -2774,9 +2780,9 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
     
     // Parse the ellipsis that designates this as a pack expansion.
     SourceLocation EllipsisLoc;
-    if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus)
-      EllipsisLoc = ConsumeToken();
-    
+    if (getLangOpts().CPlusPlus)
+      TryConsumeToken(tok::ellipsis, EllipsisLoc);
+
     // We have a valid expression. Collect it in a vector so we can
     // build the argument list.
     ObjCDictionaryElement Element = { 
@@ -2787,7 +2793,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
     if (Tok.is(tok::comma))
       ConsumeToken(); // Eat the ','.
     else if (Tok.isNot(tok::r_brace))
-      return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma));
+      return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
+                                                            << tok::comma);
   }
   SourceLocation EndLoc = ConsumeBrace();
   
@@ -2834,7 +2841,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
   T.consumeOpen();
 
   if (Tok.isNot(tok::identifier))
-    return ExprError(Diag(Tok, diag::err_expected_ident));
+    return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
 
   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
   SourceLocation ProtoIdLoc = ConsumeToken();
@@ -2869,7 +2876,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
   if (!SelIdent &&  // missing selector name.
       Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
-    return ExprError(Diag(Tok, diag::err_expected_ident));
+    return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
 
   KeyIdents.push_back(SelIdent);
   unsigned nColons = 0;
index 89e4147e285c9ec0a4fc53914d51550e8824c41a..14404ce61760807e47363001268f6a1b13829c1f 100644 (file)
@@ -225,8 +225,9 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
       IsCorrect = false;
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                 StopBeforeMatch);
-      Diag(PrevTok.getLocation(), diag::err_expected_ident)
-        << SourceRange(PrevTok.getLocation(), PrevTokLocation);
+      Diag(PrevTok.getLocation(), diag::err_expected)
+          << tok::identifier
+          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
     } else {
       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
       ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
@@ -241,7 +242,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
   }
 
   if (NoIdentIsFound) {
-    Diag(Tok, diag::err_expected_ident);
+    Diag(Tok, diag::err_expected) << tok::identifier;
     IsCorrect = false;
   }
 
index 8a374e0fce61aa7a67282cb8ebb8a236d13d69e4..a225c766c115ddf13b79fb9215c6d15a35dc4dc5 100644 (file)
@@ -130,7 +130,7 @@ StmtResult Parser::HandlePragmaCaptured()
   ConsumeToken();
 
   if (Tok.isNot(tok::l_brace)) {
-    PP.Diag(Tok, diag::err_expected_lbrace);
+    PP.Diag(Tok, diag::err_expected) << tok::l_brace;
     return StmtError();
   }
 
@@ -815,7 +815,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
   SourceLocation CommentLoc = Tok.getLocation();
   PP.Lex(Tok);
   if (Tok.isNot(tok::l_paren)) {
-    PP.Diag(CommentLoc, diag::err_expected_lparen);
+    PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
     return;
   }
 
@@ -838,7 +838,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
     return;
 
   if (Tok.isNot(tok::r_paren)) {
-    PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
+    PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
     return;
   }
   PP.Lex(Tok);  // Eat the r_paren.
index 142386402dffedf5a086901e73e3c60b46a6fd60..7f3be42fe6c6294a4a93822e436e123fc19874dd 100644 (file)
@@ -412,7 +412,7 @@ StmtResult Parser::ParseSEHTryBlock() {
 ///
 StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
   if(Tok.isNot(tok::l_brace))
-    return StmtError(Diag(Tok,diag::err_expected_lbrace));
+    return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
 
   StmtResult TryBlock(ParseCompoundStatement());
   if(TryBlock.isInvalid())
@@ -624,10 +624,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
     // GNU case range extension.
     SourceLocation DotDotDotLoc;
     ExprResult RHS;
-    if (Tok.is(tok::ellipsis)) {
-      Diag(Tok, diag::ext_gnu_case_range);
-      DotDotDotLoc = ConsumeToken();
-
+    if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
+      Diag(DotDotDotLoc, diag::ext_gnu_case_range);
       RHS = ParseConstantExpression();
       if (RHS.isInvalid()) {
         SkipUntil(tok::colon, StopAtSemi);
@@ -637,18 +635,17 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
 
     ColonProtection.restore();
 
-    if (Tok.is(tok::colon)) {
-      ColonLoc = ConsumeToken();
-
+    if (TryConsumeToken(tok::colon, ColonLoc)) {
     // Treat "case blah;" as a typo for "case blah:".
-    } else if (Tok.is(tok::semi)) {
-      ColonLoc = ConsumeToken();
-      Diag(ColonLoc, diag::err_expected_colon_after) << "'case'"
-        << FixItHint::CreateReplacement(ColonLoc, ":");
+    } else if (TryConsumeToken(tok::semi, ColonLoc)) {
+      Diag(ColonLoc, diag::err_expected_after)
+          << "'case'" << tok::colon
+          << FixItHint::CreateReplacement(ColonLoc, ":");
     } else {
       SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
-      Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'"
-        << FixItHint::CreateInsertion(ExpectedLoc, ":");
+      Diag(ExpectedLoc, diag::err_expected_after)
+          << "'case'" << tok::colon
+          << FixItHint::CreateInsertion(ExpectedLoc, ":");
       ColonLoc = ExpectedLoc;
     }
 
@@ -713,18 +710,17 @@ StmtResult Parser::ParseDefaultStatement() {
   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
 
   SourceLocation ColonLoc;
-  if (Tok.is(tok::colon)) {
-    ColonLoc = ConsumeToken();
-
+  if (TryConsumeToken(tok::colon, ColonLoc)) {
   // Treat "default;" as a typo for "default:".
-  } else if (Tok.is(tok::semi)) {
-    ColonLoc = ConsumeToken();
-    Diag(ColonLoc, diag::err_expected_colon_after) << "'default'"
-      << FixItHint::CreateReplacement(ColonLoc, ":");
+  } else if (TryConsumeToken(tok::semi, ColonLoc)) {
+    Diag(ColonLoc, diag::err_expected_after)
+        << "'default'" << tok::colon
+        << FixItHint::CreateReplacement(ColonLoc, ":");
   } else {
     SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
-    Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'"
-      << FixItHint::CreateInsertion(ExpectedLoc, ":");
+    Diag(ExpectedLoc, diag::err_expected_after)
+        << "'default'" << tok::colon
+        << FixItHint::CreateInsertion(ExpectedLoc, ":");
     ColonLoc = ExpectedLoc;
   }
 
@@ -867,7 +863,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
     SmallVector<Decl *, 8> DeclsInGroup;
     while (1) {
       if (Tok.isNot(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
         break;
       }
 
@@ -875,9 +871,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
       SourceLocation IdLoc = ConsumeToken();
       DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
 
-      if (!Tok.is(tok::comma))
+      if (!TryConsumeToken(tok::comma))
         break;
-      ConsumeToken();
     }
 
     DeclSpec DS(AttrFactory);
@@ -1346,7 +1341,7 @@ StmtResult Parser::ParseDoStatement() {
   if (Tok.isNot(tok::kw_while)) {
     if (!Body.isInvalid()) {
       Diag(Tok, diag::err_expected_while);
-      Diag(DoLoc, diag::note_matching) << "do";
+      Diag(DoLoc, diag::note_matching) << "'do'";
       SkipUntil(tok::semi, StopBeforeMatch);
     }
     return StmtError();
@@ -1677,7 +1672,7 @@ StmtResult Parser::ParseGotoStatement() {
     }
     Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
   } else {
-    Diag(Tok, diag::err_expected_ident);
+    Diag(Tok, diag::err_expected) << tok::identifier;
     return StmtError();
   }
 
@@ -2115,12 +2110,12 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
 
   if (InBraces && BraceCount != savedBraceCount) {
     // __asm without closing brace (this can happen at EOF).
-    Diag(Tok, diag::err_expected_rbrace);
-    Diag(LBraceLoc, diag::note_matching) << "{";
+    Diag(Tok, diag::err_expected) << tok::r_brace;
+    Diag(LBraceLoc, diag::note_matching) << tok::l_brace;
     return StmtError();
   } else if (NumTokensRead == 0) {
     // Empty __asm.
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return StmtError();
   }
 
@@ -2400,7 +2395,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
       T.consumeOpen();
 
       if (Tok.isNot(tok::identifier)) {
-        Diag(Tok, diag::err_expected_ident);
+        Diag(Tok, diag::err_expected) << tok::identifier;
         SkipUntil(tok::r_paren, StopAtSemi);
         return true;
       }
@@ -2561,7 +2556,7 @@ StmtResult Parser::ParseCXXTryBlock() {
 ///
 StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
   if (Tok.isNot(tok::l_brace))
-    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+    return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
 
   StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
@@ -2665,7 +2660,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
     return StmtError();
 
   if (Tok.isNot(tok::l_brace))
-    return StmtError(Diag(Tok, diag::err_expected_lbrace));
+    return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
 
   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
   StmtResult Block(ParseCompoundStatement());
@@ -2686,7 +2681,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
   // inside these braces escaping to the surrounding code.
   if (Result.Behavior == IEB_Dependent) {
     if (!Tok.is(tok::l_brace)) {
-      Diag(Tok, diag::err_expected_lbrace);
+      Diag(Tok, diag::err_expected) << tok::l_brace;
       return;
     }
 
@@ -2706,7 +2701,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
 
   BalancedDelimiterTracker Braces(*this, tok::l_brace);
   if (Braces.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return;
   }
 
index 67004cefaf96742e934bf49f6babd53a9b5d5751..03325db8860667caf8556fbf48113aba2f8b72d1 100644 (file)
@@ -496,7 +496,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
     // Unnamed template parameter. Don't have to do anything here, just
     // don't consume this token.
   } else {
-    Diag(Tok.getLocation(), diag::err_expected_ident);
+    Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
     return 0;
   }
 
@@ -577,7 +577,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
     // Unnamed template parameter. Don't have to do anything here, just
     // don't consume this token.
   } else {
-    Diag(Tok.getLocation(), diag::err_expected_ident);
+    Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
     return 0;
   }
 
index 5224c6bdc192f12ffb2852488213872107c1804e..d1424899aec8adc74b809f92f3c0978443f54059 100644 (file)
@@ -195,8 +195,11 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
 }
 
 bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
-  if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) {
-    ConsumeToken();
+  if (TryConsumeToken(tok::semi))
+    return false;
+
+  if (Tok.is(tok::code_completion)) {
+    handleUnexpectedCodeCompletionToken();
     return false;
   }
   
@@ -310,7 +313,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
 
     case tok::code_completion:
       if (!HasFlagsSet(Flags, StopAtCodeCompletion))
-        ConsumeToken();
+        handleUnexpectedCodeCompletionToken();
       return false;
         
     case tok::l_paren:
@@ -1813,8 +1816,8 @@ bool Parser::isTokenEqualOrEqualTypo() {
   case tok::pipeequal:           // |=
   case tok::equalequal:          // ==
     Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal)
-      << getTokenSimpleSpelling(Kind)
-      << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
+        << Kind
+        << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "=");
   case tok::equal:
     return true;
   }
@@ -1943,7 +1946,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
   
   BalancedDelimiterTracker Braces(*this, tok::l_brace);
   if (Braces.consumeOpen()) {
-    Diag(Tok, diag::err_expected_lbrace);
+    Diag(Tok, diag::err_expected) << tok::l_brace;
     return;
   }
 
@@ -2044,17 +2047,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
 
 bool BalancedDelimiterTracker::diagnoseMissingClose() {
   assert(!P.Tok.is(Close) && "Should have consumed closing delimiter");
-  
-  const char *LHSName = "unknown";
-  diag::kind DID;
-  switch (Close) {
-  default: llvm_unreachable("Unexpected balanced token");
-  case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
-  case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
-  case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
-  }
-  P.Diag(P.Tok, DID);
-  P.Diag(LOpen, diag::note_matching) << LHSName;
+
+  P.Diag(P.Tok, diag::err_expected) << Close;
+  P.Diag(LOpen, diag::note_matching) << Kind;
 
   // If we're not already at some kind of closing bracket, skip to our closing
   // token.
index 72c3471863cf4516b6e529be50dbd67331dad9b0..ca67094f80f26a7971aeb39732bfe209179cab58 100644 (file)
@@ -1699,7 +1699,8 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
     }
     
     if (IFace == 0) {
-      Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+      Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier
+                                                       << tok::l_paren;
       return ExprError();
     }
   }