]> granicus.if.org Git - clang/commitdiff
Fix an assertion-on-error during tentative constructor parsing by
authorJohn McCall <rjmccall@apple.com>
Fri, 26 Feb 2010 08:45:28 +0000 (08:45 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 26 Feb 2010 08:45:28 +0000 (08:45 +0000)
propagating error conditions out of the various annotate-me-a-snowflake
routines.  Generally (but not universally) removes redundant diagnostics
as well as, you know, not crashing on bad code.  On the other hand,
I have just signed myself up to fix fiddly parser errors for the next
week.  Again.

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

15 files changed:
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTentative.cpp
lib/Parse/Parser.cpp
test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp
test/Parser/cxx-template-argument.cpp
test/SemaCXX/member-pointer.cpp
test/SemaCXX/nested-name-spec.cpp
test/SemaTemplate/dependent-base-classes.cpp
test/SemaTemplate/explicit-specialization-member.cpp
test/SemaTemplate/nested-name-spec-template.cpp
test/SemaTemplate/temp_arg.cpp

index 4a367484c9d800bb8ace278b1466ff7431cf1e5b..c4488e2f68c782a421e07c62254b437c87278949 100644 (file)
@@ -320,9 +320,9 @@ private:
   /// This returns true if the token was annotated.
   bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false);
 
-  /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but only
-  /// annotates C++ scope specifiers.  This returns true if the token was
-  /// annotated.
+  /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but
+  /// only annotates C++ scope specifiers.  This returns true if there
+  /// was an unrecoverable error.
   bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
 
   /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens,
index 62b10a316e6033bf0e016812a5d839bb57fad1fc..5dc4bd2f609ccd44f6fdd79a6008a55c9107e410 100644 (file)
@@ -859,10 +859,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       return;
 
     case tok::coloncolon: // ::foo::bar
-      // Annotate C++ scope specifiers.  If we get one, loop.
-      if (TryAnnotateCXXScopeToken(true))
-        continue;
-      goto DoneWithDeclSpec;
+      // C++ scope specifier.  Annotate and loop, or bail out on error.
+      if (TryAnnotateCXXScopeToken(true)) {
+        if (!DS.hasTypeSpecifier())
+          DS.SetTypeSpecError();
+        goto DoneWithDeclSpec;
+      }
+      continue;
 
     case tok::annot_cxxscope: {
       if (DS.hasTypeSpecifier())
@@ -1020,8 +1023,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
     case tok::identifier: {
       // In C++, check to see if this is a scope specifier like foo::bar::, if
       // so handle it as such.  This is important for ctor parsing.
-      if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true))
-        continue;
+      if (getLang().CPlusPlus) {
+        if (TryAnnotateCXXScopeToken(true)) {
+          if (!DS.hasTypeSpecifier())
+            DS.SetTypeSpecError();
+          goto DoneWithDeclSpec;
+        }
+        if (!Tok.is(tok::identifier))
+          continue;
+      }
 
       // This identifier can only be a typedef name if we haven't already seen
       // a type-specifier.  Without this check we misparse:
@@ -1313,7 +1323,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
 
     // C++ typename-specifier:
     case tok::kw_typename:
-      if (TryAnnotateTypeOrScopeToken())
+      if (TryAnnotateTypeOrScopeToken()) {
+        DS.SetTypeSpecError();
+        goto DoneWithDeclSpec;
+      }
+      if (!Tok.is(tok::kw_typename))
         continue;
       break;
 
@@ -1423,10 +1437,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
-                                        TemplateInfo, SuppressDeclarations);
-    // Otherwise, not a type specifier.
-    return false;
+      return true;
+    if (Tok.is(tok::identifier))
+      return false;
+    return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+                                      TemplateInfo, SuppressDeclarations);
   case tok::coloncolon:   // ::foo::bar
     if (NextToken().is(tok::kw_new) ||    // ::new
         NextToken().is(tok::kw_delete))   // ::delete
