diff options
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 3 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-declref.cpp | 3 |
5 files changed, 35 insertions, 30 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5b3ea40b06..3825b7cc06 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2250,8 +2250,7 @@ public: FunctionDecl *Function); void InstantiateVariableDefinition(VarDecl *Var); - NamedDecl * - InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs); + NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D); // Simple function for cloning expressions. template<typename T> diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1cc999201b..1546e39ee2 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -407,8 +407,8 @@ QualType TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T, unsigned Quals) const { TypedefDecl *Typedef - = cast_or_null<TypedefDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), - TemplateArgs)); + = cast_or_null<TypedefDecl>( + SemaRef.InstantiateCurrentDeclRef(T->getDecl())); if (!Typedef) return QualType(); @@ -440,8 +440,7 @@ QualType TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T, unsigned Quals) const { RecordDecl *Record - = cast_or_null<RecordDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), - TemplateArgs)); + = cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl())); if (!Record) return QualType(); @@ -452,8 +451,7 @@ QualType TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T, unsigned Quals) const { EnumDecl *Enum - = cast_or_null<EnumDecl>(SemaRef.InstantiateDeclRef(T->getDecl(), - TemplateArgs)); + = cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl())); if (!Enum) return QualType(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 41c1944b54..33eedcec38 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -671,8 +671,8 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, return 0; } -/// \brief Find the instantiation of the given declaration with the -/// given template arguments. +/// \brief Find the instantiation of the given declaration within the +/// current instantiation. /// /// This routine is intended to be used when \p D is a declaration /// referenced from within a template, that needs to mapped into the @@ -695,10 +695,9 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, /// In the instantiation of X<int>::getKind(), we need to map the /// EnumConstantDecl for KnownValue (which refers to /// X<T>::<Kind>::KnownValue) to its instantiation -/// (X<int>::<Kind>::KnownValue). InstantiateDeclRef() performs this -/// mapping, given the template arguments 'int'. -NamedDecl * -Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) { +/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs +/// this mapping from within the instantiation of X<int>. +NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) { DeclContext *ParentDC = D->getDeclContext(); if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) { // D is a local of some kind. Look into the map of local @@ -707,7 +706,7 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) } if (NamedDecl *ParentDecl = dyn_cast<NamedDecl>(ParentDC)) { - ParentDecl = InstantiateDeclRef(ParentDecl, TemplateArgs); + ParentDecl = InstantiateCurrentDeclRef(ParentDecl); if (!ParentDecl) return 0; @@ -740,20 +739,27 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) D = Result; } - // D itself might be a class template that we need to instantiate - // with the given template arguments. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) - if (ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate()) { - QualType InjectedClassName - = ClassTemplate->getInjectedClassNameType(Context); - QualType InstantiatedType = InstantiateType(InjectedClassName, - TemplateArgs, - Record->getLocation(), - Record->getDeclName()); - if (InstantiatedType.isNull()) - return 0; - if (const RecordType *RT = InstantiatedType->getAsRecordType()) - D = RT->getDecl(); + if (ClassTemplateDecl *ClassTemplate + = Record->getDescribedClassTemplate()) { + // When the declaration D was parsed, it referred to the current + // instantiation. Therefore, look through the current context, + // which contains actual instantiations, to find the + // instantiation of the "current instantiation" that D refers + // to. Alternatively, we could just instantiate the + // injected-class-name with the current template arguments, but + // such an instantiation is far more expensive. + for (DeclContext *DC = CurContext; !DC->isFileContext(); + DC = DC->getParent()) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(DC)) + if (Context.getCanonicalDecl(Spec->getSpecializedTemplate()) + == Context.getCanonicalDecl(ClassTemplate)) + return Spec; + } + + assert(false && + "Unable to find declaration for the current instantiation"); } return D; diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 726ac2b425..31bb91def2 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -108,7 +108,6 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr( Sema::OwningExprResult TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { - // FIXME: Recast this in terms of Sema::InstantiateDeclRef. NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { assert(NTTP->getDepth() == 0 && "No nested templates yet"); @@ -141,7 +140,7 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { } ValueDecl *NewD - = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateDeclRef(D, TemplateArgs)); + = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D)); if (!NewD) return SemaRef.ExprError(); diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp index 3b6db38617..0e1e562056 100644 --- a/test/SemaTemplate/instantiate-declref.cpp +++ b/test/SemaTemplate/instantiate-declref.cpp @@ -24,6 +24,9 @@ namespace N { K1 k1 = K1Val; Kind1 = K1Val; Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val; + + InnerTemplate t; + InnerTemplate<type> t2; } }; }; |