From: Richard Smith Date: Sat, 11 Oct 2014 00:37:16 +0000 (+0000) Subject: [modules] When instantiating a class member, don't expect to find the previous X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cd98c92e39cbc0661897533da2d046ab26a347c2;p=clang [modules] When instantiating a class member, don't expect to find the previous declaration in the instantiation if the previous declaration came from another definition of the class template that got merged into the pattern definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219552 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index dce8ca4c8a..a07f7765fc 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -261,6 +261,24 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } } +/// Get the previous declaration of a declaration for the purposes of template +/// instantiation. If this finds a previous declaration, then the previous +/// declaration of the instantiation of D should be an instantiation of the +/// result of this function. +template +static DeclT *getPreviousDeclForInstantiation(DeclT *D) { + DeclT *Result = D->getPreviousDecl(); + + // If the declaration is within a class, and the previous declaration was + // merged from a different definition of that class, then we don't have a + // previous declaration for the purpose of template instantiation. + if (Result && isa(D->getDeclContext()) && + D->getLexicalDeclContext() != Result->getLexicalDeclContext()) + return nullptr; + + return Result; +} + Decl * TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { llvm_unreachable("Translation units cannot be instantiated"); @@ -347,7 +365,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, } } - if (TypedefNameDecl *Prev = D->getPreviousDecl()) { + if (TypedefNameDecl *Prev = getPreviousDeclForInstantiation(D)) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); if (!InstPrev) @@ -370,13 +388,15 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); - Owner->addDecl(Typedef); + if (Typedef) + Owner->addDecl(Typedef); return Typedef; } Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); - Owner->addDecl(Typedef); + if (Typedef) + Owner->addDecl(Typedef); return Typedef; } @@ -394,7 +414,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { TypeAliasDecl *Pattern = D->getTemplatedDecl(); TypeAliasTemplateDecl *PrevAliasTemplate = nullptr; - if (Pattern->getPreviousDecl()) { + if (getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) { PrevAliasTemplate = dyn_cast(Found.front()); @@ -714,9 +734,9 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EnumDecl *PrevDecl = nullptr; - if (D->getPreviousDecl()) { + if (EnumDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - D->getPreviousDecl(), + PatternPrev, TemplateArgs); if (!Prev) return nullptr; PrevDecl = cast(Prev); @@ -878,7 +898,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *PrevDecl = nullptr; ClassTemplateDecl *PrevClassTemplate = nullptr; - if (!isFriend && Pattern->getPreviousDecl()) { + if (!isFriend && getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) { PrevClassTemplate = dyn_cast(Found.front()); @@ -1072,7 +1092,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { VarDecl *Pattern = D->getTemplatedDecl(); VarTemplateDecl *PrevVarTemplate = nullptr; - if (Pattern->getPreviousDecl()) { + if (getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) PrevVarTemplate = dyn_cast(Found.front()); @@ -1182,7 +1202,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (!isFriend) { Owner->addDecl(InstTemplate); } else if (InstTemplate->getDeclContext()->isRecord() && - !D->getPreviousDecl()) { + !getPreviousDeclForInstantiation(D)) { SemaRef.CheckFriendAccess(InstTemplate); } @@ -1193,9 +1213,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = nullptr; if (D->isInjectedClassName()) PrevDecl = cast(Owner); - else if (D->getPreviousDecl()) { + else if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - D->getPreviousDecl(), + PatternPrev, TemplateArgs); if (!Prev) return nullptr; PrevDecl = cast(Prev); @@ -2259,7 +2279,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (CheckRedeclaration) { if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) continue; - } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) { + } else if (UsingShadowDecl *OldPrev = + getPreviousDeclForInstantiation(Shadow)) { PrevDecl = cast_or_null(SemaRef.FindInstantiatedDecl( Shadow->getLocation(), OldPrev, TemplateArgs)); } diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index 92333b377a..135fbb7702 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -97,3 +97,5 @@ struct MergeAnonUnionMember { union { int t1; } values; }; inline MergeAnonUnionMember<> maum_a() { return {}; } + +template struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; }; diff --git a/test/Modules/Inputs/cxx-templates-c.h b/test/Modules/Inputs/cxx-templates-c.h index 6b4c506670..269db441d5 100644 --- a/test/Modules/Inputs/cxx-templates-c.h +++ b/test/Modules/Inputs/cxx-templates-c.h @@ -18,3 +18,6 @@ struct MergeAnonUnionMember { union { int t1; } values; }; inline MergeAnonUnionMember<> maum_c() { return {}; } + +template struct DontWalkPreviousDeclAfterMerging { struct Inner { typedef T type; }; }; +typedef DontWalkPreviousDeclAfterMerging::Inner dwpdam_typedef; diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index b299233665..13e209acc4 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -145,6 +145,9 @@ MergeSpecializations::explicitly_specialized_in_c spec_in_c_2; #endif MergeAnonUnionMember<> maum_main; +typedef DontWalkPreviousDeclAfterMerging dwpdam_typedef_2; +dwpdam_typedef::type dwpdam_typedef_use; +DontWalkPreviousDeclAfterMerging::Inner::type dwpdam; using AliasTemplateMergingTest = WithAliasTemplate::X;