[cfe-commits] r81053 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclTemplate.h lib/AST/Decl.cpp lib/CodeGen/CodeGenModule.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaType.cpp test/CodeGenCXX/explicit-instantiation.cpp

Douglas Gregor dgregor at apple.com
Fri Sep 4 15:48:12 PDT 2009


Author: dgregor
Date: Fri Sep  4 17:48:11 2009
New Revision: 81053

URL: http://llvm.org/viewvc/llvm-project?rev=81053&view=rev
Log:
Improve the AST representation and semantic analysis for extern
templates. We now distinguish between an explicit instantiation
declaration and an explicit instantiation definition, and know not to
instantiate explicit instantiation declarations. Unfortunately, there
is some remaining confusion w.r.t. instantiation of out-of-line member
function definitions that causes trouble here.
 

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep  4 17:48:11 2009
@@ -715,6 +715,29 @@
   static bool classof(const OriginalParmVarDecl *D) { return true; }
 };
   
+// \brief Describes the kind of template specialization that a
+// particular template specialization declaration represents.
+enum TemplateSpecializationKind {
+  /// This template specialization was formed from a template-id but
+  /// has not yet been declared, defined, or instantiated.
+  TSK_Undeclared = 0,
+  /// This template specialization was implicitly instantiated from a
+  /// template. (C++ [temp.inst]).
+  TSK_ImplicitInstantiation,
+  /// This template specialization was declared or defined by an
+  /// explicit specialization (C++ [temp.expl.spec]) or partial
+  /// specialization (C++ [temp.class.spec]).
+  TSK_ExplicitSpecialization,
+  /// This template specialization was instantiated from a template
+  /// due to an explicit instantiation declaration request 
+  /// (C++0x [temp.explicit]).
+  TSK_ExplicitInstantiationDeclaration,
+  /// This template specialization was instantiated from a template
+  /// due to an explicit instantiation definition request 
+  /// (C++ [temp.explicit]).
+  TSK_ExplicitInstantiationDefinition  
+};
+  
 /// FunctionDecl - An instance of this class is created to represent a
 /// function declaration or definition. 
 ///
@@ -1077,14 +1100,14 @@
                                       const TemplateArgumentList *TemplateArgs,
                                          void *InsertPos);
 
-  /// \brief Determine whether this is an explicit specialization of a 
-  /// function template or a member function of a class template.
-  bool isExplicitSpecialization() const;
-
-  /// \brief Note that this is an explicit specialization of a function template
-  /// or a member function of a class template.
-  void setExplicitSpecialization(bool ES);
-                                 
+  /// \brief Determine what kind of template instantiation this function
+  /// represents.
+  TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+  /// \brief Determine what kind of template instantiation this function
+  /// represents.
+  void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+                       
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Fri Sep  4 17:48:11 2009
@@ -510,9 +510,8 @@
   /// \brief The function template from which this function template 
   /// specialization was generated.
   ///
-  /// The bit will be 0 for an implicit instantiation, 1 for an explicit 
-  /// specialization.
-  llvm::PointerIntPair<FunctionTemplateDecl *, 1> Template;
+  /// The two bits are contain the top 4 values of TemplateSpecializationKind.
+  llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
   
   /// \brief The template arguments used to produce the function template
   /// specialization from the function template.
@@ -520,14 +519,17 @@
   
   /// \brief Retrieve the template from which this function was specialized.
   FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
-  
-  /// \brief Determine whether this is an explicit specialization.
-  bool isExplicitSpecialization() const { return Template.getInt(); }
-  
-  /// \brief Set whether this is an explicit specialization or an implicit
-  /// instantiation.
-  void setExplicitSpecialization(bool ES) {
-    Template.setInt(ES);
+
+  /// \brief Determine what kind of template specialization this is.
+  TemplateSpecializationKind getTemplateSpecializationKind() const {
+    return (TemplateSpecializationKind)(Template.getInt() + 1);
+  }
+
+  /// \brief Set the template specialization kind.
+  void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+    assert(TSK != TSK_Undeclared && 
+         "Cannot encode TSK_Undeclared for a function template specialization");
+    Template.setInt(TSK - 1);
   }
   
   void Profile(llvm::FoldingSetNodeID &ID) {
@@ -871,24 +873,6 @@
   static bool classof(const TemplateTemplateParmDecl *D) { return true; }
 };
 
