From d12f6af14c237555f153a116645d9ccb8c42eb7a Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 26 Aug 2014 03:52:16 +0000 Subject: [PATCH] [modules] Track the described template in an alias declaration that is the pattern of an alias template declaration. Use this to merge alias templates properly when they're members of class template specializations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216437 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 10 +++++++++- lib/Sema/SemaDeclCXX.cpp | 1 + lib/Sema/SemaTemplateInstantiateDecl.cpp | 1 + lib/Serialization/ASTReaderDecl.cpp | 17 ++++++++++++----- lib/Serialization/ASTWriterDecl.cpp | 1 + test/Modules/Inputs/cxx-templates-a.h | 2 ++ test/Modules/Inputs/cxx-templates-b.h | 2 ++ test/Modules/Inputs/cxx-templates-common.h | 4 ++++ test/Modules/cxx-templates.cpp | 2 ++ 9 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index c8c118cbcf..083183525c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -43,6 +43,7 @@ class Stmt; class StringLiteral; class TemplateArgumentList; class TemplateParameterList; +class TypeAliasTemplateDecl; class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; @@ -2492,9 +2493,13 @@ public: /// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x /// alias-declaration. class TypeAliasDecl : public TypedefNameDecl { + /// The template for which this is the pattern, if any. + TypeAliasTemplateDecl *Template; + TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {} + : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo), + Template(nullptr) {} public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, @@ -2504,6 +2509,9 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; } + void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TypeAlias; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6a48162502..82d06d126b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -8207,6 +8207,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, Name.Identifier, TemplateParams, NewTD); + NewTD->setDescribedAliasTemplate(NewDecl); NewDecl->setAccess(AS); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c27a243041..e9d95f2b29 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -363,6 +363,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { TypeAliasTemplateDecl *Inst = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), InstParams, AliasInst); + AliasInst->setDescribedAliasTemplate(Inst); if (PrevAliasTemplate) Inst->setPreviousDecl(PrevAliasTemplate); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 2503500dcd..5f7a93f132 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -234,7 +234,7 @@ namespace clang { void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); - void VisitTypedefNameDecl(TypedefNameDecl *TD); + RedeclarableResult VisitTypedefNameDecl(TypedefNameDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); @@ -456,7 +456,8 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); } -void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx); @@ -465,15 +466,21 @@ void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { TD->setModedTypeSourceInfo(TInfo, modedT); } else TD->setTypeSourceInfo(TInfo); - mergeRedeclarable(TD, Redecl); + return Redecl; } void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { - VisitTypedefNameDecl(TD); + RedeclarableResult Redecl = VisitTypedefNameDecl(TD); + mergeRedeclarable(TD, Redecl); } void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { - VisitTypedefNameDecl(TD); + RedeclarableResult Redecl = VisitTypedefNameDecl(TD); + if (auto *Template = ReadDeclAs(Record, Idx)) + // Merged when we merge the template. + TD->setDescribedAliasTemplate(Template); + else + mergeRedeclarable(TD, Redecl); } ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index dca7796c02..cd8f7ddf59 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -236,6 +236,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { VisitTypedefNameDecl(D); + Writer.AddDeclRef(D->getDescribedAliasTemplate(), Record); Code = serialization::DECL_TYPEALIAS; } diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index f3150398e7..928a544fc4 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -85,3 +85,5 @@ template struct PartiallyInstantiatePartialSpec { static T *bar() { return reinterpret_cast(0); } }; typedef PartiallyInstantiatePartialSpec PartiallyInstantiatePartialSpecHelper; + +void InstantiateWithAliasTemplate(WithAliasTemplate::X); diff --git a/test/Modules/Inputs/cxx-templates-b.h b/test/Modules/Inputs/cxx-templates-b.h index 8b97d22a37..cfaea282df 100644 --- a/test/Modules/Inputs/cxx-templates-b.h +++ b/test/Modules/Inputs/cxx-templates-b.h @@ -69,6 +69,8 @@ template<> struct MergeSpecializations { template using AliasTemplate = U; +void InstantiateWithAliasTemplate(WithAliasTemplate::X); + @import cxx_templates_a; template void UseDefinedInBImplIndirectly(T &v) { PerformDelayedLookup(v); diff --git a/test/Modules/Inputs/cxx-templates-common.h b/test/Modules/Inputs/cxx-templates-common.h index f3c9022309..d729c6edf4 100644 --- a/test/Modules/Inputs/cxx-templates-common.h +++ b/test/Modules/Inputs/cxx-templates-common.h @@ -41,4 +41,8 @@ typedef WithExplicitSpecialization WithExplicitSpecializationUse; template struct WithImplicitSpecialMembers { int n; }; +template struct WithAliasTemplate { + template using X = T; +}; + #include "cxx-templates-textual.h" diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index fedaa03ef4..d0a6c0f9e5 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -143,6 +143,8 @@ MergeSpecializations::explicitly_specialized_in_b spec_in_b_2; MergeSpecializations::explicitly_specialized_in_c spec_in_c_2; #endif +using AliasTemplateMergingTest = WithAliasTemplate::X; + @import cxx_templates_common; typedef SomeTemplate SomeTemplateIntPtr; -- 2.50.1