[cfe-commits] r83890 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h include/clang/AST/DeclTemplate.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Decl.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/SemaTemplate/class-template-spec.cpp

Douglas Gregor dgregor at apple.com
Mon Oct 12 13:18:29 PDT 2009


Author: dgregor
Date: Mon Oct 12 15:18:28 2009
New Revision: 83890

URL: http://llvm.org/viewvc/llvm-project?rev=83890&view=rev
Log:
Diagnose the declaration of explicit specializations after an implicit
instantiation has already been required. To do so, keep track of the
point of instantiation for anything that can be instantiated.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/SemaTemplate/class-template-spec.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Oct 12 15:18:28 2009
@@ -593,6 +593,11 @@
   /// template specialization or instantiation this is.
   TemplateSpecializationKind getTemplateSpecializationKind();
   
+  /// \brief If this variable is an instantiation of a static data member of a
+  /// class template specialization, retrieves the member specialization
+  /// information.
+  MemberSpecializationInfo *getMemberSpecializationInfo();
+  
   /// \brief For a static data member that was instantiated from a static
   /// data member of a class template, set the template specialiation kind.
   void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
@@ -1075,6 +1080,11 @@
   /// declaration returned by getInstantiatedFromMemberFunction().
   FunctionDecl *getInstantiatedFromMemberFunction() const;
 
+  /// \brief If this function is an instantiation of a member function of a
+  /// class template specialization, retrieves the member specialization
+  /// information.
+  MemberSpecializationInfo *getMemberSpecializationInfo() const;
+                       
   /// \brief Specify that this record is an instantiation of the
   /// member function FD.
   void setInstantiationOfMemberFunction(FunctionDecl *FD,
@@ -1105,6 +1115,14 @@
   bool isFunctionTemplateSpecialization() const {
     return getPrimaryTemplate() != 0;
   }
+       
+  /// \brief If this function is actually a function template specialization,
+  /// retrieve information about this function template specialization. 
+  /// Otherwise, returns NULL.
+  FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
+    return TemplateOrSpecialization.
+             dyn_cast<FunctionTemplateSpecializationInfo*>();
+  }
                        
   /// \brief Retrieve the primary template that this function template
   /// specialization either specializes or was instantiated from.

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Oct 12 15:18:28 2009
@@ -706,6 +706,11 @@
   /// declaration returned by getInstantiatedFromMemberClass().
   CXXRecordDecl *getInstantiatedFromMemberClass() const;
   
+  /// \brief If this class is an instantiation of a member class of a
+  /// class template specialization, retrieves the member specialization
+  /// information.
+  MemberSpecializationInfo *getMemberSpecializationInfo() const;
+  
   /// \brief Specify that this record is an instantiation of the
   /// member class RD.
   void setInstantiationOfMemberClass(CXXRecordDecl *RD,

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Oct 12 15:18:28 2009
@@ -518,6 +518,10 @@
   /// specialization from the function template.
   const TemplateArgumentList *TemplateArguments;
 
+  /// \brief The point at which this function template specialization was
+  /// first instantiated. 
+  SourceLocation PointOfInstantiation;
+  
   /// \brief Retrieve the template from which this function was specialized.
   FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
 
@@ -533,6 +537,21 @@
     Template.setInt(TSK - 1);
   }
 
+  /// \brief Retrieve the first point of instantiation of this function
+  /// template specialization.
+  ///
+  /// The point of instantiation may be an invalid source location if this
+  /// function has yet to be instantiated.
+  SourceLocation getPointOfInstantiation() const { 
+    return PointOfInstantiation; 
+  }
+  
+  /// \brief Set the (first) point of instantiation of this function template
+  /// specialization.
+  void setPointOfInstantiation(SourceLocation POI) {
+    PointOfInstantiation = POI;
+  }
+  
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, TemplateArguments->getFlatArgumentList(),
             TemplateArguments->flat_size(),
@@ -556,10 +575,13 @@
   // manner in which the instantiation occurred (in the lower two bits).
   llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
   
+  // The point at which this member was first instantiated.
+  SourceLocation PointOfInstantiation;
+  
 public:
   explicit 
   MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK)
