Skip to content

Commit f94c481

Browse files
authored
[clang] Track source deduction guide for alias template deduction guides (#123875)
For deduction guides generated from alias template CTAD, store the deduction guide they were originated from. The source kind is also maintained for future expansion in CTAD from inherited constructors. This tracking is required to determine whether an alias template already has a deduction guide corresponding to some deduction guide on the original template, in order to support deduction guides for the alias from deduction guides declared after the initial usage.
1 parent a34159f commit f94c481

File tree

8 files changed

+100
-16
lines changed

8 files changed

+100
-16
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,24 +1967,42 @@ class ExplicitSpecifier {
19671967
class CXXDeductionGuideDecl : public FunctionDecl {
19681968
void anchor() override;
19691969

1970+
public:
1971+
// Represents the relationship between this deduction guide and the
1972+
// deduction guide that it was generated from (or lack thereof).
1973+
// See the SourceDeductionGuide member for more details.
1974+
enum class SourceDeductionGuideKind : uint8_t {
1975+
None,
1976+
Alias,
1977+
};
1978+
19701979
private:
19711980
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
19721981
ExplicitSpecifier ES,
19731982
const DeclarationNameInfo &NameInfo, QualType T,
19741983
TypeSourceInfo *TInfo, SourceLocation EndLocation,
19751984
CXXConstructorDecl *Ctor, DeductionCandidate Kind,
1976-
Expr *TrailingRequiresClause)
1985+
Expr *TrailingRequiresClause,
1986+
const CXXDeductionGuideDecl *GeneratedFrom,
1987+
SourceDeductionGuideKind SourceKind)
19771988
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
19781989
SC_None, false, false, ConstexprSpecKind::Unspecified,
19791990
TrailingRequiresClause),
1980-
Ctor(Ctor), ExplicitSpec(ES) {
1991+
Ctor(Ctor), ExplicitSpec(ES),
1992+
SourceDeductionGuide(GeneratedFrom, SourceKind) {
19811993
if (EndLocation.isValid())
19821994
setRangeEnd(EndLocation);
19831995
setDeductionCandidateKind(Kind);
19841996
}
19851997

19861998
CXXConstructorDecl *Ctor;
19871999
ExplicitSpecifier ExplicitSpec;
2000+
// The deduction guide, if any, that this deduction guide was generated from,
2001+
// in the case of alias template deduction. The SourceDeductionGuideKind
2002+
// member indicates which of these sources applies, or is None otherwise.
2003+
llvm::PointerIntPair<const CXXDeductionGuideDecl *, 2,
2004+
SourceDeductionGuideKind>
2005+
SourceDeductionGuide;
19882006
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
19892007

19902008
public:
@@ -1997,7 +2015,9 @@ class CXXDeductionGuideDecl : public FunctionDecl {
19972015
TypeSourceInfo *TInfo, SourceLocation EndLocation,
19982016
CXXConstructorDecl *Ctor = nullptr,
19992017
DeductionCandidate Kind = DeductionCandidate::Normal,
2000-
Expr *TrailingRequiresClause = nullptr);
2018+
Expr *TrailingRequiresClause = nullptr,
2019+
const CXXDeductionGuideDecl *SourceDG = nullptr,
2020+
SourceDeductionGuideKind SK = SourceDeductionGuideKind::None);
20012021

20022022
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
20032023
GlobalDeclID ID);
@@ -2017,6 +2037,25 @@ class CXXDeductionGuideDecl : public FunctionDecl {
20172037
/// this is an implicit deduction guide.
20182038
CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; }
20192039

2040+
/// Get the deduction guide from which this deduction guide was generated,
2041+
/// if it was generated as part of alias template deduction or from an
2042+
/// inherited constructor.
2043+
const CXXDeductionGuideDecl *getSourceDeductionGuide() const {
2044+
return SourceDeductionGuide.getPointer();
2045+
}
2046+
2047+
void setSourceDeductionGuide(CXXDeductionGuideDecl *DG) {
2048+
SourceDeductionGuide.setPointer(DG);
2049+
}
2050+
2051+
SourceDeductionGuideKind getSourceDeductionGuideKind() const {
2052+
return SourceDeductionGuide.getInt();
2053+
}
2054+
2055+
void setSourceDeductionGuideKind(SourceDeductionGuideKind SK) {
2056+
SourceDeductionGuide.setInt(SK);
2057+
}
2058+
20202059
void setDeductionCandidateKind(DeductionCandidate K) {
20212060
FunctionDeclBits.DeductionCandidateKind = static_cast<unsigned char>(K);
20222061
}

