[cfe-commits] r80389 - in /cfe/trunk: lib/Sema/Sema.h 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
Fri Aug 28 13:31:08 PDT 2009


Author: dgregor
Date: Fri Aug 28 15:31:08 2009
New Revision: 80389

URL: http://llvm.org/viewvc/llvm-project?rev=80389&view=rev
Log:
Implement template instantiation for member class templates.

When performing template instantiation of the definitions of member
templates (or members thereof),  we build a data structure containing
the template arguments from each "level" of template
instantiation. During template instantiation, we substitute all levels
of template arguments simultaneously. 


Modified:
    cfe/trunk/lib/Sema/Sema.h
    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/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80389&r1=80388&r2=80389&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Aug 28 15:31:08 2009
@@ -2903,29 +2903,28 @@
 
   void PerformPendingImplicitInstantiations();
   
-  QualType SubstType(QualType T, const TemplateArgumentList &TemplateArgs,
+  QualType SubstType(QualType T, 
+                     const MultiLevelTemplateArgumentList &TemplateArgs,
                      SourceLocation Loc, DeclarationName Entity);
   
-  OwningExprResult SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs);
+  OwningExprResult SubstExpr(Expr *E, 
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
 
-  OwningStmtResult SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs);
+  OwningStmtResult SubstStmt(Stmt *S, 
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
 
   Decl *SubstDecl(Decl *D, DeclContext *Owner,
-                  const TemplateArgumentList &TemplateArgs);
+                  const MultiLevelTemplateArgumentList &TemplateArgs);
 
   bool 
   SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
                       CXXRecordDecl *Pattern,
-                      const TemplateArgumentList &TemplateArgs);
-
-  bool
-  InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
-                             CXXRecordDecl *Pattern);
+                      const MultiLevelTemplateArgumentList &TemplateArgs);
 
   bool
   InstantiateClass(SourceLocation PointOfInstantiation,
                    CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
-                   const TemplateArgumentList &TemplateArgs,
+                   const MultiLevelTemplateArgumentList &TemplateArgs,
                    bool ExplicitInstantiation,
                    bool Complain = true);
 
@@ -2936,7 +2935,7 @@
 
   void InstantiateClassMembers(SourceLocation PointOfInstantiation,
                                CXXRecordDecl *Instantiation,
-                               const TemplateArgumentList &TemplateArgs);
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
 
   void InstantiateClassTemplateSpecializationMembers(
                                           SourceLocation PointOfInstantiation,
@@ -2945,13 +2944,13 @@
   NestedNameSpecifier *
   SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
                            SourceRange Range,
-                           const TemplateArgumentList &TemplateArgs);
+                           const MultiLevelTemplateArgumentList &TemplateArgs);
 
   TemplateName
   SubstTemplateName(TemplateName Name, SourceLocation Loc,
-                    const TemplateArgumentList &TemplateArgs);
+                    const MultiLevelTemplateArgumentList &TemplateArgs);
   TemplateArgument Subst(TemplateArgument Arg,
-                         const TemplateArgumentList &TemplateArgs);
+                         const MultiLevelTemplateArgumentList &TemplateArgs);
 
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                      FunctionDecl *Function,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Aug 28 15:31:08 2009
@@ -2473,14 +2473,14 @@
       Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
 
       // Instantiate the expression.
-      const TemplateArgumentList &ArgList = getTemplateInstantiationArgs(FD);
+      MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD);
       
       // FIXME: We should really make a new InstantiatingTemplate ctor
       // that has a better message - right now we're just piggy-backing 
       // off the "default template argument" error message.
       InstantiatingTemplate Inst(*this, CallLoc, FD->getPrimaryTemplate(),
-                                 ArgList.getFlatArgumentList(),
-                                 ArgList.flat_size());
+                                 ArgList.getInnermost().getFlatArgumentList(),
+                                 ArgList.getInnermost().flat_size());
 
       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=80389&r1=80388&r2=80389&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Aug 28 15:31:08 2009