-    : MemberAndTSK(IF, TSK - 1) {
+    : MemberAndTSK(IF, TSK - 1), PointOfInstantiation() {
     assert(TSK != TSK_Undeclared && 
            "Cannot encode undeclared template specializations for members");
   }
@@ -579,6 +601,18 @@
            "Cannot encode undeclared template specializations for members");
     MemberAndTSK.setInt(TSK - 1);
   }
+  
+  /// \brief Retrieve the first point of instantiation of this member. 
+  /// If the point of instantiation is an invalid location, then this member
+  /// has not yet been instantiated.
+  SourceLocation getPointOfInstantiation() const { 
+    return PointOfInstantiation; 
+  }
+  
+  /// \brief Set the first point of instantiation.
+  void setPointOfInstantiation(SourceLocation POI) {
+    PointOfInstantiation = POI;
+  }
 };
   
 /// Declaration of a template function.

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 12 15:18:28 2009
@@ -967,6 +967,10 @@
 def err_spec_member_not_instantiated : Error<
   "specialization of member %q0 does not specialize an instantiated member">;
 def note_specialized_decl : Note<"attempt to specialize declaration here">;
+def err_specialization_after_instantiation : Error<
+  "explicit specialization of %0 after instantiation">;
+def note_instantiation_required_here : Note<
+  "%select{implicit|explicit}0 instantiation first required here">;
 
 // C++ class template specializations and out-of-line definitions
 def err_template_spec_needs_header : Error<

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Oct 12 15:18:28 2009
@@ -374,8 +374,7 @@
 }
 
 VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
-  if (MemberSpecializationInfo *MSI
-        = getASTContext().getInstantiatedFromStaticDataMember(this))
+  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
     return cast<VarDecl>(MSI->getInstantiatedFrom());
   
   return 0;
@@ -389,9 +388,12 @@
   return TSK_Undeclared;
 }
 
+MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() {
+  return getASTContext().getInstantiatedFromStaticDataMember(this);
+}
+
 void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
-  MemberSpecializationInfo *MSI
-    = getASTContext().getInstantiatedFromStaticDataMember(this);
+  MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
   assert(MSI && "Not an instantiated static data member?");
   MSI->setTemplateSpecializationKind(TSK);
 }
@@ -703,13 +705,16 @@
 }
 
 FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
-  if (MemberSpecializationInfo *Info 
-        = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+  if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
     return cast<FunctionDecl>(Info->getInstantiatedFrom());
   
   return 0;
 }
 
+MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
+  return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+}
+
 void 
 FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
                                                TemplateSpecializationKind TSK) {

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Oct 12 15:18:28 2009
@@ -434,13 +434,16 @@
 }
 
 CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
-  if (MemberSpecializationInfo *MSInfo
-        = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>())
+  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
     return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
   
   return 0;
 }
 
+MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
+  return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
+}
+
 void 
 CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
                                              TemplateSpecializationKind TSK) {
@@ -456,8 +459,7 @@
         = dyn_cast<ClassTemplateSpecializationDecl>(this))
     return Spec->getSpecializationKind();
   
-  if (MemberSpecializationInfo *MSInfo
-      = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>())
+  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
     return MSInfo->getTemplateSpecializationKind();
   
   return TSK_Undeclared;
@@ -471,8 +473,7 @@
     return;
   }
   
-  if (MemberSpecializationInfo *MSInfo
-        = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>()) {
+  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
     MSInfo->setTemplateSpecializationKind(TSK);
     return;
   }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Oct 12 15:18:28 2009