@@ -1435,10 +1450,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
-                                        TemplateInfo, SuppressDeclarations);
-    // Otherwise, not a type specifier.
-    return false;
+      return true;
+    return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+                                      TemplateInfo, SuppressDeclarations);
 
   // simple-type-specifier:
   case tok::annot_typename: {
@@ -1848,8 +1862,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
     Attr.reset(ParseGNUAttributes());
 
   CXXScopeSpec SS;
-  if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
-    if (Tok.isNot(tok::identifier)) {
+  if (getLang().CPlusPlus) {
+    if (ParseOptionalCXXScopeSpecifier(SS, 0, false))
+      return;
+
+    if (SS.isSet() && Tok.isNot(tok::identifier)) {
       Diag(Tok, diag::err_expected_ident);
       if (Tok.isNot(tok::l_brace)) {
         // Has no name and is not a definition.
@@ -2016,21 +2033,19 @@ bool Parser::isTypeSpecifierQualifier() {
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isTypeSpecifierQualifier();
-    // Otherwise, not a type specifier.
-    return false;
+      return true;
+    if (Tok.is(tok::identifier))
+      return false;
+    return isTypeSpecifierQualifier();
 
   case tok::coloncolon:   // ::foo::bar
     if (NextToken().is(tok::kw_new) ||    // ::new
         NextToken().is(tok::kw_delete))   // ::delete
       return false;
 
-    // Annotate typenames and C++ scope specifiers.  If we get one, just
-    // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isTypeSpecifierQualifier();
-    // Otherwise, not a type specifier.
-    return false;
+      return true;
+    return isTypeSpecifierQualifier();
 
     // GNU attributes support.
   case tok::kw___attribute:
@@ -2101,14 +2116,15 @@ bool Parser::isDeclarationSpecifier() {
     if (TryAltiVecVectorToken())
       return true;
     // Fall through.
-
   case tok::kw_typename: // typename T::type
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isDeclarationSpecifier();
-    // Otherwise, not a declaration specifier.
-    return false;
+      return true;
+    if (Tok.is(tok::identifier))
+      return false;
+    return isDeclarationSpecifier();
+
   case tok::coloncolon:   // ::foo::bar
     if (NextToken().is(tok::kw_new) ||    // ::new
         NextToken().is(tok::kw_delete))   // ::delete
@@ -2117,9 +2133,8 @@ bool Parser::isDeclarationSpecifier() {
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isDeclarationSpecifier();
-    // Otherwise, not a declaration specifier.
-    return false;
+      return true;
+    return isDeclarationSpecifier();
 
     // storage-class-specifier
   case tok::kw_typedef:
@@ -2200,7 +2215,10 @@ bool Parser::isConstructorDeclarator() {
 
   // Parse the C++ scope specifier.
   CXXScopeSpec SS;
-  ParseOptionalCXXScopeSpecifier(SS, 0, true);
+  if (ParseOptionalCXXScopeSpecifier(SS, 0, true)) {
+    TPA.Revert();
+    return false;
+  }
 
   // Parse the constructor name.
   if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
@@ -2351,7 +2369,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
       (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
        Tok.is(tok::annot_cxxscope))) {
     CXXScopeSpec SS;
-    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
+    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); // ignore fail
+
+    if (SS.isSet()) {
       if (Tok.isNot(tok::star)) {
         // The scope spec really belongs to the direct-declarator.
         D.getCXXScopeSpec() = SS;
@@ -2507,9 +2527,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
 
   if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
     // ParseDeclaratorInternal might already have parsed the scope.
-    bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+    bool afterCXXScope = D.getCXXScopeSpec().isSet();
+    if (!afterCXXScope) {
       ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
                                      true);
+      afterCXXScope = D.getCXXScopeSpec().isSet();
+    }
+
     if (afterCXXScope) {
       if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
         // Change the declaration context for name lookup, until this function
@@ -2799,7 +2823,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
   // K&R-style function:  void foo(a,b,c)
   if (!getLang().CPlusPlus && Tok.is(tok::identifier)
       && !TryAltiVecVectorToken()) {
-    if (!TryAnnotateTypeOrScopeToken()) {
+    if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) {
       // K&R identifier lists can't have typedefs as identifiers, per
       // C99 6.7.5.3p11.
       if (RequiresArg) {
index 225ce256b11edf269d8823da3e797b34dd2e58cd..dbbfb9518b33ffacdacbd26294f641669461224e 100644 (file)
@@ -645,7 +645,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
     // "FOO : BAR" is not a potential typo for "FOO::BAR".
     ColonProtectionRAIIObject X(*this);
     
-    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
+    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+    if (SS.isSet())
       if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
         Diag(Tok, diag::err_expected_ident);
   }
@@ -1163,7 +1164,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
   // Access declarations.
   if (!TemplateInfo.Kind &&
       (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
-      TryAnnotateCXXScopeToken() &&
+      !TryAnnotateCXXScopeToken() &&
       Tok.is(tok::annot_cxxscope)) {
     bool isAccessDecl = false;
     if (NextToken().is(tok::identifier))
index f69740bf8bd6f24ad4b42013de7e61e373cb4eda..af91021d33ce7387f8a97b62f57ba3b1eabc346e 100644 (file)
@@ -626,6 +626,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
           Next.is(tok::l_paren)) {
         // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
         if (TryAnnotateTypeOrScopeToken())
+          return ExprError();
+        if (!Tok.is(tok::identifier))
           return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
       }
     }
@@ -790,7 +792,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
 
     if (SavedKind == tok::kw_typename) {
       // postfix-expression: typename-specifier '(' expression-list[opt] ')'
-      if (!TryAnnotateTypeOrScopeToken())
+      if (TryAnnotateTypeOrScopeToken())
         return ExprError();
     }
 
@@ -852,6 +854,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
     // ::foo::bar -> global qualified name etc.   If TryAnnotateTypeOrScopeToken
     // annotates the token, tail recurse.
     if (TryAnnotateTypeOrScopeToken())
+      return ExprError();
+    if (!Tok.is(tok::coloncolon))
       return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
 
     // ::new -> [C++] new-expression
index 7998b26f9bc5d0182b61d8853ecd92b7bfd83943..f1e989f4a7b0ed268974b5c4def4fa59fdfabe6d 100644 (file)
@@ -55,7 +55,7 @@ using namespace clang;
 
 /// member access expression, e.g., the \p T:: in \p p->T::m.
 ///
-/// \returns true if a scope specifier was parsed.
+/// \returns true if there was an error parsing a scope specifier
 bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
                                             Action::TypeTy *ObjectType,
                                             bool EnteringContext,
@@ -67,7 +67,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
     SS.setScopeRep(Tok.getAnnotationValue());
     SS.setRange(Tok.getAnnotationRange());
     ConsumeToken();
-    return true;
+    return false;
   }
 
   bool HasScopeSpecifier = false;
@@ -168,10 +168,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
         = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
                                              ObjectType, EnteringContext);
       if (!Template)
-        break;
+        return true;
       if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
                                   &SS, TemplateName, TemplateKWLoc, false))
-        break;
+        return true;
 
       continue;
     }
@@ -188,7 +188,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
         = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
       if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
         *MayBePseudoDestructor = true;
-        return HasScopeSpecifier;
+        return false;
       }
 
       if (TemplateId->Kind == TNK_Type_template ||
@@ -258,7 +258,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
           !Actions.isNonTypeNestedNameSpecifier(CurScope, SS, Tok.getLocation(),
                                                 II, ObjectType)) {
         *MayBePseudoDestructor = true;
-        return HasScopeSpecifier;
+        return false;
       }
 
       // We have an identifier followed by a '::'. Lookup this name
@@ -303,7 +303,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
         ConsumeToken();
         if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, 
                                     SourceLocation(), false))
-          break;
+          return true;
         continue;
       }
     }
@@ -319,7 +319,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
   if (CheckForDestructor && Tok.is(tok::tilde))
     *MayBePseudoDestructor = true;
 
-  return HasScopeSpecifier;
+  return false;
 }
 
 /// ParseCXXIdExpression - Handle id-expression.
index 6251a2f36754cbc1b324478abdc01803bf9f5591..516a9a620b62c0fda6101d2cab48ce97942b932e 100644 (file)
@@ -491,7 +491,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
 
   while (1) {
     if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
-      TryAnnotateCXXScopeToken(true);
+      if (TryAnnotateCXXScopeToken(true))
+        return TPResult::Error();
 
     if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
         (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
@@ -681,9 +682,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isCXXDeclarationSpecifier();
-    // Otherwise, not a typename.
-    return TPResult::False();
+      return TPResult::Error();
+    if (Tok.is(tok::identifier))
+      return TPResult::False();
+    return isCXXDeclarationSpecifier();
 
   case tok::coloncolon: {    // ::foo::bar
     const Token &Next = NextToken();
@@ -694,9 +696,8 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return isCXXDeclarationSpecifier();
-    // Otherwise, not a typename.
-    return TPResult::False();
+      return TPResult::Error();
+    return isCXXDeclarationSpecifier();
   }
       
     // decl-specifier:
@@ -762,7 +763,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
 
   case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
     // We've already annotated a scope; try to annotate a type.
-    if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
+    if (TryAnnotateTypeOrScopeToken())
+      return TPResult::Error();
+    if (!Tok.is(tok::annot_typename))
       return TPResult::False();
     // If that succeeded, fallthrough into the generic simple-type-id case.
 
index 24162373e0eb3ac9c2a5b55bbff131e17ff48528..a6ae9cfd0d3c98ba9fb31aac5d6fb0d376e8a8d2 100644 (file)
@@ -891,8 +891,7 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
 /// specifier, and another one to get the actual type inside
 /// ParseDeclarationSpecifiers).
 ///
-/// This returns true if the token was annotated or an unrecoverable error
-/// occurs.
+/// This returns true if an error occurred.
 ///
 /// Note that this routine emits an error if you call it with ::new or ::delete
 /// as the current tokens, so only call it in contexts where these are invalid.
@@ -910,11 +909,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
     //            simple-template-id
     SourceLocation TypenameLoc = ConsumeToken();
     CXXScopeSpec SS;
-    bool HadNestedNameSpecifier
-      = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
-    if (!HadNestedNameSpecifier) {
+    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false))
+      return true;
+    if (!SS.isSet()) {
       Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
-      return false;
+      return true;
     }
 
     TypeResult Ty;
@@ -928,7 +927,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
       if (TemplateId->Kind == TNK_Function_template) {
         Diag(Tok, diag::err_typename_refers_to_non_type_template)
           << Tok.getAnnotationRange();
-        return false;
+        return true;
       }
 
       AnnotateTemplateIdTokenAsType(0);
@@ -942,7 +941,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
     } else {
       Diag(Tok, diag::err_expected_type_name_after_typename)
         << SS.getRange();
-      return false;
+      return true;
     }
 
     SourceLocation EndLoc = Tok.getLastLoc();
@@ -951,7 +950,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
     Tok.setAnnotationEndLoc(EndLoc);
     Tok.setLocation(TypenameLoc);
     PP.AnnotateCachedTokens(Tok);
-    return true;
+    return false;
   }
 
   // Remembers whether the token was originally a scope annotation.
