[cfe-commits] r71608 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp test/SemaTemplate/temp_explicit.cpp www/cxx_status.html

Douglas Gregor dgregor at apple.com
Tue May 12 16:25:51 PDT 2009


Author: dgregor
Date: Tue May 12 18:25:50 2009
New Revision: 71608

URL: http://llvm.org/viewvc/llvm-project?rev=71608&view=rev
Log:
Implement parsing for explicit instantiations of class templates, e.g.,

  template class X<int>;

This also cleans up the propagation of template information through
declaration parsing, which is used to improve some diagnostics.


Added:
    cfe/trunk/test/SemaTemplate/temp_explicit.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/www/cxx_status.html

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue May 12 18:25:50 2009
@@ -241,8 +241,13 @@
   "use of right-shift operator ('>>') in template argument will require "
   "parentheses in C++0x">;
 def err_multiple_template_declarators : Error<
-    "%select{a template declaration|an explicit template instantiation}0 can "
-    "only %select{declare|instante}0 a single entity">;
+    "%select{|a template declaration|an explicit template specialization|"
+    "an explicit template instantiation}0 can "
+    "only %select{|declare|declare|instantiate}0 a single entity">;
+def err_explicit_instantiation_with_definition : Error<
+    "explicit template instantiation cannot have a definition; if this "
+    "definition is meant to be an explicit specialization, add '<>' after the "
+    "'template' keyword">;
 
 def err_expected_qualified_after_typename : Error<
   "expected a qualified name after 'typename'">;

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue May 12 18:25:50 2009
@@ -1319,6 +1319,62 @@
     return DeclResult();
   }
 
+  /// \brief Process the explicit instantiation of a class template
+  /// specialization.
+  ///
+  /// This routine is invoked when an explicit instantiation of a
+  /// class template specialization is encountered. In the following
+  /// example, ActOnExplicitInstantiation will be invoked to force the
+  /// instantiation of X<int>:
+  ///
+  /// \code
+  /// template<typename T> class X { /* ... */ };
+  /// template class X<int>; // explicit instantiation
+  /// \endcode
+  ///
+  /// \param S the current scope
+  ///
+  /// \param TemplateLoc the location of the 'template' keyword that
+  /// specifies that this is an explicit instantiation.
+  ///
+  /// \param TagSpec whether this declares a class, struct, or union
+  /// (template).
+  ///
+  /// \param KWLoc the location of the 'class', 'struct', or 'union'
+  /// keyword.
+  ///
+  /// \param SS the scope specifier preceding the template-id.
+  ///
+  /// \param Template the declaration of the class template that we
+  /// are instantiation.
+  ///
+  /// \param LAngleLoc the location of the '<' token in the template-id.
+  ///
+  /// \param TemplateArgs the template arguments used to form the
+  /// template-id.
+  ///
+  /// \param TemplateArgLocs the locations of the template arguments.
+  ///
+  /// \param RAngleLoc the location of the '>' token in the template-id.
+  ///
+  /// \param Attr attributes that apply to this instantiation.
+  virtual DeclResult
+  ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
+                             unsigned TagSpec, 
+                             SourceLocation KWLoc,
+                             const CXXScopeSpec &SS,
+                             TemplateTy Template,
+                             SourceLocation TemplateNameLoc,
+                             SourceLocation LAngleLoc,
+                             ASTTemplateArgsPtr TemplateArgs,
+                             SourceLocation *TemplateArgLocs,
+                             SourceLocation RAngleLoc,
+                             AttributeList *Attr) {
+    return DeclResult();
+  }
+                             
+                             
+
   /// \brief Called when the parser has parsed a C++ typename
   /// specifier that ends in an identifier, e.g., "typename T::type".
   ///

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue May 12 18:25:50 2009
@@ -547,6 +547,43 @@
                             tok::TokenKind EarlyAbortIf = tok::unknown,
                             bool ConsumeFinalToken = true);
 