@@ -4279,14 +4279,22 @@
           // Diagnose attempts to redefine a tag.
           if (TUK == TUK_Definition) {
             if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
-              Diag(NameLoc, diag::err_redefinition) << Name;
-              Diag(Def->getLocation(), diag::note_previous_definition);
-              // If this is a redefinition, recover by making this
-              // struct be anonymous, which will make any later
-              // references get the previous definition.
-              Name = 0;
-              PrevDecl = 0;
-              Invalid = true;
+              // If we're defining a specialization and the previous definition
+              // is from an implicit instantiation, don't emit an error
+              // here; we'll catch this in the general case below.
+              if (!isExplicitSpecialization ||
+                  !isa<CXXRecordDecl>(Def) ||
+                  cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() 
+                                               == TSK_ExplicitSpecialization) {
+                Diag(NameLoc, diag::err_redefinition) << Name;
+                Diag(Def->getLocation(), diag::note_previous_definition);
+                // If this is a redefinition, recover by making this
+                // struct be anonymous, which will make any later
+                // references get the previous definition.
+                Name = 0;
+                PrevDecl = 0;
+                Invalid = true;
+              }
             } else {
               // If the type is currently being defined, complain
               // about a nested redefinition.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct 12 15:18:28 2009
@@ -6199,10 +6199,28 @@
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
     // Implicit instantiation of function templates and member functions of
     // class templates.
-    if (!Function->getBody() && 
-        Function->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
-      PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
-
+    if (!Function->getBody() &&
+        Function->getTemplateSpecializationKind() 
+                                                == TSK_ImplicitInstantiation) {
+      bool AlreadyInstantiated = false;
+      if (FunctionTemplateSpecializationInfo *SpecInfo
+                                = Function->getTemplateSpecializationInfo()) {
+        if (SpecInfo->getPointOfInstantiation().isInvalid())
+          SpecInfo->setPointOfInstantiation(Loc);
+        else
+          AlreadyInstantiated = true;
+      } else if (MemberSpecializationInfo *MSInfo 
+                                  = Function->getMemberSpecializationInfo()) {
+        if (MSInfo->getPointOfInstantiation().isInvalid())
+          MSInfo->setPointOfInstantiation(Loc);
+        else
+          AlreadyInstantiated = true;
+      }
+      
+      if (!AlreadyInstantiated)
+        PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
+    }
+    
     // FIXME: keep track of references to static functions
     Function->setUsed(true);
     return;
@@ -6211,9 +6229,15 @@
   if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
     // Implicit instantiation of static data members of class templates.
     if (Var->isStaticDataMember() &&
-        Var->getInstantiatedFromStaticDataMember() &&
-        Var->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
-      PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+        Var->getInstantiatedFromStaticDataMember()) {
+      MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+      assert(MSInfo && "Missing member specialization information?");
+      if (MSInfo->getPointOfInstantiation().isInvalid() &&
+          MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
+        MSInfo->setPointOfInstantiation(Loc);
+        PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+      }
+    }
 
     // FIXME: keep track of references to static data?
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Oct 12 15:18:28 2009
@@ -2820,7 +2820,7 @@
                                        TemplateNameLoc, isPartialSpecialization,
                                        TSK_ExplicitSpecialization))
     return true;
-
+  
   // The canonical type
   QualType CanonType;
   if (PrevDecl && 
@@ -2918,6 +2918,24 @@
     CanonType = Context.getTypeDeclType(Specialization);
   }
 
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+    SourceRange Range(TemplateNameLoc, RAngleLoc);
+    Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+      << Context.getTypeDeclType(Specialization) << Range;
+
+    Diag(PrevDecl->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (PrevDecl->getTemplateSpecializationKind() 
+                                                != TSK_ImplicitInstantiation);
+    return true;
+  }
+  
   // If this is not a friend, note that this is an explicit specialization.
   if (TUK != TUK_Friend)
     Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