@@ -1243,7 +1243,8 @@
 
           TemplateArgumentList TemplateArgs(Context, Converted,
                                             /*TakeArgs=*/false);
-          ArgType = SubstType(ArgType, TemplateArgs,
+          ArgType = SubstType(ArgType, 
+                              MultiLevelTemplateArgumentList(TemplateArgs),
                               TTP->getDefaultArgumentLoc(),
                               TTP->getDeclName());
         }
@@ -1265,8 +1266,9 @@
         TemplateArgumentList TemplateArgs(Context, Converted,
                                           /*TakeArgs=*/false);
 
-        Sema::OwningExprResult E = SubstExpr(NTTP->getDefaultArgument(), 
-                                             TemplateArgs);
+        Sema::OwningExprResult E 
+          = SubstExpr(NTTP->getDefaultArgument(), 
+                      MultiLevelTemplateArgumentList(TemplateArgs));
         if (E.isInvalid())
           return true;
         

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.h (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.h Fri Aug 28 15:31:08 2009
@@ -46,8 +46,8 @@
     MultiLevelTemplateArgumentList() { }
     
     /// \brief Construct a single-level template argument list.
-    MultiLevelTemplateArgumentList(const TemplateArgumentList *TemplateArgs) {
-      TemplateArgumentLists.push_back(TemplateArgs);
+    MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+      TemplateArgumentLists.push_back(&TemplateArgs);
     }
     
     /// \brief Determine the number of levels in this template argument
@@ -57,8 +57,21 @@
     /// \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]->size());
-      return TemplateArgumentLists[getNumLevels() - Depth]->get(Index);
+      assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
+      return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
+    }
+    
+    /// \brief Determine whether there is a non-NULL template argument at the
+    /// given depth and index.
+    ///
+    /// There must exist a template argument list at the given depth.
+    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
+      assert(Depth < TemplateArgumentLists.size());
+      
+      if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
+        return false;
+      
+      return !(*this)(Depth, Index).isNull();
     }
     
     /// \brief Add a new outermost level to the multi-level template argument 
@@ -67,6 +80,11 @@
       TemplateArgumentLists.push_back(TemplateArgs);
     }
     
+    /// \brief Retrieve the innermost template argument list.
+    const TemplateArgumentList &getInnermost() const {
+      return *TemplateArgumentLists.front();
+    }
+    
     // Implicit conversion to a single template argument list, to facilitate a
     // gradual transition to MultiLevelTemplateArgumentLists.
     operator const TemplateArgumentList &() const {

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Aug 28 15:31:08 2009
@@ -26,8 +26,8 @@
 // Template Instantiation Support
 //===----------------------------------------------------------------------===/
 
-/// \brief Retrieve the template argument list that should be used to
-/// instantiate the given declaration.
+/// \brief Retrieve the template argument list(s) that should be used to
+/// instantiate the definition of the given declaration.
 MultiLevelTemplateArgumentList
 Sema::getTemplateInstantiationArgs(NamedDecl *D) {
   // Accumulate the set of template argument lists in this structure.
@@ -298,7 +298,7 @@
   class VISIBILITY_HIDDEN TemplateInstantiator 
     : public TreeTransform<TemplateInstantiator> 
   {
-    const TemplateArgumentList &TemplateArgs;
+    const MultiLevelTemplateArgumentList &TemplateArgs;
     SourceLocation Loc;
     DeclarationName Entity;
 
@@ -306,7 +306,7 @@
     typedef TreeTransform<TemplateInstantiator> inherited;
     
     TemplateInstantiator(Sema &SemaRef, 
-                         const TemplateArgumentList &TemplateArgs,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
                          SourceLocation Loc,
                          DeclarationName Entity) 
       : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), 
@@ -353,15 +353,24 @@
 Decl *TemplateInstantiator::TransformDecl(Decl *D) {
   if (TemplateTemplateParmDecl *TTP 
         = dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
-    // FIXME: Depth reduction
-    assert(TTP->getDepth() == 0 && 
-           "Cannot reduce depth of a template template parameter");
-    assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
-           "Wrong kind of template template argument");
-    TemplateDecl *Template 
-      = dyn_cast<TemplateDecl>(TemplateArgs[TTP->getPosition()].getAsDecl());
-    assert(Template && "Expected a template");
-    return Template;
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+             "Wrong kind of template template argument");
+      return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(), 
+                                             TTP->getPosition()).getAsDecl());
+    }
+    
+    // If the corresponding template argument is NULL or non-existent, it's 
+    // because we are performing instantiation from explicitly-specified 
+    // template arguments in a function template, but there were some
+    // arguments left unspecified.
+    if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(), 
+                                          TTP->getPosition()))
+      return D;
+    
+    // FIXME: Implement depth reduction of template template parameters
+    assert(false && 
+      "Reducing depth of template template parameters is not yet implemented");
   }
   
   return SemaRef.FindInstantiatedDecl(cast_or_null<NamedDecl>(D));
