]> granicus.if.org Git - clang/commitdiff
Improve diagnostics when parsing something like
authorDouglas Gregor <dgregor@apple.com>
Fri, 30 Oct 2009 21:46:58 +0000 (21:46 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 30 Oct 2009 21:46:58 +0000 (21:46 +0000)
  template<> struct foo<int> { ... };

where "foo" does not refer to a template. Fixes PR3844.

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

include/clang/Basic/DiagnosticParseKinds.td
lib/Parse/ParseDeclCXX.cpp
test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
test/CXX/temp/temp.spec/temp.explicit/p5.cpp
test/Parser/cxx-template-decl.cpp

index add979a199106a58c326b97028cbee65d2d9fc2c..48f58fb9a611311f04f3fd66ce0acf2a68cda8a0 100644 (file)
@@ -282,6 +282,8 @@ def err_typename_refers_to_non_type_template : Error<
   "typename specifier refers to a non-template">;
 def err_expected_type_name_after_typename : Error<
   "expected an identifier or template-id after '::'">;
+def err_explicit_spec_non_template : Error<
+  "explicit specialization of non-template %select{class|struct|union}0 %1">;
 
 def err_variadic_templates : Error<
   "variadic templates are only allowed in C++0x">;
index d381e3e9747260829ff7505aef29bd43a7a81587..72c9f33cd8db9987d0aaf4a12549dfcbea247b12 100644 (file)
@@ -589,6 +589,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
       Diag(Tok, diag::err_expected_ident);
 
+  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
   // Parse the (optional) class name or simple-template-id.
   IdentifierInfo *Name = 0;
   SourceLocation NameLoc;
@@ -596,6 +598,42 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
   if (Tok.is(tok::identifier)) {
     Name = Tok.getIdentifierInfo();
     NameLoc = ConsumeToken();
+    
+    if (Tok.is(tok::less)) {
+      // The name was supposed to refer to a template, but didn't. 
+      // Eat the template argument list and try to continue parsing this as
+      // a class (or template thereof).
+      TemplateArgList TemplateArgs;
+      TemplateArgIsTypeList TemplateArgIsType;
+      TemplateArgLocationList TemplateArgLocations;
+      SourceLocation LAngleLoc, RAngleLoc;
+      if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, 
+                                           true, LAngleLoc,
+                                           TemplateArgs, TemplateArgIsType,
+                                           TemplateArgLocations, RAngleLoc)) {
+        // We couldn't parse the template argument list at all, so don't
+        // try to give any location information for the list.
+        LAngleLoc = RAngleLoc = SourceLocation();
+      }
+      
+      Diag(NameLoc, diag::err_explicit_spec_non_template)
+        << (TagType == DeclSpec::TST_class? 0
+            : TagType == DeclSpec::TST_struct? 1
+            : 2)
+        << Name
+        << SourceRange(LAngleLoc, RAngleLoc);
+      
+      // If this is an explicit specialization, strip off the last template
+      // parameter list, since we've removed its template arguments.
+      if (TemplateParams && TemplateParams->size() > 1) {
+        TemplateParams->pop_back();
+      } else {
+        TemplateParams = 0;
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
+          = ParsedTemplateInfo::NonTemplate;
+      }
+      
+    }
   } else if (Tok.is(tok::annot_template_id)) {
     TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     NameLoc = ConsumeToken();
@@ -660,7 +698,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
   // Create the tag portion of the class or class template.
   Action::DeclResult TagOrTempResult = true; // invalid
   Action::TypeResult TypeResult = true; // invalid
-  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
 
   // FIXME: When TUK == TUK_Reference and we have a template-id, we need
   // to turn that template-id into a type.
index 2bd1400faefb0d7b78febcc852cd746c8289264a..33fb93bacfafab3b536bbbb70377162bf9016715 100644 (file)
@@ -4,8 +4,7 @@ namespace N {
   template<class T> class X;
 }
 
-// FIXME: this diagnostic is terrible (PR3844).
-template<> class X<int> { /* ... */ }; // expected-error {{unqualified-id}}
+template<> class X<int> { /* ... */ }; // expected-error {{non-template class 'X'}}
 
 namespace N {
   
index ee756027706b1376079a266bf5458760f9ac5a38..b85b62f262c8ffa3b58410afa9ae0b81799887b5 100644 (file)
@@ -6,8 +6,7 @@ namespace N {
   };
 }
 
-// FIXME: poor diagnostic
-template class Z<int>; // expected-error{{unqualified-id}}
+template class Z<int>; // expected-error{{non-template class 'Z'}}
 
 // FIXME: This example from the standard is wrong; note posted to CWG reflector
 // on 10/27/2009
index 67f52b6a67aa27ad92f2ba3c925b0e2d9b006165..2b2d3de50497c9aff5cb95c916f1296bd988e542 100644 (file)
@@ -92,3 +92,7 @@ void f2() {
   int x;
   A< typeof(x>1) > a;
 }
+
+
+// PR3844
+template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}}