@@ -2925,8 +2943,6 @@
   // Check that this isn't a redefinition of this specialization.
   if (TUK == TUK_Definition) {
     if (RecordDecl *Def = Specialization->getDefinition(Context)) {
-      // FIXME: Should also handle explicit specialization after implicit
-      // instantiation with a special diagnostic.
       SourceRange Range(TemplateNameLoc, RAngleLoc);
       Diag(TemplateNameLoc, diag::err_redefinition)
         << Context.getTypeDeclType(Specialization) << Range;
@@ -3106,7 +3122,7 @@
     return true;
   
   // FIXME: Check if the prior specialization has a point of instantiation.
-  // If so, we have run afoul of C++ [temp.expl.spec]p6.
+  // If so, we have run afoul of .
   
   // Check the scope of this explicit specialization.
   if (CheckTemplateSpecializationScope(*this, 
@@ -3114,11 +3130,29 @@
                                        Specialization, FD->getLocation(), 
                                        false, TSK_ExplicitSpecialization))
     return true;
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that spe- cialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  FunctionTemplateSpecializationInfo *SpecInfo
+    = Specialization->getTemplateSpecializationInfo();
+  assert(SpecInfo && "Function template specialization info missing?");
+  if (SpecInfo->getPointOfInstantiation().isValid()) {
+    Diag(FD->getLocation(), diag::err_specialization_after_instantiation)
+      << FD;
+    Diag(SpecInfo->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (Specialization->getTemplateSpecializationKind() 
+                                                != TSK_ImplicitInstantiation);
+    return true;
+  }
   
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
-  // FIXME: Check for prior explicit instantiations?
-  Specialization->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+  SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
   
   // Turn the given function declaration into a function template
   // specialization, with the template arguments from the previous
@@ -3156,6 +3190,8 @@
   // Try to find the member we are instantiating.
   NamedDecl *Instantiation = 0;
   NamedDecl *InstantiatedFrom = 0;
+  MemberSpecializationInfo *MSInfo = 0;
+
   if (!PrevDecl) {
     // Nowhere to look anyway.
   } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
@@ -3164,6 +3200,7 @@
         if (Context.hasSameType(Function->getType(), Method->getType())) {
           Instantiation = Method;
           InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
+          MSInfo = Method->getMemberSpecializationInfo();
           break;
         }
       }
@@ -3173,11 +3210,13 @@
       if (PrevVar->isStaticDataMember()) {
         Instantiation = PrevDecl;
         InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
+        MSInfo = PrevVar->getMemberSpecializationInfo();
       }
   } else if (isa<RecordDecl>(Member)) {
     if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) {
       Instantiation = PrevDecl;
       InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
+      MSInfo = PrevRecord->getMemberSpecializationInfo();
     }
   }
   
@@ -3188,9 +3227,6 @@
     return false;
   }
   
-  // FIXME: Check if the prior declaration has a point of instantiation.
-  // If so, we have run afoul of C++ [temp.expl.spec]p6.
-  
   // Make sure that this is a specialization of a member.
   if (!InstantiatedFrom) {
     Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
@@ -3199,6 +3235,22 @@
     return true;
   }
   
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that spe- cialization shall be declared 
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a 
+  //   use occurs; no diagnostic is required.
+  assert(MSInfo && "Member specialization info missing?");
+  if (MSInfo->getPointOfInstantiation().isValid()) {
+    Diag(Member->getLocation(), diag::err_specialization_after_instantiation)
+      << Member;
+    Diag(MSInfo->getPointOfInstantiation(), 
+         diag::note_instantiation_required_here)
+      << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation);
+    return true;
+  }
+  
   // Check the scope of this explicit specialization.
   if (CheckTemplateSpecializationScope(*this, 
                                        InstantiatedFrom,
@@ -3206,8 +3258,6 @@
                                        false, TSK_ExplicitSpecialization))
     return true;
 
-  // FIXME: Check for specialization-after-instantiation errors and such.
-  
   // Note that this is an explicit instantiation of a member.
   // the original declaration to note that it is an explicit specialization
   // (if it was previously an implicit instantiation). This latter step

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Oct 12 15:18:28 2009
@@ -1677,12 +1677,17 @@
     } else if (CXXRecordDecl *Rec
                  = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
       if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
+        MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo();
+        assert(MSInfo && "Missing member specialization information?");
         // This record was instantiated from a class within a template.
-        if (Rec->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+        if (MSInfo->getTemplateSpecializationKind() 
+                                               != TSK_ExplicitSpecialization) {
+          MSInfo->setPointOfInstantiation(Loc);
           return InstantiateClass(Loc, Rec, Pattern,
                                   getTemplateInstantiationArgs(Rec),
                                   TSK_ImplicitInstantiation,
                                   /*Complain=*/diag != 0);
+        }
       }
     }
   }

Modified: cfe/trunk/test/SemaTemplate/class-template-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-spec.cpp?rev=83890&r1=83889&r2=83890&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-spec.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-spec.cpp Mon Oct 12 15:18:28 2009
@@ -20,7 +20,8 @@
                           A<double> *a2)
 {
   (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
-  (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
+  (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} \
+               // expected-note{{first required here}}
 }
 
 typedef float FLOAT;
@@ -70,7 +71,8 @@
 }
 
 // Diagnose specialization errors
-struct A<double> { }; // expected-error{{template specialization requires 'template<>'}}
+struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} \
+                      // expected-error{{after instantiation}}
 
 template<> struct ::A<double>;
 





More information about the cfe-commits mailing list