clang/lib/AST/ASTImporter.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3997,14 +3997,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
39973997
importExplicitSpecifier(Err, Guide->getExplicitSpecifier());
39983998
CXXConstructorDecl *Ctor =
39993999
importChecked(Err, Guide->getCorrespondingConstructor());
4000+
const CXXDeductionGuideDecl *SourceDG =
4001+
importChecked(Err, Guide->getSourceDeductionGuide());
40004002
if (Err)
40014003
return std::move(Err);
40024004
if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>(
40034005
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec,
4004-
NameInfo, T, TInfo, ToEndLoc, Ctor))
4006+
NameInfo, T, TInfo, ToEndLoc, Ctor,
4007+
Guide->getDeductionCandidateKind(), TrailingRequiresClause,
4008+
SourceDG, Guide->getSourceDeductionGuideKind()))
40054009
return ToFunction;
4006-
cast<CXXDeductionGuideDecl>(ToFunction)
4007-
->setDeductionCandidateKind(Guide->getDeductionCandidateKind());
40084010
} else {
40094011
if (GetImportedOrCreateDecl(
40104012
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,

clang/lib/AST/DeclCXX.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,18 +2292,22 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
22922292
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
22932293
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
22942294
TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor,
2295-
DeductionCandidate Kind, Expr *TrailingRequiresClause) {
2296-
return new (C, DC)
2297-
CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, TInfo,
2298-
EndLocation, Ctor, Kind, TrailingRequiresClause);
2295+
DeductionCandidate Kind, Expr *TrailingRequiresClause,
2296+
const CXXDeductionGuideDecl *GeneratedFrom,
2297+
SourceDeductionGuideKind SourceKind) {
2298+
return new (C, DC) CXXDeductionGuideDecl(
2299+
C, DC, StartLoc, ES, NameInfo, T, TInfo, EndLocation, Ctor, Kind,
2300+
TrailingRequiresClause, GeneratedFrom, SourceKind);
22992301
}
23002302

23012303
CXXDeductionGuideDecl *
23022304
CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
23032305
return new (C, ID) CXXDeductionGuideDecl(
2304-
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
2305-
QualType(), nullptr, SourceLocation(), nullptr,
2306-
DeductionCandidate::Normal, nullptr);
2306+
C, /*DC=*/nullptr, SourceLocation(), ExplicitSpecifier(),
2307+
DeclarationNameInfo(), QualType(), /*TInfo=*/nullptr, SourceLocation(),
2308+
/*Ctor=*/nullptr, DeductionCandidate::Normal,
2309+
/*TrailingRequiresClause=*/nullptr,
2310+
/*GeneratedFrom=*/nullptr, SourceDeductionGuideKind::None);
23072311
}
23082312

23092313
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,12 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
11751175
GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(),
11761176
AliasTemplate->getLocation(), AliasTemplate->getEndLoc(),
11771177
F->isImplicit()));
1178-
cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl())
1179-
->setDeductionCandidateKind(GG->getDeductionCandidateKind());
1178+
auto *DGuide = cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl());
1179+
DGuide->setDeductionCandidateKind(GG->getDeductionCandidateKind());
1180+
DGuide->setSourceDeductionGuide(
1181+
cast<CXXDeductionGuideDecl>(F->getTemplatedDecl()));
1182+
DGuide->setSourceDeductionGuideKind(
1183+
CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
11801184
return Result;
11811185
}
11821186
return nullptr;

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2269,7 +2269,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
22692269
SemaRef.Context, DC, D->getInnerLocStart(),
22702270
InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
22712271
D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(),
2272-
DGuide->getDeductionCandidateKind(), TrailingRequiresClause);
2272+
DGuide->getDeductionCandidateKind(), TrailingRequiresClause,
2273+
DGuide->getSourceDeductionGuide(),
2274+
DGuide->getSourceDeductionGuideKind());
22732275
Function->setAccess(D->getAccess());
22742276
} else {
22752277
Function = FunctionDecl::Create(

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,10 @@ void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
22952295
VisitFunctionDecl(D);
22962296
D->setDeductionCandidateKind(
22972297
static_cast<DeductionCandidate>(Record.readInt()));
2298+
D->setSourceDeductionGuide(readDeclAs<CXXDeductionGuideDecl>());
2299+
D->setSourceDeductionGuideKind(
2300+
static_cast<CXXDeductionGuideDecl::SourceDeductionGuideKind>(
2301+
Record.readInt()));
22982302
}
22992303

23002304
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,9 @@ void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
846846
Record.AddDeclRef(D->Ctor);
847847
VisitFunctionDecl(D);
848848
Record.push_back(static_cast<unsigned char>(D->getDeductionCandidateKind()));
849+
Record.AddDeclRef(D->getSourceDeductionGuide());
850+
Record.push_back(
851+
static_cast<unsigned char>(D->getSourceDeductionGuideKind()));
849852
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
850853
}
851854

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8125,6 +8125,9 @@ TEST_P(ImportFunctions, CTADImplicit) {
81258125
auto *ToD = Import(FromD, Lang_CXX17);
81268126
ASSERT_TRUE(ToD);
81278127
EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy);
8128+
EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8129+
EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8130+
CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
81288131
// Check that the deduced class template is also imported.
81298132
EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
81308133
FromD->getDeducedTemplate()));
@@ -8149,6 +8152,9 @@ TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
81498152
ASSERT_TRUE(ToD);
81508153
EXPECT_FALSE(FromD->isImplicit());
81518154
EXPECT_TRUE(ToD->isExplicit());
8155+
EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8156+
EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8157+
CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
81528158
}
81538159

81548160
TEST_P(ImportFunctions, CTADWithLocalTypedef) {
@@ -8167,6 +8173,26 @@ TEST_P(ImportFunctions, CTADWithLocalTypedef) {
81678173
ASSERT_TRUE(ToD);
81688174
}
81698175

8176+
TEST_P(ImportFunctions, CTADAliasTemplate) {
8177+
Decl *TU = getTuDecl(
8178+
R"(
8179+
template <typename T> struct A {
8180+
A(T);
8181+
};
8182+
template<typename T>
8183+
using B = A<T>;
8184+
B b{(int)0};
8185+
)",
8186+
Lang_CXX20, "input.cc");
8187+
auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8188+
TU, cxxDeductionGuideDecl(hasParameter(0, hasType(asString("int")))));
8189+
auto *ToD = Import(FromD, Lang_CXX20);
8190+
ASSERT_TRUE(ToD);
8191+
EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==
8192+
CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
8193+
EXPECT_TRUE(ToD->getSourceDeductionGuide());
8194+
}
8195+
81708196
TEST_P(ImportFunctions, ParmVarDeclDeclContext) {
81718197
constexpr auto FromTUCode = R"(
81728198
void f(int P);

0 commit comments

Comments
 (0)