diff options
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 82 | ||||
-rw-r--r-- | test/SemaTemplate/default-expr-arguments.cpp | 10 |
4 files changed, 81 insertions, 24 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ff99475212..c078d43152 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3103,8 +3103,10 @@ public: const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); - NamedDecl *FindInstantiatedDecl(NamedDecl *D); - DeclContext *FindInstantiatedContext(DeclContext *DC); + NamedDecl *FindInstantiatedDecl(NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclContext *FindInstantiatedContext(DeclContext *DC, + const MultiLevelTemplateArgumentList &TemplateArgs); // Objective-C declarations. virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc, diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 87216a072d..86b49d4f32 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -429,7 +429,7 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { "Reducing depth of template template parameters is not yet implemented"); } - return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D)); + return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs); } Decl *TemplateInstantiator::TransformDefinition(Decl *D) { @@ -533,7 +533,8 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { if (Arg.getKind() == TemplateArgument::Declaration) { ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); - VD = cast_or_null<ValueDecl>(getSema().FindInstantiatedDecl(VD)); + VD = cast_or_null<ValueDecl>( + getSema().FindInstantiatedDecl(VD, TemplateArgs)); if (!VD) return SemaRef.ExprError(); @@ -562,7 +563,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { E->getSourceRange().getBegin())); } - NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D); + NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs); if (!InstD) return SemaRef.ExprError(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index af00cb9a4a..a43413e275 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -491,7 +491,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { return 0; // Build the instantiated method declaration. - DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext()); + DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), + TemplateArgs); FunctionDecl *Function = FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getDeclName(), T, D->getDeclaratorInfo(), @@ -1176,9 +1177,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, // Is this an anonymous union? if (FieldDecl *UnionInit = Init->getAnonUnionMember()) - Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit)); + Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit, TemplateArgs)); else - Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember())); + Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember(), + TemplateArgs)); NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), NewArgs.size(), @@ -1333,9 +1335,10 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, /// within the current instantiation. /// /// \returns NULL if there was an error -DeclContext *Sema::FindInstantiatedContext(DeclContext* DC) { +DeclContext *Sema::FindInstantiatedContext(DeclContext* DC, + const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { - Decl* ID = FindInstantiatedDecl(D); + Decl* ID = FindInstantiatedDecl(D, TemplateArgs); return cast_or_null<DeclContext>(ID); } else return DC; } @@ -1366,7 +1369,8 @@ DeclContext *Sema::FindInstantiatedContext(DeclContext* DC) { /// X<T>::<Kind>::KnownValue) to its instantiation /// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs /// this mapping from within the instantiation of X<int>. -NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D) { +NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs) { if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { // Transform all of the elements of the overloaded function set. OverloadedFunctionDecl *Result @@ -1376,7 +1380,8 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D) { FEnd = Ovl->function_end(); F != FEnd; ++F) { Result->addOverload( - AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F))); + AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F, + TemplateArgs))); } return Result; @@ -1389,29 +1394,68 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D) { return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D)); } - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) - 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. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + if (!Record->isDependentContext()) + return D; + + // If the RecordDecl is actually the injected-class-name or a "templated" + // declaration for a class template or class template partial + // specialization, substitute into the injected-class-name of the + // class template or partial specialization to find the new DeclContext. + QualType T; + ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); + + if (ClassTemplate) { + T = ClassTemplate->getInjectedClassNameType(Context); + } else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { + T = Context.getTypeDeclType(Record); + ClassTemplate = PartialSpec->getSpecializedTemplate(); + } + + if (!T.isNull()) { + // Substitute into the injected-class-name to get the type corresponding + // to the instantiation we want. This substitution should never fail, + // since we know we can instantiate the injected-class-name or we wouldn't + // have gotten to the injected-class-name! + // FIXME: Can we use the CurrentInstantiationScope to avoid this extra + // instantiation in the common case? + T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName()); + assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); + + if (!T->isDependentType()) { + assert(T->isRecordType() && "Instantiation must produce a record type"); + return T->getAs<RecordType>()->getDecl(); + } + + // We are performing "partial" template instantiation to create the + // member declarations for the members of a class template + // specialization. Therefore, D is actually referring to something in + // the current instantiation. Look through the current context, + // which contains actual instantiations, to find the instantiation of + // the "current instantiation" that D refers to. for (DeclContext *DC = CurContext; !DC->isFileContext(); DC = DC->getParent()) { if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) - if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate())) + if (isInstantiationOf(ClassTemplate, + Spec->getSpecializedTemplate())) return Spec; } assert(false && "Unable to find declaration for the current instantiation"); + return Record; } + + // Fall through to deal with other dependent record types (e.g., + // anonymous unions in class templates). + } - ParentDC = FindInstantiatedContext(ParentDC); + if (!ParentDC->isDependentContext()) + return D; + + ParentDC = FindInstantiatedContext(ParentDC, TemplateArgs); if (!ParentDC) return 0; diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp index 01d0e60887..74d87e9db9 100644 --- a/test/SemaTemplate/default-expr-arguments.cpp +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -68,3 +68,13 @@ void test_x0_not_default_constructible(X0<NotDefaultConstructible> xn) { xn.f(42); xn.f(); // expected-note{{in instantiation of default function argument}} } + +template<typename T> +struct X1 { + typedef T value_type; + X1(const value_type& value = value_type()); +}; + +void test_X1() { + X1<int> x1; +} |