[cfe-commits] r107895 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/AST/DeclTemplate.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplate.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-template.cpp

Douglas Gregor dgregor at apple.com
Thu Jul 8 11:37:38 PDT 2010


Author: dgregor
Date: Thu Jul  8 13:37:38 2010
New Revision: 107895

URL: http://llvm.org/viewvc/llvm-project?rev=107895&view=rev
Log:
When performing substitution of template arguments within the body of
a template, be sure to include the template arguments from the
injected-class-name. Fixes PR7587.

Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplate.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Jul  8 13:37:38 2010
@@ -1476,7 +1476,7 @@
   ///   typedef array this_type; // "array" is equivalent to "array<T, N>"
   /// };
   /// \endcode
-  QualType getInjectedClassNameSpecialization(ASTContext &Context);
+  QualType getInjectedClassNameSpecialization();
 
   /// \brief Retrieve the member class template that this class template was
   /// derived from.

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Thu Jul  8 13:37:38 2010
@@ -201,7 +201,7 @@
 }
 
 QualType
-ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
+ClassTemplateDecl::getInjectedClassNameSpecialization() {
   Common *CommonPtr = getCommonPtr();
   if (!CommonPtr->InjectedClassNameType.isNull())
     return CommonPtr->InjectedClassNameType;
@@ -210,7 +210,7 @@
   // corresponding to template parameter packs should be pack
   // expansions. We already say that in 14.6.2.1p2, so it would be
   // better to fix that redundancy.
-
+  ASTContext &Context = getASTContext();
   TemplateParameterList *Params = getTemplateParameters();
   llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
   TemplateArgs.reserve(Params->size());

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Jul  8 13:37:38 2010
@@ -96,7 +96,7 @@
           // injected class name of the named class template, we're entering
           // into that class template definition.
           QualType Injected
-            = ClassTemplate->getInjectedClassNameSpecialization(Context);
+            = ClassTemplate->getInjectedClassNameSpecialization();
           if (Context.hasSameType(Injected, ContextType))
             return ClassTemplate->getTemplatedDecl();
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul  8 13:37:38 2010
@@ -3317,9 +3317,10 @@
       MultiLevelTemplateArgumentList ArgList
         = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
 
-      InstantiatingTemplate Inst(*this, CallLoc, Param,
-                                 ArgList.getInnermost().getFlatArgumentList(),
-                                 ArgList.getInnermost().flat_size());
+      std::pair<const TemplateArgument *, unsigned> Innermost 
+        = ArgList.getInnermost();
+      InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
+                                 Innermost.second);
 
       OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
       if (Result.isInvalid())

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jul  8 13:37:38 2010
@@ -884,7 +884,7 @@
   NewClass->setDescribedClassTemplate(NewTemplate);
 
   // Build the type for the class template declaration now.
-  QualType T = NewTemplate->getInjectedClassNameSpecialization(Context);
+  QualType T = NewTemplate->getInjectedClassNameSpecialization();
   T = Context.getInjectedClassNameType(NewClass, T);
   assert(T->isDependentType() && "Class template type is not dependent?");
   (void)T;

Modified: cfe/trunk/lib/Sema/SemaTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.h?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.h (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.h Thu Jul  8 13:37:38 2010
@@ -36,10 +36,14 @@
   /// When instantiating X<int>::Y<17>::f, the multi-level template argument
   /// list will contain a template argument list (int) at depth 0 and a
   /// template argument list (17) at depth 1.
-  struct MultiLevelTemplateArgumentList {
+  class MultiLevelTemplateArgumentList {
+  public:
+    typedef std::pair<const TemplateArgument *, unsigned> ArgList;
+    
+  private:
     /// \brief The template argument lists, stored from the innermost template
     /// argument list (first) to the outermost template argument list (last).
-    llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists;
+    llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
     
   public:
     /// \brief Construct an empty set of template argument lists.
@@ -48,7 +52,7 @@
     /// \brief Construct a single-level template argument list.
     explicit 
     MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
-      TemplateArgumentLists.push_back(&TemplateArgs);
+      addOuterTemplateArguments(&TemplateArgs);
     }
     
     /// \brief Determine the number of levels in this template argument
@@ -58,8 +62,8 @@
     /// \brief Retrieve the template argument at a given depth and index.
     const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
       assert(Depth < TemplateArgumentLists.size());
-      assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
-      return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
+      assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+      return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
     }
     
     /// \brief Determine whether there is a non-NULL template argument at the
@@ -69,7 +73,7 @@
     bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
       assert(Depth < TemplateArgumentLists.size());
       
-      if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
+      if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
         return false;
       
       return !(*this)(Depth, Index).isNull();
@@ -78,12 +82,21 @@
     /// \brief Add a new outermost level to the multi-level template argument 
     /// list.
     void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
-      TemplateArgumentLists.push_back(TemplateArgs);
+      TemplateArgumentLists.push_back(
+                                    ArgList(TemplateArgs->getFlatArgumentList(),
+                                            TemplateArgs->flat_size()));
+    }
+    
+    /// \brief Add a new outmost level to the multi-level template argument
+    /// list.
+    void addOuterTemplateArguments(const TemplateArgument *Args, 
+                                   unsigned NumArgs) {
+      TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
     }
     
     /// \brief Retrieve the innermost template argument list.