+  /// \brief Contains information about any template-specific
+  /// information that has been parsed prior to parsing declaration
+  /// specifiers.
+  struct ParsedTemplateInfo {
+    ParsedTemplateInfo() 
+      : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
+
+    ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
+                       bool isSpecialization)
+      : Kind(isSpecialization? ExplicitSpecialization : Template),
+        TemplateParams(TemplateParams) { }
+
+    explicit ParsedTemplateInfo(SourceLocation TemplateLoc)
+      : Kind(ExplicitInstantiation), 
+        TemplateLoc(TemplateLoc) { }
+
+    /// \brief The kind of template we are parsing.
+    enum {
+      /// \brief We are not parsing a template at all.
+      NonTemplate = 0,
+      /// \brief We are parsing a template declaration.
+      Template,
+      /// \brief We are parsing an explicit specialization.
+      ExplicitSpecialization,
+      /// \brief We are parsing an explicit instantiation.
+      ExplicitInstantiation
+    } Kind;
+
+    /// \brief The template parameter lists, for template declarations
+    /// and explicit specializations.
+    TemplateParameterLists *TemplateParams;
+
+    /// \brief The location of the 'template' keyword, for an explicit
+    /// instantiation.
+    SourceLocation TemplateLoc;
+  };
+
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
   DeclGroupPtrTy ParseExternalDeclaration();
@@ -823,14 +860,15 @@
   DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
 
   bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
-                        TemplateParameterLists *TemplateParams,
+                        const ParsedTemplateInfo &TemplateInfo,
                         AccessSpecifier AS);
   void ParseDeclarationSpecifiers(DeclSpec &DS, 
-                                  TemplateParameterLists *TemplateParams = 0,
+                const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
                                   AccessSpecifier AS = AS_none);
   bool ParseOptionalTypeSpecifier(DeclSpec &DS, int &isInvalid, 
                                   const char *&PrevSpec,
-                                  TemplateParameterLists *TemplateParams = 0);
+               const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+
   void ParseSpecifierQualifierList(DeclSpec &DS);
   
   void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
@@ -1025,7 +1063,7 @@
                             const CXXScopeSpec *SS = 0);
   void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
                            DeclSpec &DS, 
-                           TemplateParameterLists *TemplateParams = 0,
+                const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
                            AccessSpecifier AS = AS_none);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    DeclPtrTy TagDecl);
@@ -1051,13 +1089,15 @@
   typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList;
 
   // C++ 14.1: Template Parameters [temp.param]
+  DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context,
+                                                 SourceLocation &DeclEnd,
+                                                 AccessSpecifier AS = AS_none);
   DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context,
                                                      SourceLocation &DeclEnd,
-                                                   AccessSpecifier AS=AS_none);
+                                                     AccessSpecifier AS);
   DeclPtrTy ParseSingleDeclarationAfterTemplate(
                                        unsigned Context,
-                                       TemplateParameterLists *TemplateParams,
-                                       SourceLocation TemplateLoc,
+                                       const ParsedTemplateInfo &TemplateInfo,
                                        SourceLocation &DeclEnd,
                                        AccessSpecifier AS=AS_none);
   bool ParseTemplateParameters(unsigned Depth, 
@@ -1094,7 +1134,8 @@
                                  TemplateArgIsTypeList &TemplateArgIsType,
                                  TemplateArgLocationList &TemplateArgLocations);
   void *ParseTemplateArgument(bool &ArgIsType);
-  DeclPtrTy ParseExplicitInstantiation(SourceLocation &DeclEnd);
+  DeclPtrTy ParseExplicitInstantiation(SourceLocation TemplateLoc, 
+                                       SourceLocation &DeclEnd);
 
   //===--------------------------------------------------------------------===//
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue May 12 18:25:50 2009
@@ -234,14 +234,8 @@
   DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
   case tok::kw_template:
-    if (NextToken().isNot(tok::less)) {
-      SingleDecl = ParseExplicitInstantiation(DeclEnd);
-      break;
-    }
-    // Fall through for template declarations and specializations
-
   case tok::kw_export:
-    SingleDecl = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd);
+    SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
     break;
   case tok::kw_namespace:
     SingleDecl = ParseNamespace(Context, DeclEnd);
@@ -521,7 +515,7 @@
 /// other pieces of declspec after it, it returns true.
 ///
 bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
-                              TemplateParameterLists *TemplateParams,
+                              const ParsedTemplateInfo &TemplateInfo,
                               AccessSpecifier AS) {
   assert(Tok.is(tok::identifier) && "should have identifier");
   
@@ -576,7 +570,7 @@
       if (TagKind == tok::kw_enum)
         ParseEnumSpecifier(Loc, DS, AS);
       else
-        ParseClassSpecifier(TagKind, Loc, DS, TemplateParams, AS);
+        ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
       return true;
     }
   }
