diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index fa3f4ec98eb36..79fd403c2718c 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1967,17 +1967,29 @@ class ExplicitSpecifier { class CXXDeductionGuideDecl : public FunctionDecl { void anchor() override; +public: + // Represents the relationship between this deduction guide and the + // deduction guide that it was generated from (or lack thereof). + // See the SourceDeductionGuide member for more details. + enum class SourceDeductionGuideKind : uint8_t { + None, + Alias, + }; + private: CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, DeductionCandidate Kind, - Expr *TrailingRequiresClause) + Expr *TrailingRequiresClause, + const CXXDeductionGuideDecl *GeneratedFrom, + SourceDeductionGuideKind SourceKind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, SC_None, false, false, ConstexprSpecKind::Unspecified, TrailingRequiresClause), - Ctor(Ctor), ExplicitSpec(ES) { + Ctor(Ctor), ExplicitSpec(ES), + SourceDeductionGuide(GeneratedFrom, SourceKind) { if (EndLocation.isValid()) setRangeEnd(EndLocation); setDeductionCandidateKind(Kind); @@ -1985,6 +1997,12 @@ class CXXDeductionGuideDecl : public FunctionDecl { CXXConstructorDecl *Ctor; ExplicitSpecifier ExplicitSpec; + // The deduction guide, if any, that this deduction guide was generated from, + // in the case of alias template deduction. The SourceDeductionGuideKind + // member indicates which of these sources applies, or is None otherwise. + llvm::PointerIntPair + SourceDeductionGuide; void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } public: @@ -1997,7 +2015,9 @@ class CXXDeductionGuideDecl : public FunctionDecl { TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor = nullptr, DeductionCandidate Kind = DeductionCandidate::Normal, - Expr *TrailingRequiresClause = nullptr); + Expr *TrailingRequiresClause = nullptr, + const CXXDeductionGuideDecl *SourceDG = nullptr, + SourceDeductionGuideKind SK = SourceDeductionGuideKind::None); static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -2017,6 +2037,25 @@ class CXXDeductionGuideDecl : public FunctionDecl { /// this is an implicit deduction guide. CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; } + /// Get the deduction guide from which this deduction guide was generated, + /// if it was generated as part of alias template deduction or from an + /// inherited constructor. + const CXXDeductionGuideDecl *getSourceDeductionGuide() const { + return SourceDeductionGuide.getPointer(); + } + + void setSourceDeductionGuide(CXXDeductionGuideDecl *DG) { + SourceDeductionGuide.setPointer(DG); + } + + SourceDeductionGuideKind getSourceDeductionGuideKind() const { + return SourceDeductionGuide.getInt(); + } + + void setSourceDeductionGuideKind(SourceDeductionGuideKind SK) { + SourceDeductionGuide.setInt(SK); + } + void setDeductionCandidateKind(DeductionCandidate K) { FunctionDeclBits.DeductionCandidateKind = static_cast(K); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 0669aa1b809c3..0a643f8092ed3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3999,14 +3999,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { importExplicitSpecifier(Err, Guide->getExplicitSpecifier()); CXXConstructorDecl *Ctor = importChecked(Err, Guide->getCorrespondingConstructor()); + const CXXDeductionGuideDecl *SourceDG = + importChecked(Err, Guide->getSourceDeductionGuide()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec, - NameInfo, T, TInfo, ToEndLoc, Ctor)) + NameInfo, T, TInfo, ToEndLoc, Ctor, + Guide->getDeductionCandidateKind(), TrailingRequiresClause, + SourceDG, Guide->getSourceDeductionGuideKind())) return ToFunction; - cast(ToFunction) - ->setDeductionCandidateKind(Guide->getDeductionCandidateKind()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index c0a4356dcb004..a023a9f456a0e 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2292,18 +2292,22 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, - DeductionCandidate Kind, Expr *TrailingRequiresClause) { - return new (C, DC) - CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, TInfo, - EndLocation, Ctor, Kind, TrailingRequiresClause); + DeductionCandidate Kind, Expr *TrailingRequiresClause, + const CXXDeductionGuideDecl *GeneratedFrom, + SourceDeductionGuideKind SourceKind) { + return new (C, DC) CXXDeductionGuideDecl( + C, DC, StartLoc, ES, NameInfo, T, TInfo, EndLocation, Ctor, Kind, + TrailingRequiresClause, GeneratedFrom, SourceKind); } CXXDeductionGuideDecl * CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { return new (C, ID) CXXDeductionGuideDecl( - C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), - QualType(), nullptr, SourceLocation(), nullptr, - DeductionCandidate::Normal, nullptr); + C, /*DC=*/nullptr, SourceLocation(), ExplicitSpecifier(), + DeclarationNameInfo(), QualType(), /*TInfo=*/nullptr, SourceLocation(), + /*Ctor=*/nullptr, DeductionCandidate::Normal, + /*TrailingRequiresClause=*/nullptr, + /*GeneratedFrom=*/nullptr, SourceDeductionGuideKind::None); } RequiresExprBodyDecl *RequiresExprBodyDecl::Create( diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 950783303efb3..00c5dfd3d7a43 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -1175,8 +1175,12 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(), AliasTemplate->getLocation(), AliasTemplate->getEndLoc(), F->isImplicit())); - cast(Result->getTemplatedDecl()) - ->setDeductionCandidateKind(GG->getDeductionCandidateKind()); + auto *DGuide = cast(Result->getTemplatedDecl()); + DGuide->setDeductionCandidateKind(GG->getDeductionCandidateKind()); + DGuide->setSourceDeductionGuide( + cast(F->getTemplatedDecl())); + DGuide->setSourceDeductionGuideKind( + CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias); return Result; } return nullptr; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6a2331e59477a..1a637710c99b7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2264,7 +2264,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( SemaRef.Context, DC, D->getInnerLocStart(), InstantiatedExplicitSpecifier, NameInfo, T, TInfo, D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(), - DGuide->getDeductionCandidateKind(), TrailingRequiresClause); + DGuide->getDeductionCandidateKind(), TrailingRequiresClause, + DGuide->getSourceDeductionGuide(), + DGuide->getSourceDeductionGuideKind()); Function->setAccess(D->getAccess()); } else { Function = FunctionDecl::Create( diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0b75468a94103..87e1931ee47fd 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2295,6 +2295,10 @@ void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { VisitFunctionDecl(D); D->setDeductionCandidateKind( static_cast(Record.readInt())); + D->setSourceDeductionGuide(readDeclAs()); + D->setSourceDeductionGuideKind( + static_cast( + Record.readInt())); } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 8b9ba04dce91c..fa2294da95de8 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -846,6 +846,9 @@ void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { Record.AddDeclRef(D->Ctor); VisitFunctionDecl(D); Record.push_back(static_cast(D->getDeductionCandidateKind())); + Record.AddDeclRef(D->getSourceDeductionGuide()); + Record.push_back( + static_cast(D->getSourceDeductionGuideKind())); Code = serialization::DECL_CXX_DEDUCTION_GUIDE; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 791248e7a394f..bd8468ad4baed 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -8105,6 +8105,9 @@ TEST_P(ImportFunctions, CTADImplicit) { auto *ToD = Import(FromD, Lang_CXX17); ASSERT_TRUE(ToD); EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy); + EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr); + EXPECT_EQ(ToD->getSourceDeductionGuideKind(), + CXXDeductionGuideDecl::SourceDeductionGuideKind::None); // Check that the deduced class template is also imported. EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull( FromD->getDeducedTemplate())); @@ -8129,6 +8132,9 @@ TEST_P(ImportFunctions, CTADUserDefinedExplicit) { ASSERT_TRUE(ToD); EXPECT_FALSE(FromD->isImplicit()); EXPECT_TRUE(ToD->isExplicit()); + EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr); + EXPECT_EQ(ToD->getSourceDeductionGuideKind(), + CXXDeductionGuideDecl::SourceDeductionGuideKind::None); } TEST_P(ImportFunctions, CTADWithLocalTypedef) { @@ -8147,6 +8153,26 @@ TEST_P(ImportFunctions, CTADWithLocalTypedef) { ASSERT_TRUE(ToD); } +TEST_P(ImportFunctions, CTADAliasTemplate) { + Decl *TU = getTuDecl( + R"( + template struct A { + A(T); + }; + template + using B = A; + B b{(int)0}; + )", + Lang_CXX20, "input.cc"); + auto *FromD = FirstDeclMatcher().match( + TU, cxxDeductionGuideDecl(hasParameter(0, hasType(asString("int"))))); + auto *ToD = Import(FromD, Lang_CXX20); + ASSERT_TRUE(ToD); + EXPECT_TRUE(ToD->getSourceDeductionGuideKind() == + CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias); + EXPECT_TRUE(ToD->getSourceDeductionGuide()); +} + TEST_P(ImportFunctions, ParmVarDeclDeclContext) { constexpr auto FromTUCode = R"( void f(int P);