From: Douglas Gregor Date: Mon, 1 Mar 2010 15:56:25 +0000 (+0000) Subject: When looking for the instantiated declaration that corresponds to a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c1e98f1cb37b40e619a0c8aee8b337f037b432b;p=clang When looking for the instantiated declaration that corresponds to a given declaration in a template, make sure that the context we're searching through is complete. Fixes PR6376. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97444 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9e5e9f6f8b..abc89b41f4 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -455,6 +455,8 @@ def err_qualified_member_nonclass : Error< "qualified member access refers to a member in %0">; def err_incomplete_member_access : Error< "member access into incomplete type %0">; +def err_incomplete_type : Error< + "incomplete type %0 where a complete type is required">; // C++ class members def err_storageclass_invalid_for_member : Error< diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 42f9838785..0fe9b7fa21 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3539,9 +3539,9 @@ public: const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); - NamedDecl *FindInstantiatedDecl(NamedDecl *D, + NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs); - DeclContext *FindInstantiatedContext(DeclContext *DC, + DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, const MultiLevelTemplateArgumentList &TemplateArgs); // Objective-C declarations. diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index f12c559ec1..fbd1a9ff1a 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -540,7 +540,7 @@ namespace { /// \brief Transform the given declaration by instantiating a reference to /// this declaration. - Decl *TransformDecl(Decl *D); + Decl *TransformDecl(SourceLocation Loc, Decl *D); /// \brief Transform the definition of the given declaration by /// instantiating it. @@ -575,7 +575,7 @@ namespace { }; } -Decl *TemplateInstantiator::TransformDecl(Decl *D) { +Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (!D) return 0; @@ -600,7 +600,7 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { // template parameter. } - return SemaRef.FindInstantiatedDecl(cast(D), TemplateArgs); + return SemaRef.FindInstantiatedDecl(Loc, cast(D), TemplateArgs); } Decl *TemplateInstantiator::TransformDefinition(Decl *D) { @@ -623,7 +623,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, if (TTP->getDepth() < TemplateArgs.getNumLevels()) { QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType(); if (T.isNull()) - return cast_or_null(TransformDecl(D)); + return cast_or_null(TransformDecl(Loc, D)); if (const TagType *Tag = T->getAs()) return Tag->getDecl(); @@ -634,7 +634,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, } } - return cast_or_null(TransformDecl(D)); + return cast_or_null(TransformDecl(Loc, D)); } VarDecl * @@ -724,7 +724,8 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, // Find the instantiation of the template argument. This is // required for nested templates. VD = cast_or_null( - getSema().FindInstantiatedDecl(VD, TemplateArgs)); + getSema().FindInstantiatedDecl(E->getLocation(), + VD, TemplateArgs)); if (!VD) return SemaRef.ExprError(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f13bd69453..3d9899e112 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -162,7 +162,8 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { Typedef->setInvalidDecl(); if (TypedefDecl *Prev = D->getPreviousDeclaration()) { - NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(Prev, TemplateArgs); + NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, + TemplateArgs); Typedef->setPreviousDeclaration(cast(InstPrev)); } @@ -433,7 +434,8 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Hack to make this work almost well pending a rewrite. if (ND->getDeclContext()->isRecord()) { if (!ND->getDeclContext()->isDependentContext()) { - NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs); + NewND = SemaRef.FindInstantiatedDecl(D->getLocation(), ND, + TemplateArgs); } else { // FIXME: Hack to avoid crashing when incorrectly trying to instantiate // templated friend declarations. This doesn't produce a correct AST; @@ -699,7 +701,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { if (D->isInjectedClassName()) PrevDecl = cast(Owner); else if (D->getPreviousDeclaration()) { - NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getPreviousDeclaration(), + NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), + D->getPreviousDeclaration(), TemplateArgs); if (!Prev) return 0; PrevDecl = cast(Prev); @@ -772,7 +775,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (D->getDeclContext()->isFunctionOrMethod()) DC = Owner; else - DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), TemplateArgs); + DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), + TemplateArgs); FunctionDecl *Function = FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), @@ -1228,7 +1232,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { I != E; ++I) { UsingShadowDecl *Shadow = *I; NamedDecl *InstTarget = - cast(SemaRef.FindInstantiatedDecl(Shadow->getTargetDecl(), + cast(SemaRef.FindInstantiatedDecl(Shadow->getLocation(), + Shadow->getTargetDecl(), TemplateArgs)); if (CheckRedeclaration && @@ -1922,9 +1927,11 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, // Is this an anonymous union? if (FieldDecl *UnionInit = Init->getAnonUnionMember()) - Member = cast(FindInstantiatedDecl(UnionInit, TemplateArgs)); + Member = cast(FindInstantiatedDecl(Init->getMemberLocation(), + UnionInit, TemplateArgs)); else - Member = cast(FindInstantiatedDecl(Init->getMember(), + Member = cast(FindInstantiatedDecl(Init->getMemberLocation(), + Init->getMember(), TemplateArgs)); NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), @@ -2154,10 +2161,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(SourceLocation Loc, DeclContext* DC, const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast(DC)) { - Decl* ID = FindInstantiatedDecl(D, TemplateArgs); + Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs); return cast_or_null(ID); } else return DC; } @@ -2188,7 +2195,7 @@ DeclContext *Sema::FindInstantiatedContext(DeclContext* DC, /// X::::KnownValue) to its instantiation /// (X::::KnownValue). InstantiateCurrentDeclRef() performs /// this mapping from within the instantiation of X. -NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, +NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs) { DeclContext *ParentDC = D->getDeclContext(); if (isa(D) || isa(D) || @@ -2275,7 +2282,7 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, if (!ParentDC->isDependentContext()) return D; - ParentDC = FindInstantiatedContext(ParentDC, TemplateArgs); + ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); if (!ParentDC) return 0; @@ -2283,6 +2290,20 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, // We performed some kind of instantiation in the parent context, // so now we need to look into the instantiated parent context to // find the instantiation of the declaration D. + + // If our context is a class template specialization, we may need + // to instantiate it before performing lookup into that context. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(ParentDC)) { + if (!Spec->isDependentContext()) { + QualType T = Context.getTypeDeclType(Spec); + if (const TagType *Tag = T->getAs()) + if (!Tag->isBeingDefined() && + RequireCompleteType(Loc, T, diag::err_incomplete_type)) + return 0; + } + } + NamedDecl *Result = 0; if (D->getDeclName()) { DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 95ec5a4313..4177d5249a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -237,13 +237,15 @@ public: /// /// By default, acts as the identity function on declarations. Subclasses /// may override this function to provide alternate behavior. - Decl *TransformDecl(Decl *D) { return D; } + Decl *TransformDecl(SourceLocation Loc, Decl *D) { return D; } /// \brief Transform the definition of the given declaration. /// /// By default, invokes TransformDecl() to transform the declaration. /// Subclasses may override this function to provide alternate behavior. - Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); } + Decl *TransformDefinition(SourceLocation Loc, Decl *D) { + return getDerived().TransformDecl(D); + } /// \brief Transform the given declaration, which was the first part of a /// nested-name-specifier in a member access expression. @@ -255,7 +257,7 @@ public: /// By default, invokes TransformDecl() to transform the declaration. /// Subclasses may override this function to provide alternate behavior. NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) { - return cast_or_null(getDerived().TransformDecl(D)); + return cast_or_null(getDerived().TransformDecl(Loc, D)); } /// \brief Transform the given nested-name-specifier. @@ -1745,7 +1747,8 @@ TreeTransform::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, case NestedNameSpecifier::Namespace: { NamespaceDecl *NS = cast_or_null( - getDerived().TransformDecl(NNS->getAsNamespace())); + getDerived().TransformDecl(Range.getBegin(), + NNS->getAsNamespace())); if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() && NS == NNS->getAsNamespace()) @@ -1822,6 +1825,8 @@ template TemplateName TreeTransform::TransformTemplateName(TemplateName Name, QualType ObjectType) { + SourceLocation Loc = getDerived().getBaseLocation(); + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { NestedNameSpecifier *NNS = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(), @@ -1832,7 +1837,7 @@ TreeTransform::TransformTemplateName(TemplateName Name, if (TemplateDecl *Template = QTN->getTemplateDecl()) { TemplateDecl *TransTemplate - = cast_or_null(getDerived().TransformDecl(Template)); + = cast_or_null(getDerived().TransformDecl(Loc, Template)); if (!TransTemplate) return TemplateName(); @@ -1872,7 +1877,7 @@ TreeTransform::TransformTemplateName(TemplateName Name, if (TemplateDecl *Template = Name.getAsTemplateDecl()) { TemplateDecl *TransTemplate - = cast_or_null(getDerived().TransformDecl(Template)); + = cast_or_null(getDerived().TransformDecl(Loc, Template)); if (!TransTemplate) return TemplateName(); @@ -1949,7 +1954,7 @@ bool TreeTransform::TransformTemplateArgument( if (NamedDecl *ND = dyn_cast(Arg.getAsDecl())) Name = ND->getDeclName(); TemporaryBase Rebase(*this, Input.getLocation(), Name); - Decl *D = getDerived().TransformDecl(Arg.getAsDecl()); + Decl *D = getDerived().TransformDecl(Input.getLocation(), Arg.getAsDecl()); if (!D) return true; Expr *SourceExpr = Input.getSourceDeclExpression(); @@ -2618,7 +2623,7 @@ TreeTransform::TransformUnresolvedUsingType(TypeLocBuilder &TLB, UnresolvedUsingTypeLoc TL, QualType ObjectType) { UnresolvedUsingType *T = TL.getTypePtr(); - Decl *D = getDerived().TransformDecl(T->getDecl()); + Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()); if (!D) return QualType(); @@ -2643,7 +2648,8 @@ QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, QualType ObjectType) { TypedefType *T = TL.getTypePtr(); TypedefDecl *Typedef - = cast_or_null(getDerived().TransformDecl(T->getDecl())); + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Typedef) return QualType(); @@ -2748,7 +2754,8 @@ QualType TreeTransform::TransformRecordType(TypeLocBuilder &TLB, QualType ObjectType) { RecordType *T = TL.getTypePtr(); RecordDecl *Record - = cast_or_null(getDerived().TransformDecl(T->getDecl())); + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Record) return QualType(); @@ -2772,7 +2779,8 @@ QualType TreeTransform::TransformEnumType(TypeLocBuilder &TLB, QualType ObjectType) { EnumType *T = TL.getTypePtr(); EnumDecl *Enum - = cast_or_null(getDerived().TransformDecl(T->getDecl())); + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Enum) return QualType(); @@ -3588,7 +3596,8 @@ TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { } ValueDecl *ND - = cast_or_null(getDerived().TransformDecl(E->getDecl())); + = cast_or_null(getDerived().TransformDecl(E->getLocation(), + E->getDecl())); if (!ND) return SemaRef.ExprError(); @@ -3797,7 +3806,8 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { } ValueDecl *Member - = cast_or_null(getDerived().TransformDecl(E->getMemberDecl())); + = cast_or_null(getDerived().TransformDecl(E->getMemberLoc(), + E->getMemberDecl())); if (!Member) return SemaRef.ExprError(); @@ -4521,7 +4531,8 @@ template Sema::OwningExprResult TreeTransform::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { ParmVarDecl *Param - = cast_or_null(getDerived().TransformDecl(E->getParam())); + = cast_or_null(getDerived().TransformDecl(E->getLocStart(), + E->getParam())); if (!Param) return SemaRef.ExprError(); @@ -4592,7 +4603,8 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { CXXConstructorDecl *Constructor = 0; if (E->getConstructor()) { Constructor = cast_or_null( - getDerived().TransformDecl(E->getConstructor())); + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); if (!Constructor) return SemaRef.ExprError(); } @@ -4600,7 +4612,8 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { FunctionDecl *OperatorNew = 0; if (E->getOperatorNew()) { OperatorNew = cast_or_null( - getDerived().TransformDecl(E->getOperatorNew())); + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorNew())); if (!OperatorNew) return SemaRef.ExprError(); } @@ -4608,7 +4621,8 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { FunctionDecl *OperatorDelete = 0; if (E->getOperatorDelete()) { OperatorDelete = cast_or_null( - getDerived().TransformDecl(E->getOperatorDelete())); + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorDelete())); if (!OperatorDelete) return SemaRef.ExprError(); } @@ -4682,7 +4696,8 @@ TreeTransform::TransformCXXDeleteExpr(CXXDeleteExpr *E) { FunctionDecl *OperatorDelete = 0; if (E->getOperatorDelete()) { OperatorDelete = cast_or_null( - getDerived().TransformDecl(E->getOperatorDelete())); + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorDelete())); if (!OperatorDelete) return SemaRef.ExprError(); } @@ -4794,7 +4809,9 @@ TreeTransform::TransformUnresolvedLookupExpr( // Transform all the decls. for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), E = Old->decls_end(); I != E; ++I) { - NamedDecl *InstD = static_cast(getDerived().TransformDecl(*I)); + NamedDecl *InstD = static_cast( + getDerived().TransformDecl(Old->getNameLoc(), + *I)); if (!InstD) { // Silently ignore these if a UsingShadowDecl instantiated to nothing. // This can happen because of dependent hiding. @@ -4933,7 +4950,8 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { CXXConstructorDecl *Constructor = cast_or_null( - getDerived().TransformDecl(E->getConstructor())); + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); if (!Constructor) return SemaRef.ExprError(); @@ -5013,7 +5031,8 @@ TreeTransform::TransformCXXTemporaryObjectExpr( CXXConstructorDecl *Constructor = cast_or_null( - getDerived().TransformDecl(E->getConstructor())); + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); if (!Constructor) return SemaRef.ExprError(); @@ -5221,7 +5240,9 @@ TreeTransform::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) // Transform all the decls. for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(), E = Old->decls_end(); I != E; ++I) { - NamedDecl *InstD = static_cast(getDerived().TransformDecl(*I)); + NamedDecl *InstD = static_cast( + getDerived().TransformDecl(Old->getMemberLoc(), + *I)); if (!InstD) { // Silently ignore these if a UsingShadowDecl instantiated to nothing. // This can happen because of dependent hiding. @@ -5319,7 +5340,8 @@ Sema::OwningExprResult TreeTransform::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { ObjCProtocolDecl *Protocol = cast_or_null( - getDerived().TransformDecl(E->getProtocol())); + getDerived().TransformDecl(E->getLocStart(), + E->getProtocol())); if (!Protocol) return SemaRef.ExprError(); diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp index 183fefab41..0ae13b9728 100644 --- a/test/SemaTemplate/instantiate-complete.cpp +++ b/test/SemaTemplate/instantiate-complete.cpp @@ -66,3 +66,20 @@ struct X3 { void enum_constructors(X1 &x1) { X3 > x3 = x1; } + +namespace PR6376 { + template struct W { }; + + template + struct X { + template + struct apply { + typedef W type; + }; + }; + + template + struct Y : public X::template apply::type { }; + + template struct Y; +}