@@ -395,59 +404,65 @@
   // FIXME: Clean this up a bit
   NamedDecl *D = E->getDecl();
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
-    assert(NTTP->getDepth() == 0 && "No nested templates yet");
+    if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) {
+      assert(false && "Cannot reduce non-type template parameter depth yet");
+      return getSema().ExprError();
+    }
     
     // If the corresponding template argument is NULL or non-existent, it's 
     // because we are performing instantiation from explicitly-specified 
     // template arguments in a function template, but there were some
     // arguments left unspecified.
-    if (NTTP->getPosition() >= TemplateArgs.size() ||
-        TemplateArgs[NTTP->getPosition()].isNull())
-      return SemaRef.Owned(E); // FIXME: Clone the expression!
+    if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), 
+                                          NTTP->getPosition()))
+      return SemaRef.Owned(E->Retain());
     
-    const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
+    const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), 
+                                               NTTP->getPosition());
     
     // The template argument itself might be an expression, in which
     // case we just return that expression.
     if (Arg.getKind() == TemplateArgument::Expression)
-      // FIXME: Clone the expression!
-      return SemaRef.Owned(Arg.getAsExpr());
+      return SemaRef.Owned(Arg.getAsExpr()->Retain());
     
     if (Arg.getKind() == TemplateArgument::Declaration) {
       ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
       
-      // FIXME: Can VD ever have a dependent type?
+      VD = cast_or_null<ValueDecl>(getSema().FindInstantiatedDecl(VD));
+      if (!VD)
+        return SemaRef.ExprError();
+      
       return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), 
-                                      false, false);
+                                      /*FIXME:*/false, /*FIXME:*/false);
     }
     
     assert(Arg.getKind() == TemplateArgument::Integral);
     QualType T = Arg.getIntegralType();
     if (T->isCharType() || T->isWideCharType())
       return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
-                                                                  Arg.getAsIntegral()->getZExtValue(),
-                                                                  T->isWideCharType(),
-                                                                  T, 
-                                                                  E->getSourceRange().getBegin()));
+                                            Arg.getAsIntegral()->getZExtValue(),
+                                            T->isWideCharType(),
+                                            T, 
+                                            E->getSourceRange().getBegin()));
     if (T->isBooleanType())
       return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
-                                                                    Arg.getAsIntegral()->getBoolValue(),
-                                                                    T, 
-                                                                    E->getSourceRange().getBegin()));
+                                          Arg.getAsIntegral()->getBoolValue(),
+                                          T, 
+                                          E->getSourceRange().getBegin()));
     
     assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
     return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
-                                                              *Arg.getAsIntegral(),
-                                                              T, 
-                                                              E->getSourceRange().getBegin()));
+                                              *Arg.getAsIntegral(),
+                                              T, 
+                                              E->getSourceRange().getBegin()));
   }
   
   if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
     // FIXME: instantiate each decl in the overload set
     return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