@@ -959,7 +958,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
 
   CXXScopeSpec SS;
   if (getLang().CPlusPlus)
-    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
+    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+      return true;
 
   if (Tok.is(tok::identifier)) {
     // Determine whether the identifier is a type name.
@@ -976,7 +976,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
       // In case the tokens were cached, have Preprocessor replace
       // them with the annotation token.
       PP.AnnotateCachedTokens(Tok);
-      return true;
+      return false;
     }
 
     if (!getLang().CPlusPlus) {
@@ -1001,7 +1001,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
           // If an unrecoverable error occurred, we need to return true here,
           // because the token stream is in a damaged state.  We may not return
           // a valid identifier.
-          return Tok.isNot(tok::identifier);
+          return true;
         }
       }
     }
@@ -1021,12 +1021,12 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
       // to produce a type annotation token. Update the template-id
       // annotation token to a type annotation token now.
       AnnotateTemplateIdTokenAsType(&SS);
-      return true;
+      return false;
     }
   }
 
   if (SS.isEmpty())
-    return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon);
+    return false;
 
   // A C++ scope specifier that isn't followed by a typename.
   // Push the current token back into the token stream (or revert it if it is
@@ -1044,7 +1044,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
   // just reverted back to the state we were in before being called.
   if (!wasScopeAnnotation)
     PP.AnnotateCachedTokens(Tok);