-    const TemplateArgumentList &getInnermost() const {
-      return *TemplateArgumentLists.front();
+    const ArgList &getInnermost() const { 
+      return TemplateArgumentLists.front(); 
     }
   };
   

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jul  8 13:37:38 2010
@@ -63,7 +63,8 @@
     if (ClassTemplateSpecializationDecl *Spec
           = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
       // We're done when we hit an explicit specialization.
-      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization)
+      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+          !isa<ClassTemplatePartialSpecializationDecl>(Spec))
         break;
 
       Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
@@ -104,6 +105,15 @@
         RelativeToPrimary = false;
         continue;
       }
+    } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
+      if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
+        QualType T = ClassTemplate->getInjectedClassNameSpecialization();
+        const TemplateSpecializationType *TST
+          = cast<TemplateSpecializationType>(Context.getCanonicalType(T));
+        Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
+        if (ClassTemplate->isMemberSpecialization())
+          break;
+      }
     }
 
     Ctx = Ctx->getParent();

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jul  8 13:37:38 2010
@@ -820,7 +820,7 @@
   
   // Trigger creation of the type for the instantiation.
   SemaRef.Context.getInjectedClassNameType(RecordInst,
-                  Inst->getInjectedClassNameSpecialization(SemaRef.Context));
+                                    Inst->getInjectedClassNameSpecialization());
 
   // Finish handling of friends.
   if (isFriend) {
@@ -978,9 +978,10 @@
   void *InsertPos = 0;
   if (FunctionTemplate && !TemplateParams) {
     llvm::FoldingSetNodeID ID;
-    FunctionTemplateSpecializationInfo::Profile(ID,
-                             TemplateArgs.getInnermost().getFlatArgumentList(),
-                                       TemplateArgs.getInnermost().flat_size(),
+    std::pair<const TemplateArgument *, unsigned> Innermost 
+      = TemplateArgs.getInnermost();
+    FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
+                                                Innermost.second,
                                                 SemaRef.Context);
 
     FunctionTemplateSpecializationInfo *Info
@@ -1089,8 +1090,12 @@
     }
   } else if (FunctionTemplate) {
     // Record this function template specialization.
+    std::pair<const TemplateArgument *, unsigned> Innermost 
+      = TemplateArgs.getInnermost();
     Function->setFunctionTemplateSpecialization(FunctionTemplate,
-                                                &TemplateArgs.getInnermost(),
+                  new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
+                                                             Innermost.first,
+                                                             Innermost.second),
                                                 InsertPos);
   } else if (isFriend && D->isThisDeclarationADefinition()) {
     // TODO: should we remember this connection regardless of whether
@@ -1227,9 +1232,10 @@
     // template. Check whether there is already a function template
     // specialization for this particular set of template arguments.
     llvm::FoldingSetNodeID ID;
-    FunctionTemplateSpecializationInfo::Profile(ID,
-                            TemplateArgs.getInnermost().getFlatArgumentList(),
-                                      TemplateArgs.getInnermost().flat_size(),
+    std::pair<const TemplateArgument *, unsigned> Innermost 
+      = TemplateArgs.getInnermost();
+    FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
+                                                Innermost.second,
                                                 SemaRef.Context);
 
     FunctionTemplateSpecializationInfo *Info
@@ -1374,8 +1380,12 @@
     Method->setDescribedFunctionTemplate(FunctionTemplate);
   } else if (FunctionTemplate) {
     // Record this function template specialization.
+    std::pair<const TemplateArgument *, unsigned> Innermost 
+      = TemplateArgs.getInnermost();
     Method->setFunctionTemplateSpecialization(FunctionTemplate,
-                                              &TemplateArgs.getInnermost(),
+                    new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
+                                                              Innermost.first,
+                                                              Innermost.second),
                                               InsertPos);
   } else if (!isFriend) {
     // Record that this is an instantiation of a member function.
@@ -2597,7 +2607,7 @@
     ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
     
     if (ClassTemplate) {
-      T = ClassTemplate->getInjectedClassNameSpecialization(Context);
+      T = ClassTemplate->getInjectedClassNameSpecialization();
     } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
                  = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
       ClassTemplate = PartialSpec->getSpecializedTemplate();

Modified: cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Thu Jul  8 13:37:38 2010
@@ -156,3 +156,36 @@
   };
 
 }
+
+namespace PR7587 {
+  template<typename> class X0;
+  template<typename> struct X1;
+  template<typename> class X2;
+
+  template<typename T> class X3
+  {
+    template<
+      template<typename> class TT,
+      typename U = typename X1<T>::type
+    > 
+    struct Inner {
+      typedef X2<TT<typename X1<T>::type> > Type;
+    };
+
+    const typename Inner<X0>::Type minCoeff() const;
+  };
+
+  template<typename T> class X3<T*>
+  {
+    template<
+      template<typename> class TT,
+      typename U = typename X1<T>::type
+    > 
+    struct Inner {
+      typedef X2<TT<typename X1<T>::type> > Type;
+    };
+
+    const typename Inner<X0>::Type minCoeff() const;
+  };
+
+}





More information about the cfe-commits mailing list