-// \brief Describes the kind of template specialization that a
-// particular template specialization declaration represents.
-enum TemplateSpecializationKind {
-  /// This template specialization was formed from a template-id but
-  /// has not yet been declared, defined, or instantiated.
-  TSK_Undeclared = 0,
-  /// This template specialization was declared or defined by an
-  /// explicit specialization (C++ [temp.expl.spec]) or partial
-  /// specialization (C++ [temp.class.spec]).
-  TSK_ExplicitSpecialization,
-  /// This template specialization was implicitly instantiated from a
-  /// template. (C++ [temp.inst]).
-  TSK_ImplicitInstantiation,
-  /// This template specialization was instantiated from a template
-  /// due to an explicit instantiation request (C++ [temp.explicit]).
-  TSK_ExplicitInstantiation
-};
-
 /// \brief Represents a class template specialization, which refers to
 /// a class template with a given set of template arguments.
 ///
@@ -927,7 +911,7 @@
 
   /// \brief The kind of specialization this declaration refers to.
   /// Really a value of type TemplateSpecializationKind.
-  unsigned SpecializationKind : 2;
+  unsigned SpecializationKind : 3;
 
 protected:
   ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
@@ -972,7 +956,8 @@
                      ClassTemplatePartialSpecializationDecl *>
   getInstantiatedFrom() const {
     if (getSpecializationKind() != TSK_ImplicitInstantiation &&
-        getSpecializationKind() != TSK_ExplicitInstantiation)
+        getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+        getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
       return (ClassTemplateDecl*)0;
     
     if (SpecializedPartialSpecialization *PartialSpec 

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Sep  4 17:48:11 2009
@@ -640,7 +640,7 @@
   
   Info->Function = this;
   Info->Template.setPointer(Template);
-  Info->Template.setInt(0); // Implicit instantiation, unless told otherwise
+  Info->Template.setInt(TSK_ImplicitInstantiation - 1);
   Info->TemplateArguments = TemplateArgs;
   TemplateOrSpecialization = Info;
   
@@ -649,24 +649,35 @@
   Template->getSpecializations().InsertNode(Info, InsertPos);
 }
 
-bool FunctionDecl::isExplicitSpecialization() const {
-  // FIXME: check this property for explicit specializations of member
-  // functions of class templates.
+TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
+  // For a function template specialization, query the specialization 
+  // information object.
   FunctionTemplateSpecializationInfo *Info 
     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
-  if (!Info)
-    return false;
+  if (Info)
+    return Info->getTemplateSpecializationKind();
+  
+  if (!getInstantiatedFromMemberFunction())
+    return TSK_Undeclared;
+  
+  // Find the class template specialization corresponding to this instantiation
+  // of a member function.
+  const DeclContext *Parent = getDeclContext();
+  while (Parent && !isa<ClassTemplateSpecializationDecl>(Parent))
+    Parent = Parent->getParent();
   
-  return Info->isExplicitSpecialization();
+  if (!Parent)
+    return TSK_Undeclared;
+
+  return cast<ClassTemplateSpecializationDecl>(Parent)->getSpecializationKind();
 }
 
-void FunctionDecl::setExplicitSpecialization(bool ES) {
-  // FIXME: set this property for explicit specializations of member functions
-  // of class templates.
+void 
+FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
   FunctionTemplateSpecializationInfo *Info 
     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
-  if (Info)
-    Info->setExplicitSpecialization(ES);
+  assert(Info && "Not a function template specialization");
+  Info->setTemplateSpecializationKind(TSK);
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Sep  4 17:48:11 2009
@@ -250,9 +250,8 @@
   // The kind of external linkage this function will have, if it is not
   // inline or static.
   CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
-  if (Context.getLangOptions().CPlusPlus &&
-      (FD->getPrimaryTemplate() || FD->getInstantiatedFromMemberFunction()) &&
-      !FD->isExplicitSpecialization())
+  if (Context.getLangOptions().CPlusPlus && 
+      FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
     External = CodeGenModule::GVA_TemplateInstantiation;
       
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Sep  4 17:48:11 2009
@@ -3011,21 +3011,24 @@
   InstantiateClass(SourceLocation PointOfInstantiation,
                    CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
                    const MultiLevelTemplateArgumentList &TemplateArgs,
-                   bool ExplicitInstantiation,
+                   TemplateSpecializationKind TSK,
                    bool Complain = true);
 
   bool 
   InstantiateClassTemplateSpecialization(
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                           bool ExplicitInstantiation, bool Complain = true);
+                           TemplateSpecializationKind TSK,
+                           bool Complain = true);
 
   void InstantiateClassMembers(SourceLocation PointOfInstantiation,
                                CXXRecordDecl *Instantiation,
-                            const MultiLevelTemplateArgumentList &TemplateArgs);
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                               TemplateSpecializationKind TSK);
 
   void InstantiateClassTemplateSpecializationMembers(
                                           SourceLocation PointOfInstantiation,
-                           ClassTemplateSpecializationDecl *ClassTemplateSpec);
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                                                TemplateSpecializationKind TSK);
 
   NestedNameSpecifier *
   SubstNestedNameSpecifier(NestedNameSpecifier *NNS,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Sep  4 17:48:11 2009
@@ -2934,7 +2934,8 @@
 
   bool SpecializationRequiresInstantiation = true;
   if (PrevDecl) {
-    if (PrevDecl->getSpecializationKind() == TSK_ExplicitInstantiation) {
+    if (PrevDecl->getSpecializationKind() 
+          == TSK_ExplicitInstantiationDefinition) {
       // This particular specialization has already been declared or
       // instantiated. We cannot explicitly instantiate it.
       Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate)
@@ -3028,16 +3029,19 @@
   //
   // This check comes when we actually try to perform the
   // instantiation.
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition 
+                           : TSK_ExplicitInstantiationDeclaration;
   if (SpecializationRequiresInstantiation)
-    InstantiateClassTemplateSpecialization(Specialization, true);
+    InstantiateClassTemplateSpecialization(Specialization, TSK);
   else // Instantiate the members of this class template specialization.
-    InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
+    InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization,
+                                                  TSK);
 
   return DeclPtrTy::make(Specialization);
 }
 
 // Explicit instantiation of a member class of a class template.
-// FIXME: Implement extern template semantics.
 Sema::DeclResult
 Sema::ActOnExplicitInstantiation(Scope *S, 
                                  SourceLocation ExternLoc,
@@ -3092,17 +3096,21 @@
     }
   }
 
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition 
+                           : TSK_ExplicitInstantiationDeclaration;
+  
   if (!Record->getDefinition(Context)) {
     // If the class has a definition, instantiate it (and all of its
     // members, recursively).
     Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
     if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, 
                                     getTemplateInstantiationArgs(Record),
-                                    /*ExplicitInstantiation=*/true))
+                                    TSK))
       return true;
   } else // Instantiate all of the members of the class.
     InstantiateClassMembers(TemplateLoc, Record, 
-                            getTemplateInstantiationArgs(Record));
+                            getTemplateInstantiationArgs(Record), TSK);
 
   // FIXME: We don't have any representation for explicit instantiations of
   // member classes. Such a representation is not needed for compilation, but it

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Sep  4 17:48:11 2009
@@ -623,8 +623,7 @@
 /// \param TemplateArgs The template arguments to be substituted into
 /// the pattern.
 ///
