[cfe-commits] r85616 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Fri Oct 30 14:46:59 PDT 2009


Author: dgregor
Date: Fri Oct 30 16:46:58 2009
New Revision: 85616

URL: http://llvm.org/viewvc/llvm-project?rev=85616&view=rev
Log:
Improve diagnostics when parsing something like

  template<> struct foo<int> { ... };

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

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

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=85616&r1=85615&r2=85616&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Oct 30 16:46:58 2009
@@ -282,6 +282,8 @@
   "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">;

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=85616&r1=85615&r2=85616&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Oct 30 16:46:58 2009
@@ -589,6 +589,8 @@
     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 @@
   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 @@
   // 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.

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp?rev=85616&r1=85615&r2=85616&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp Fri Oct 30 16:46:58 2009
@@ -4,8 +4,7 @@
   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 {
   

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp?rev=85616&r1=85615&r2=85616&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp Fri Oct 30 16:46:58 2009
@@ -6,8 +6,7 @@
   };
 }
 
-// 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

Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=85616&r1=85615&r2=85616&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Fri Oct 30 16:46:58 2009
@@ -92,3 +92,7 @@
   int x;
   A< typeof(x>1) > a;
 }
+
+
+// PR3844
+template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}}





More information about the cfe-commits mailing list