-  return true;
+  return false;
 }
 
 /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
@@ -1061,10 +1061,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
          "Cannot be a type or scope token!");
 
   CXXScopeSpec SS;
-  if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
-    // If the token left behind is not an identifier, we either had an error or
-    // successfully turned it into an annotation token.
-    return Tok.isNot(tok::identifier);
+  if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+    return true;
+  if (!SS.isSet())
+    return false;
 
   // Push the current token back into the token stream (or revert it if it is
   // cached) and use an annotation scope token for current token.
@@ -1079,7 +1079,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
   // In case the tokens were cached, have Preprocessor replace them with the
   // annotation token.
   PP.AnnotateCachedTokens(Tok);
-  return true;
+  return false;
 }
 
 // Anchor the Parser::FieldCallback vtable to this translation unit.
index a8b83d4854e3990220b415103b429316cd024a72..eb5465cc19bb08dd2ea9c9008aba7c9180bc50ee 100644 (file)
@@ -33,5 +33,4 @@ template <typename T> void g(T);
 template <typename T> void g(T, T);
 
 int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \
-     // expected-error{{cannot determine the type of an overloaded function}} \
-     // FIXME: expected-error{{use of undeclared identifier}}
+     // expected-error{{cannot determine the type of an overloaded function}}
index 80389a07b0acbfccfed1a37ec649db4db8da0e0d..532b4c9894b7dfa5dff4e17a105a69802aba27bd 100644 (file)
@@ -5,5 +5,5 @@ template<typename T> struct A {};
 // Check for template argument lists followed by junk
 // FIXME: The diagnostics here aren't great...
 A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}}