-/// \param ExplicitInstantiation whether this is an explicit instantiation
-/// (otherwise, it is an implicit instantiation).
+/// \param TSK the kind of implicit or explicit instantiation to perform.
 ///
 /// \param Complain whether to complain if the class cannot be instantiated due
 /// to the lack of a definition.
@@ -634,7 +633,7 @@
 Sema::InstantiateClass(SourceLocation PointOfInstantiation,
                        CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
                        const MultiLevelTemplateArgumentList &TemplateArgs,
-                       bool ExplicitInstantiation,
+                       TemplateSpecializationKind TSK,
                        bool Complain) {
   bool Invalid = false;
 
@@ -650,7 +649,7 @@
       Diag(Pattern->getLocation(), diag::note_member_of_template_here);
     } else {
       Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
-        << ExplicitInstantiation
+        << (TSK != TSK_ImplicitInstantiation)
         << Context.getTypeDeclType(Instantiation);
       Diag(Pattern->getLocation(), diag::note_template_decl_here);
     }
@@ -708,9 +707,10 @@
     Consumer.HandleTagDeclDefinition(Instantiation);
 
   // If this is an explicit instantiation, instantiate our members, too.
-  if (!Invalid && ExplicitInstantiation) {
+  if (!Invalid && TSK != TSK_ImplicitInstantiation) {
     Inst.Clear();
-    InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
+    InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs,
+                            TSK);
   }
 
   return Invalid;
@@ -719,7 +719,7 @@
 bool 
 Sema::InstantiateClassTemplateSpecialization(
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                           bool ExplicitInstantiation,
+                           TemplateSpecializationKind TSK,
                            bool Complain) {
   // Perform the actual instantiation on the canonical declaration.
   ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
@@ -798,14 +798,12 @@
   }
 
   // Note that this is an instantiation.
-  ClassTemplateSpec->setSpecializationKind(
-                        ExplicitInstantiation? TSK_ExplicitInstantiation 
-                                             : TSK_ImplicitInstantiation);
+  ClassTemplateSpec->setSpecializationKind(TSK);
 
   bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
                                  ClassTemplateSpec, Pattern, 
                               getTemplateInstantiationArgs(ClassTemplateSpec),
-                                 ExplicitInstantiation,
+                                 TSK,
                                  Complain);
   
   for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
@@ -822,8 +820,10 @@
 /// or a member class of a template.
 void
 Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