-                                                           SemaRef.Context.OverloadTy,
-                                                           E->getLocation(),
-                                                           false, false));
+                                                     SemaRef.Context.OverloadTy,
+                                                     E->getLocation(),
+                                                     false, false));
   }
   
   NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D);
@@ -464,31 +479,30 @@
 QualType 
 TemplateInstantiator::TransformTemplateTypeParmType(
                                               const TemplateTypeParmType *T) {
-  if (T->getDepth() == 0) {
+  if (T->getDepth() < TemplateArgs.getNumLevels()) {
     // Replace the template type parameter with its corresponding
     // template argument.
     
-    // FIXME: When dealing with member templates, we might end up with multiple
-    /// levels of template arguments that we're substituting into concurrently.
-    
     // If the corresponding template argument is NULL or doesn't exist, it's 
     // because we are performing instantiation from explicitly-specified 
     // template arguments in a function template class, but there were some 
     // arguments left unspecified.
-    if (T->getIndex() >= TemplateArgs.size() ||
-        TemplateArgs[T->getIndex()].isNull())
-      return QualType(T, 0); // Would be nice to keep the original type here
-        
-    assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
+    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
+      return QualType(T, 0);
+    
+    assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind() 
+             == TemplateArgument::Type &&
            "Template argument kind mismatch");
-    return TemplateArgs[T->getIndex()].getAsType();
+
+    return TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
   } 
 
   // The template type parameter comes from an inner template (e.g.,
   // the template parameter list of a member template inside the
   // template we are instantiating). Create a new template type
   // parameter with the template "level" reduced by one.
-  return getSema().Context.getTemplateTypeParmType(T->getDepth() - 1,
+  return getSema().Context.getTemplateTypeParmType(
+                                  T->getDepth() - TemplateArgs.getNumLevels(),
                                                    T->getIndex(),
                                                    T->isParameterPack(),
                                                    T->getName());
@@ -522,7 +536,7 @@
 /// \returns If the instantiation succeeds, the instantiated
 /// type. Otherwise, produces diagnostics and returns a NULL type.
 QualType Sema::SubstType(QualType T, 
-                         const TemplateArgumentList &TemplateArgs,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
                          SourceLocation Loc, DeclarationName Entity) {
   assert(!ActiveTemplateInstantiations.empty() &&
          "Cannot perform an instantiation without some context on the "
@@ -545,7 +559,7 @@
 bool 
 Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
                           CXXRecordDecl *Pattern,
-                          const TemplateArgumentList &TemplateArgs) {
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
   bool Invalid = false;
   llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
   for (ClassTemplateSpecializationDecl::base_class_iterator 
@@ -586,38 +600,6 @@
   return Invalid;
 }
 
-/// \brief Force a template's pattern class to be instantiated.
-///
-/// \returns true if an error occurred
-bool Sema::InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
-                                      CXXRecordDecl *Pattern) {
-  if (Pattern->getDefinition(Context)) return false;
-
-  ClassTemplateDecl *PatternTemp = Pattern->getDescribedClassTemplate();
-  if (!PatternTemp) return false;
-
-  // Check whether this template is a lazy instantiation of a
-  // dependent member template, e.g. Inner<U> in
-  // Outer<int>::Inner<U>.
-  ClassTemplateDecl *PatternPatternTemp
-    = PatternTemp->getInstantiatedFromMemberTemplate();
-  if (!PatternPatternTemp) return false;
-  
-  ClassTemplateSpecializationDecl *Spec = 0;
-  for (DeclContext *Parent = Pattern->getDeclContext();
-       Parent && !Spec; Parent = Parent->getParent())
-    Spec = dyn_cast<ClassTemplateSpecializationDecl>(Parent);
-  assert(Spec && "Not a member of a class template specialization?");
-
-  // TODO: the error message from a nested failure here is probably
-  // not ideal.
-  return InstantiateClass(PointOfInstantiation,
-                          Pattern,
-                          PatternPatternTemp->getTemplatedDecl(),
-                          Spec->getTemplateArgs(),
-                          /* ExplicitInstantiation = */ false);
-}
-
 /// \brief Instantiate the definition of a class from a given pattern.
 ///
 /// \param PointOfInstantiation The point of instantiation within the
@@ -644,15 +626,11 @@
 bool
 Sema::InstantiateClass(SourceLocation PointOfInstantiation,
                        CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
-                       const TemplateArgumentList &TemplateArgs,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
                        bool ExplicitInstantiation,
                        bool Complain) {
   bool Invalid = false;
 
-  // Lazily instantiate member templates here.
-  if (InstantiateTemplatePattern(PointOfInstantiation, Pattern))
-    return true;
-  
   CXXRecordDecl *PatternDef 
     = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
   if (!PatternDef) {
@@ -745,9 +723,7 @@
     return true;
 
   ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
-  CXXRecordDecl *Pattern = Template->getTemplatedDecl();
-  const TemplateArgumentList *TemplateArgs 
-    = &ClassTemplateSpec->getTemplateArgs();
+  CXXRecordDecl *Pattern = 0;
 
   // C++ [temp.class.spec.match]p1:
   //   When a class template is used in a context that requires an
@@ -782,7 +758,6 @@
     //   -- If exactly one matching specialization is found, the
     //      instantiation is generated from that specialization.
     Pattern = Matched[0].first;
-    TemplateArgs = Matched[0].second;
     ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
   } else if (Matched.size() > 1) {
     //   -- If more than one matching specialization is found, the
@@ -796,21 +771,31 @@
     // specializations.
     Diag(ClassTemplateSpec->getLocation(), 
          diag::unsup_template_partial_spec_ordering);
+
+    // FIXME: Temporary hack to fall back to the primary template
+    ClassTemplateDecl *OrigTemplate = Template;
+    while (OrigTemplate->getInstantiatedFromMemberTemplate())
+      OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+    
+    Pattern = OrigTemplate->getTemplatedDecl();
   } else {
     //   -- If no matches are found, the instantiation is generated
     //      from the primary template.
-
-    // Since we initialized the pattern and template arguments from
-    // the primary template, there is nothing more we need to do here.
+    ClassTemplateDecl *OrigTemplate = Template;
+    while (OrigTemplate->getInstantiatedFromMemberTemplate())
+      OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+    
+    Pattern = OrigTemplate->getTemplatedDecl();
   }
 
-  // Note that this is an instantiation.  
+  // Note that this is an instantiation.
   ClassTemplateSpec->setSpecializationKind(
                         ExplicitInstantiation? TSK_ExplicitInstantiation 
                                              : TSK_ImplicitInstantiation);
 
   bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
-                                 ClassTemplateSpec, Pattern, *TemplateArgs,
+                                 ClassTemplateSpec, Pattern, 
+                              getTemplateInstantiationArgs(ClassTemplateSpec),
                                  ExplicitInstantiation,
                                  Complain);
   
@@ -829,7 +814,7 @@
 void
 Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
                         CXXRecordDecl *Instantiation,
-                        const TemplateArgumentList &TemplateArgs) {
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {
   for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
                                DEnd = Instantiation->decls_end();
        D != DEnd; ++D) {
@@ -866,11 +851,11 @@
   //   containing the explicit instantiation, except as described
   //   below.
   InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
-                          ClassTemplateSpec->getTemplateArgs());
+                          getTemplateInstantiationArgs(ClassTemplateSpec));
 }
 
 Sema::OwningStmtResult 
-Sema::SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
+Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
   if (!S)
     return Owned(S);
 
@@ -881,7 +866,7 @@
 }
 
 Sema::OwningExprResult 