@@ -622,7 +616,7 @@
 
 ///
 void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
-                                        TemplateParameterLists *TemplateParams,
+                                        const ParsedTemplateInfo &TemplateInfo,
                                         AccessSpecifier AS) {
   DS.SetRangeStart(Tok.getLocation());
   while (1) {
@@ -686,7 +680,7 @@
       // typename.  
       if (TypeRep == 0) {
         ConsumeToken();   // Eat the scope spec so the identifier is current.
-        if (ParseImplicitInt(DS, &SS, TemplateParams, AS)) continue;
+        if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue;
         goto DoneWithDeclSpec;
       }
       
@@ -748,7 +742,7 @@
       // If this is not a typedef name, don't parse it as part of the declspec,
       // it must be an implicit int or an error.
       if (TypeRep == 0) {
-        if (ParseImplicitInt(DS, 0, TemplateParams, AS)) continue;
+        if (ParseImplicitInt(DS, 0, TemplateInfo, AS)) continue;
         goto DoneWithDeclSpec;
       }
 
@@ -934,7 +928,7 @@
     case tok::kw_union: {
       tok::TokenKind Kind = Tok.getKind();
       ConsumeToken();
-      ParseClassSpecifier(Kind, Loc, DS, TemplateParams, AS);
+      ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
       continue;
     }
 
@@ -1047,7 +1041,7 @@
 /// [OBJC]  typedef-name objc-protocol-refs[opt]  [TODO]
 bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
                                         const char *&PrevSpec,
-                                        TemplateParameterLists *TemplateParams){
+                                      const ParsedTemplateInfo &TemplateInfo) {
   SourceLocation Loc = Tok.getLocation();
 
   switch (Tok.getKind()) {
@@ -1056,7 +1050,7 @@
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec,TemplateParams);
+      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo);
     // Otherwise, not a type specifier.
     return false;
   case tok::coloncolon:   // ::foo::bar
@@ -1067,7 +1061,7 @@
     // Annotate typenames and C++ scope specifiers.  If we get one, just
     // recurse to handle whatever we get.
     if (TryAnnotateTypeOrScopeToken())
-      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec,TemplateParams);
+      return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo);
     // Otherwise, not a type specifier.
     return false;
       
@@ -1156,7 +1150,7 @@
   case tok::kw_union: {
     tok::TokenKind Kind = Tok.getKind();
     ConsumeToken();
-    ParseClassSpecifier(Kind, Loc, DS, TemplateParams);
+    ParseClassSpecifier(Kind, Loc, DS, TemplateInfo);
     return true;
   }
 

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue May 12 18:25:50 2009
@@ -392,7 +392,7 @@
 ///         'union'
 void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
                                  SourceLocation StartLoc, DeclSpec &DS,