-A<int x; // expected-error {{expected '>'}} expected-error {{C++ requires a type specifier for all declarations}}
+A<int x; // expected-error {{expected '>'}}
 
index 3d9d5b5ebbbc5f537a72434f65080b93991b3c06..d6050cd7337ae82e09ef75bb519d06b2c230702e 100644 (file)
@@ -12,8 +12,7 @@ int A::*pdi1;
 int (::A::*pdi2);
 int (A::*pfi)(int);
 
-int B::*pbi; // expected-error {{expected a class or namespace}} \
-             // expected-error{{does not point into a class}}
+int B::*pbi; // expected-error {{expected a class or namespace}}
 int C::*pci; // expected-error {{'pci' does not point into a class}}
 void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
 int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}}
index 8a217b312088682601571f96a313b7aed650a407..247e91b2eb398413b36f231d8f56b643309c451b 100644 (file)
@@ -13,8 +13,9 @@ namespace A {
 }
 
 A:: ; // expected-error {{expected unqualified-id}}
-::A::ax::undef ex3; // expected-error {{no member named}}
-A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}}
+// FIXME: redundant errors
+::A::ax::undef ex3; // expected-error {{no member named}} expected-error {{unknown type name}}
+A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name}}
 
 int A::C::Ag1() { return 0; }
 
index 80d20b09b82a9633a1c251cf88d6c1abf8efa246..cd90f63410670249366a351f233239b5507f6a81 100644 (file)
@@ -57,7 +57,6 @@ namespace PR6031 {
     int foo() {
       class NoDepBase::Nested nested; // expected-error{{'Nested' does not name a tag member in the specified scope}}
       typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \
-      // FIXME: expected-error{{expected an identifier or template-id after '::'}} \
       // FIXME: expected-error{{unqualified-id}}
       return NoDepBase::a; // expected-error{{no member named 'a' in 'struct PR6031::NoDepBase'}}
     }
index 417cdc1f1987b6a7ab3ad171e6092281bc61dcdb..cb0a39a9d0cf7ef16b2ec3fe79f59c9dd39dbe39 100644 (file)
@@ -16,7 +16,7 @@ namespace PR6161 {
               // expected-error{{expected class name}} \
   // expected-note{{attempt to specialize declaration here}}
   {
-    static locale::id id; // expected-error{{use of undeclared identifier}}
+    static locale::id id; // expected-error{{use of undeclared identifier}} FIXME: expected-error {{unknown type name}}
   };
   numpunct<char>::~numpunct(); // expected-error{{template specialization requires 'template<>'}} \
   // expected-error{{specialization of member 'PR6161::numpunct<char>::~numpunct' does not specialize an instantiated member}}
index 704b8cfce128371d6249b8dbad8a46b2132cd08b..1691db74a115622ef700e55ef8a5fad03a3d9b58 100644 (file)
@@ -49,6 +49,5 @@ struct ::N::A<int>::X {
 template<typename T>
 struct TestA {
   typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \
-                                                // expected-error{{identifier or template-id}} \
                                                 // expected-error{{expected member name}}
 };
index 3c9fcb5066102ed83e77356d4d7f109b21c6b9b3..80bbda785d0551282a054426779a56a10dcd5539 100644 (file)
@@ -10,3 +10,10 @@ A<int, 0, X> * a1;
 
 A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}}
 A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}}
+
+namespace test0 {
+  template <class t> class foo {};
+  template <class t> class bar {
+    bar(::test0::foo<tee> *ptr) {} // FIXME(redundant): expected-error 2 {{use of undeclared identifier 'tee'}}
+  };
+}