-Sema::SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
+Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
   if (!E)
     return Owned(E);
   
@@ -894,8 +879,8 @@
 /// \brief Do template substitution on a nested-name-specifier.
 NestedNameSpecifier *
 Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
-                                     SourceRange Range,
-                                     const TemplateArgumentList &TemplateArgs) {
+                               SourceRange Range,
+                         const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
                                     DeclarationName());
   return Instantiator.TransformNestedNameSpecifier(NNS, Range);
@@ -903,14 +888,14 @@
 
 TemplateName
 Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
-                        const TemplateArgumentList &TemplateArgs) {
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
                                     DeclarationName());
   return Instantiator.TransformTemplateName(Name);
 }
 
 TemplateArgument Sema::Subst(TemplateArgument Arg, 
-                             const TemplateArgumentList &TemplateArgs) {
+                         const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                     DeclarationName());
   return Instantiator.TransformTemplateArgument(Arg);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Aug 28 15:31:08 2009
@@ -25,13 +25,13 @@
     : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
     Sema &SemaRef;
     DeclContext *Owner;
-    const TemplateArgumentList &TemplateArgs;
+    const MultiLevelTemplateArgumentList &TemplateArgs;
     
   public:
     typedef Sema::OwningExprResult OwningExprResult;
 
     TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
-                             const TemplateArgumentList &TemplateArgs)
+                             const MultiLevelTemplateArgumentList &TemplateArgs)
       : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
     
     // FIXME: Once we get closer to completion, replace these manually-written