-                                 TemplateParameterLists *TemplateParams,
+                                 const ParsedTemplateInfo &TemplateInfo,
                                  AccessSpecifier AS) {
   DeclSpec::TST TagType;
   if (TagTokKind == tok::kw_struct)
@@ -475,15 +475,72 @@
 
   // Create the tag portion of the class or class template.
   Action::DeclResult TagOrTempResult;
+  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
+  // FIXME: When TK == TK_Reference and we have a template-id, we need
+  // to turn that template-id into a type.
+
   if (TemplateId && TK != Action::TK_Reference) {
-    // Explicit specialization or class template partial
-    // specialization. Let semantic analysis decide.
+    // Explicit specialization, class template partial specialization,
+    // or explicit instantiation.
     ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
                                        TemplateId->getTemplateArgs(),
                                        TemplateId->getTemplateArgIsType(),
                                        TemplateId->NumArgs);
-    TagOrTempResult
-      = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
+    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+        TK == Action::TK_Declaration) {
+      // This is an explicit instantiation of a class template.
+      TagOrTempResult
+        = Actions.ActOnExplicitInstantiation(CurScope, 
+                                             TemplateInfo.TemplateLoc, 
+                                             TagType,
+                                             StartLoc, 
+                                             SS,
+                                     TemplateTy::make(TemplateId->Template), 
+                                             TemplateId->TemplateNameLoc, 
+                                             TemplateId->LAngleLoc, 
+                                             TemplateArgsPtr,
+                                      TemplateId->getTemplateArgLocations(),
+                                             TemplateId->RAngleLoc, 
+                                             Attr);
+    } else {
+      // This is an explicit specialization or a class template
+      // partial specialization.
+      TemplateParameterLists FakedParamLists;
+
+      if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
+        // This looks like an explicit instantiation, because we have
+        // something like
+        //
+        //   template class Foo<X>
+        //
+        // but it is actually a declaration. Most likely, this was
+        // meant to be an explicit specialization, but the user forgot
+        // the '<>' after 'template'.
+        assert(TK == Action::TK_Definition && "Can only get a definition here");
+
+        SourceLocation LAngleLoc 
+          = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+        Diag(TemplateId->TemplateNameLoc, 
+             diag::err_explicit_instantiation_with_definition)
+          << SourceRange(TemplateInfo.TemplateLoc)
+          << CodeModificationHint::CreateInsertion(LAngleLoc, "<>");
+
+        // Create a fake template parameter list that contains only
+        // "template<>", so that we treat this construct as a class
+        // template specialization.
+        FakedParamLists.push_back(
+          Actions.ActOnTemplateParameterList(0, SourceLocation(), 
+                                             TemplateInfo.TemplateLoc,
+                                             LAngleLoc, 
+                                             0, 0, 
+                                             LAngleLoc));
+        TemplateParams = &FakedParamLists;
+      }
+
+      // Build the class template specialization.
+      TagOrTempResult
+        = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
                        StartLoc, SS,
                        TemplateTy::make(TemplateId->Template), 
                        TemplateId->TemplateNameLoc, 
@@ -495,6 +552,7 @@
                        Action::MultiTemplateParamsArg(Actions, 
                                     TemplateParams? &(*TemplateParams)[0] : 0,
                                  TemplateParams? TemplateParams->size() : 0));
+    }
     TemplateId->Destroy();
   } else if (TemplateParams && TK != Action::TK_Reference)
     TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK, 
@@ -691,8 +749,8 @@
       
   if (Tok.is(tok::kw_template)) {
     SourceLocation DeclEnd;
-    ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, DeclEnd,
-                                             AS);
+    ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd, 
+                                         AS);
     return;
   }
 
@@ -708,7 +766,7 @@
   // decl-specifier-seq:
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
-  ParseDeclarationSpecifiers(DS, 0, AS);
+  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
 
   if (Tok.is(tok::semi)) {
     ConsumeToken();

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue May 12 18:25:50 2009
@@ -18,6 +18,18 @@
 #include "AstGuard.h"
 using namespace clang;
 
+/// \brief Parse a template declaration, explicit instantiation, or
+/// explicit specialization.
+Parser::DeclPtrTy
+Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
+                                             SourceLocation &DeclEnd,
+                                             AccessSpecifier AS) {
+  if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less))
+    return ParseExplicitInstantiation(ConsumeToken(), DeclEnd);
+
+  return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
+}
+
 /// \brief Parse a template declaration or an explicit specialization.
 ///
 /// Template declarations include one or more template parameter lists
@@ -64,6 +76,7 @@
   // defining A<T>::B receives just the inner template parameter list
   // (and retrieves the outer template parameter list from its
   // context).
+  bool isSpecialiation = true;
   TemplateParameterLists ParamLists;
   do {
     // Consume the 'export', if any.
@@ -87,6 +100,9 @@
     ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc, 
                             RAngleLoc);
 
+    if (!TemplateParams.empty())
+      isSpecialiation = false;
+
     ParamLists.push_back(
       Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc, 
                                          TemplateLoc, LAngleLoc, 
@@ -95,8 +111,9 @@
   } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
   // Parse the actual template declaration.
-  return ParseSingleDeclarationAfterTemplate(Context, &ParamLists,
-                                             SourceLocation(),
+  return ParseSingleDeclarationAfterTemplate(Context, 
+                                             ParsedTemplateInfo(&ParamLists,
+                                                             isSpecialiation),
                                              DeclEnd, AS);
 }
 
