diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/DeclTemplate.h | 2 | ||||
| -rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.h | 31 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 30 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiate-member-template.cpp | 33 | 
9 files changed, 95 insertions, 28 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 1fa596cccb2..135dd3ae78d 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1476,7 +1476,7 @@ public:    ///   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. diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 9a7bc9105bd..f00eb0478a7 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -201,7 +201,7 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {  }  QualType -ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) { +ClassTemplateDecl::getInjectedClassNameSpecialization() {    Common *CommonPtr = getCommonPtr();    if (!CommonPtr->InjectedClassNameType.isNull())      return CommonPtr->InjectedClassNameType; @@ -210,7 +210,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {    // 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()); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 42c346fbe83..f56573a8de2 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -96,7 +96,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,            // 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(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 93cec73d038..66369674f25 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3317,9 +3317,10 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,        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()) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index af1cb50006e..31823c72ead 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -884,7 +884,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,    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; diff --git a/clang/lib/Sema/SemaTemplate.h b/clang/lib/Sema/SemaTemplate.h index ca59e273551..b3f46519ab7 100644 --- a/clang/lib/Sema/SemaTemplate.h +++ b/clang/lib/Sema/SemaTemplate.h @@ -36,10 +36,14 @@ namespace clang {    /// 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 @@ namespace clang {      /// \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 @@ namespace clang {      /// \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 @@ namespace clang {      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 @@ namespace clang {      /// \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();       }    }; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 897acf39cee..6db0916e445 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -63,7 +63,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,      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 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,          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(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 853f7c30944..5778a827fcf 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -820,7 +820,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {    // 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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,    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 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,      }    } 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 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,      // 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 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,      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 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,      ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();      if (ClassTemplate) { -      T = ClassTemplate->getInjectedClassNameSpecialization(Context); +      T = ClassTemplate->getInjectedClassNameSpecialization();      } else if (ClassTemplatePartialSpecializationDecl *PartialSpec                   = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {        ClassTemplate = PartialSpec->getSpecializedTemplate(); diff --git a/clang/test/SemaTemplate/instantiate-member-template.cpp b/clang/test/SemaTemplate/instantiate-member-template.cpp index ae8425e716e..24a3f317e63 100644 --- a/clang/test/SemaTemplate/instantiate-member-template.cpp +++ b/clang/test/SemaTemplate/instantiate-member-template.cpp @@ -156,3 +156,36 @@ namespace PR6239 {    };  } + +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; +  }; + +}  | 