@@ -457,8 +457,8 @@
   if (FunctionTemplate) {
     llvm::FoldingSetNodeID ID;
     FunctionTemplateSpecializationInfo::Profile(ID, 
-                                          TemplateArgs.getFlatArgumentList(),
-                                                TemplateArgs.flat_size(),
+                             TemplateArgs.getInnermost().getFlatArgumentList(),
+                                       TemplateArgs.getInnermost().flat_size(),
                                                 SemaRef.Context);
     
     FunctionTemplateSpecializationInfo *Info 
@@ -513,7 +513,7 @@
     // Record this function template specialization.
     Function->setFunctionTemplateSpecialization(SemaRef.Context,
                                                 FunctionTemplate,
-                                                &TemplateArgs,
+                                                &TemplateArgs.getInnermost(),
                                                 InsertPos);
   }
 
@@ -531,8 +531,8 @@
     // specialization for this particular set of template arguments.
     llvm::FoldingSetNodeID ID;
     FunctionTemplateSpecializationInfo::Profile(ID, 
-                                          TemplateArgs.getFlatArgumentList(),
-                                                TemplateArgs.flat_size(),
+                            TemplateArgs.getInnermost().getFlatArgumentList(),
+                                      TemplateArgs.getInnermost().flat_size(),
                                                 SemaRef.Context);
     
     FunctionTemplateSpecializationInfo *Info 
@@ -646,7 +646,7 @@
     // Record this function template specialization.
     Method->setFunctionTemplateSpecialization(SemaRef.Context,
                                               FunctionTemplate,
-                                              &TemplateArgs,
+                                              &TemplateArgs.getInnermost(),
                                               InsertPos);
   
   bool Redeclaration = false;
@@ -760,7 +760,7 @@
 }
 
 Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
-                      const TemplateArgumentList &TemplateArgs) {
+                      const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
   return Instantiator.Visit(D);
 }

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=80389&r1=80388&r2=80389&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Fri Aug 28 15:31:08 2009
@@ -21,3 +21,25 @@
   double *&dpr2 = xv.f1(ip, dp);
 }
 
+template<typename T>
+struct X1 {
+  template<typename U>
+  struct Inner0 {
+    U x; 
+    T y; // expected-error{{void}}
+  };
+
+  template<typename U>
+  struct Inner1 {
+    U x; // expected-error{{void}}
+    T y; 
+  };
+};
+
+void test_X1() {
+  X1<void>::Inner0<int> *xvip; // okay
+  X1<void>::Inner0<int> xvi; // expected-note{{instantiation}}
+  
+  X1<int>::Inner1<void> *xivp; // okay
+  X1<int>::Inner1<void> xiv; // expected-note{{instantiation}}
+}





More information about the cfe-commits mailing list