[cfe-commits] r85620 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp test/CXX/temp/temp.spec/temp.explicit/p5.cpp

Douglas Gregor dgregor at apple.com
Fri Oct 30 15:09:44 PDT 2009


Author: dgregor
Date: Fri Oct 30 17:09:44 2009
New Revision: 85620

URL: http://llvm.org/viewvc/llvm-project?rev=85620&view=rev
Log:
Improved fix for PR3844, which recovers better for class template
partial specializations and explicit instantiations of non-templates.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Oct 30 17:09:44 2009
@@ -283,7 +283,8 @@
 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">;
+  "explicit %select{specialization|instantiation}0 of non-template "
+  "%select{class|struct|union}1 %2">;
 
 def err_variadic_templates : Error<
   "variadic templates are only allowed in C++0x">;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=85620&r1=85619&r2=85620&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Oct 30 17:09:44 2009
@@ -603,14 +603,17 @@
       : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
 
     ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
-                       bool isSpecialization)
+                       bool isSpecialization,
+                       bool lastParameterListWasEmpty = false)
       : Kind(isSpecialization? ExplicitSpecialization : Template),
-        TemplateParams(TemplateParams) { }
+        TemplateParams(TemplateParams), 
+        LastParameterListWasEmpty(lastParameterListWasEmpty) { }
 
     explicit ParsedTemplateInfo(SourceLocation ExternLoc,
                                 SourceLocation TemplateLoc)
       : Kind(ExplicitInstantiation), TemplateParams(0),
-        ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
+        ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+        LastParameterListWasEmpty(false){ }
 
     /// \brief The kind of template we are parsing.
     enum {
@@ -635,6 +638,9 @@
     /// \brief The location of the 'template' keyword, for an explicit
     /// instantiation.
     SourceLocation TemplateLoc;
+    
+    /// \brief Whether the last template parameter list was empty.
+    bool LastParameterListWasEmpty;
   };
 
   void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Oct 30 17:09:44 2009
@@ -617,21 +617,35 @@
       }
       
       Diag(NameLoc, diag::err_explicit_spec_non_template)
+        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
         << (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 {
+      // Strip off the last template parameter list if it was empty, since 
+      // we've removed its template argument list.
+      if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+        if (TemplateParams && TemplateParams->size() > 1) {
+          TemplateParams->pop_back();
+        } else {
+          TemplateParams = 0;
+          const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
+            = ParsedTemplateInfo::NonTemplate;
+        }
+      } else if (TemplateInfo.Kind
+                                == ParsedTemplateInfo::ExplicitInstantiation) {
+        // Pretend this is just a forward declaration.
         TemplateParams = 0;
         const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
           = ParsedTemplateInfo::NonTemplate;
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc 
+          = SourceLocation();
+        const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+          = SourceLocation();
       }
+        
       
     }
   } else if (Tok.is(tok::annot_template_id)) {

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri Oct 30 17:09:44 2009
@@ -101,6 +101,7 @@
   // (and retrieves the outer template parameter list from its
   // context).
   bool isSpecialization = true;
+  bool LastParamListWasEmpty = false;
   TemplateParameterLists ParamLists;
   TemplateParameterDepthCounter Depth(TemplateParameterDepth);
   do {
@@ -140,13 +141,16 @@
     if (!TemplateParams.empty()) {
       isSpecialization = false;
       ++Depth;
+    } else {
+      LastParamListWasEmpty = true;
     }
   } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
   // Parse the actual template declaration.
   return ParseSingleDeclarationAfterTemplate(Context,
                                              ParsedTemplateInfo(&ParamLists,
-                                                             isSpecialization),
+                                                             isSpecialization,
+                                                         LastParamListWasEmpty),
                                              DeclEnd, AS);
 }
 

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=85620&r1=85619&r2=85620&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 17:09:44 2009
@@ -6,7 +6,7 @@
   };
 }
 
-template class Z<int>; // expected-error{{non-template class 'Z'}}
+template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}
 
 // FIXME: This example from the standard is wrong; note posted to CWG reflector
 // on 10/27/2009





More information about the cfe-commits mailing list