-                        CXXRecordDecl *Instantiation,
-                        const MultiLevelTemplateArgumentList &TemplateArgs) {
+                              CXXRecordDecl *Instantiation,
+                        const MultiLevelTemplateArgumentList &TemplateArgs,
+                              TemplateSpecializationKind TSK) {
+  // FIXME: extern templates
   for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
                                DEnd = Instantiation->decls_end();
        D != DEnd; ++D) {
@@ -839,7 +839,8 @@
                "Missing instantiated-from-template information");
         InstantiateClass(PointOfInstantiation, Record,
                          Record->getInstantiatedFromMemberClass(),
-                         TemplateArgs, true);
+                         TemplateArgs,
+                         TSK);
       }
     }
   }
@@ -848,9 +849,11 @@
 /// \brief Instantiate the definitions of all of the members of the
 /// given class template specialization, which was named as part of an
 /// explicit instantiation.
-void Sema::InstantiateClassTemplateSpecializationMembers(
+void 
+Sema::InstantiateClassTemplateSpecializationMembers(
                                            SourceLocation PointOfInstantiation,
-                          ClassTemplateSpecializationDecl *ClassTemplateSpec) {
+                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                                               TemplateSpecializationKind TSK) {
   // C++0x [temp.explicit]p7:
   //   An explicit instantiation that names a class template
   //   specialization is an explicit instantion of the same kind
@@ -860,7 +863,8 @@
   //   containing the explicit instantiation, except as described
   //   below.
   InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
-                          getTemplateInstantiationArgs(ClassTemplateSpec));
+                          getTemplateInstantiationArgs(ClassTemplateSpec),
+                          TSK);
 }
 
 Sema::OwningStmtResult 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Sep  4 17:48:11 2009
@@ -402,6 +402,8 @@
 
 Decl *
 TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  // FIXME: Dig out the out-of-line definition of this function template?
+  
   TemplateParameterList *TempParams = D->getTemplateParameters();
   TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
   if (!InstParams) 
@@ -496,7 +498,7 @@
                            D->getStorageClass(),
                            D->isInline(), D->hasWrittenPrototype());
   Function->setLexicalDeclContext(Owner);
-
+  
   // Attach the parameters
   for (unsigned P = 0; P < Params.size(); ++P)
     Params[P]->setOwningFunction(Function);
@@ -622,7 +624,7 @@
                                                     Method->getDeclName(), 
                                                     TemplateParams, Method);
     if (D->isOutOfLine())
-      FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+      FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());    
     Method->setDescribedFunctionTemplate(FunctionTemplate);
   } else if (!FunctionTemplate)
     Method->setInstantiationOfMemberFunction(D);
@@ -979,6 +981,15 @@
   if (!Pattern)
     return;
 
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity 
+  //   to which they refer.
+  if (Function->getTemplateSpecializationKind() 
+        == TSK_ExplicitInstantiationDeclaration &&
+      PatternDecl->isOutOfLine() && !PatternDecl->isInline())
+    return;
+  
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
   if (Inst)
     return;
@@ -1080,6 +1091,8 @@
     return;
   }
 
+  // FIXME: extern templates
+  
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
   if (Inst)
     return;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Sep  4 17:48:11 2009
@@ -1781,7 +1781,7 @@
         if (Loc.isValid())
           ClassTemplateSpec->setLocation(Loc);
         return InstantiateClassTemplateSpecialization(ClassTemplateSpec,
-                                             /*ExplicitInstantiation=*/false,
+                                                      TSK_ImplicitInstantiation,
                                                       /*Complain=*/diag != 0);
       }
     } else if (CXXRecordDecl *Rec 
@@ -1790,7 +1790,7 @@
         // This record was instantiated from a class within a template.
         return InstantiateClass(Loc, Rec, Pattern, 
                                 getTemplateInstantiationArgs(Rec),
-                                /*ExplicitInstantiation=*/false,
+                                TSK_ImplicitInstantiation,
                                 /*Complain=*/diag != 0);
       }
     }

Modified: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp?rev=81053&r1=81052&r2=81053&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Fri Sep  4 17:48:11 2009
@@ -1,11 +1,17 @@
 // RUN: clang-cc -emit-llvm -femit-all-decls -o %t %s &&
 // RUN: grep "_ZNK4plusIillEclERKiRKl" %t | count 1
 
+// FIXME: We should not need the -femit-all-decls, because operator() should
+// be emitted as an external symbol rather than with linkonce_odr linkage.
+// This is a Sema problem.
 template<typename T, typename U, typename Result>
 struct plus {
-  Result operator()(const T& t, const U& u) const {
-    return t + u;
-  }
+  Result operator()(const T& t, const U& u) const;
 };
 
+template<typename T, typename U, typename Result>
+Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
+  return t + u;
+}
+
 template struct plus<int, long, long>;





More information about the cfe-commits mailing list