@@ -123,14 +140,16 @@
 Parser::DeclPtrTy 
 Parser::ParseSingleDeclarationAfterTemplate(
                                        unsigned Context,
-                                       TemplateParameterLists *TemplateParams,
-                                       SourceLocation TemplateLoc,
+                                       const ParsedTemplateInfo &TemplateInfo,
                                        SourceLocation &DeclEnd,
                                        AccessSpecifier AS) {
+  assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
+         "Template information required");
+
   // Parse the declaration specifiers.
   DeclSpec DS;
   // FIXME: Pass TemplateLoc through for explicit template instantiations
-  ParseDeclarationSpecifiers(DS, TemplateParams, AS);
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
 
   if (Tok.is(tok::semi)) {
     DeclEnd = ConsumeToken();
@@ -156,7 +175,7 @@
 
     if (Tok.is(tok::comma)) {
       Diag(Tok, diag::err_multiple_template_declarators)
-        << (TemplateParams == 0);
+        << (int)TemplateInfo.Kind;
       SkipUntil(tok::semi, true, false);
       return ThisDecl;
     }
@@ -785,11 +804,10 @@
 ///
 ///       explicit-instantiation:
 ///         'template' declaration
-Parser::DeclPtrTy Parser::ParseExplicitInstantiation(SourceLocation &DeclEnd) {
-  assert(Tok.is(tok::kw_template) && NextToken().isNot(tok::less) &&
-	 "Token does not start an explicit instantiation.");
-  
-  SourceLocation TemplateLoc = ConsumeToken();
-  return ParseSingleDeclarationAfterTemplate(Declarator::FileContext, 0, 
-                                             TemplateLoc, DeclEnd, AS_none);
+Parser::DeclPtrTy 
+Parser::ParseExplicitInstantiation(SourceLocation TemplateLoc,
+                                   SourceLocation &DeclEnd) {
+  return ParseSingleDeclarationAfterTemplate(Declarator::FileContext, 
+                                             ParsedTemplateInfo(TemplateLoc),
+                                             DeclEnd, AS_none);
 }

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

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue May 12 18:25:50 2009
@@ -480,7 +480,7 @@
 Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
-  ParseDeclarationSpecifiers(DS, 0, AS);
+  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
   // declaration-specifiers init-declarator-list[opt] ';'

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=71608&r1=71607&r2=71608&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue May 12 18:25:50 2009
@@ -1017,13 +1017,16 @@
   // FIXME: Warn on useless const/volatile
   // FIXME: Warn on useless static/extern/typedef/private_extern/mutable
   // FIXME: Warn on useless attributes
-
   TagDecl *Tag = 0;
   if (DS.getTypeSpecType() == DeclSpec::TST_class ||
       DS.getTypeSpecType() == DeclSpec::TST_struct ||
       DS.getTypeSpecType() == DeclSpec::TST_union ||
-      DS.getTypeSpecType() == DeclSpec::TST_enum)
+      DS.getTypeSpecType() == DeclSpec::TST_enum) {
+    if (!DS.getTypeRep()) // We probably had an error
+      return DeclPtrTy();
+
     Tag = dyn_cast<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
+  }
 
   if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
     if (!Record->getDeclName() && Record->isDefinition() &&

Added: cfe/trunk/test/SemaTemplate/temp_explicit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_explicit.cpp?rev=71608&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_explicit.cpp (added)
+++ cfe/trunk/test/SemaTemplate/temp_explicit.cpp Tue May 12 18:25:50 2009
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+//
+// Tests explicit instantiation of templates.
+template<typename T, typename U = T> class X0 { };
+
+namespace N {
+  template<typename T, typename U = T> class X1 { };
+}
+
+template class X0<int, float>;
+template class X0<int>;
+
+template class N::X1<int>;
+template class ::N::X1<int, float>;
+
+using namespace N;
+template class X1<float>;
+
+template class X0<double> { }; // expected-error{{explicit specialization}}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=71608&r1=71607&r2=71608&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Tue May 12 18:25:50 2009
@@ -2053,11 +2053,11 @@
 </tr>
 <tr>
   <td>    14.7.2 [temp.explicit]</td>
+  <td class="basic" align="center"></td>
+  <td class="basic" align="center"></td>
   <td class="broken" align="center"></td>
   <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td></td>  
+  <td>Function templates cannot be instantiated</td>  
 </tr>
 <tr>
   <td>    14.7.3 [temp.expl.spec]</td>





More information about the cfe-commits mailing list