aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorantangelo <contact@antangelo.com>2025-01-27 18:59:12 -0500
committerGitHub <noreply@github.com>2025-01-27 18:59:12 -0500
commitf94c481543bdd3b11a668ad78d46593cf974788f (patch)
treec7a5011911380e9d4692400f7c863f3be73d43cf /clang
parenta34159f85ee01c197cc9d938bd1fc40c4c7dba51 (diff)
downloadllvm-f94c481543bdd3b11a668ad78d46593cf974788f.zip
llvm-f94c481543bdd3b11a668ad78d46593cf974788f.tar.gz
llvm-f94c481543bdd3b11a668ad78d46593cf974788f.tar.bz2
[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.
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/DeclCXX.h45
-rw-r--r--clang/lib/AST/ASTImporter.cpp8
-rw-r--r--clang/lib/AST/DeclCXX.cpp18
-rw-r--r--clang/lib/Sema/SemaTemplateDeductionGuide.cpp8
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp4
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp4
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp3
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp26
8 files changed, 100 insertions, 16 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index fa3f4ec..79fd403 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1967,17 +1967,29 @@ public:
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 @@ private:
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<const CXXDeductionGuideDecl *, 2,
+ SourceDeductionGuideKind>
+ SourceDeductionGuide;
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
public:
@@ -1997,7 +2015,9 @@ public:
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 @@ public:
/// 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<unsigned char>(K);
}
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f661de5..5433b61 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3997,14 +3997,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<CXXDeductionGuideDecl>(
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<CXXDeductionGuideDecl>(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 c0a4356d..a023a9f4 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 9507833..00c5dfd3 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<CXXDeductionGuideDecl>(Result->getTemplatedDecl())
- ->setDeductionCandidateKind(GG->getDeductionCandidateKind());
+ auto *DGuide = cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl());
+ DGuide->setDeductionCandidateKind(GG->getDeductionCandidateKind());
+ DGuide->setSourceDeductionGuide(
+ cast<CXXDeductionGuideDecl>(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 337262e..ebe2dd9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2269,7 +2269,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 0b75468..87e1931 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<DeductionCandidate>(Record.readInt()));
+ D->setSourceDeductionGuide(readDeclAs<CXXDeductionGuideDecl>());
+ D->setSourceDeductionGuideKind(
+ static_cast<CXXDeductionGuideDecl::SourceDeductionGuideKind>(
+ Record.readInt()));
}
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 8b9ba04..fa2294d 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<unsigned char>(D->getDeductionCandidateKind()));
+ Record.AddDeclRef(D->getSourceDeductionGuide());
+ Record.push_back(
+ static_cast<unsigned char>(D->getSourceDeductionGuideKind()));
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index e778605..114d0b4 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -8125,6 +8125,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()));
@@ -8149,6 +8152,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) {
@@ -8167,6 +8173,26 @@ TEST_P(ImportFunctions, CTADWithLocalTypedef) {
ASSERT_TRUE(ToD);
}
+TEST_P(ImportFunctions, CTADAliasTemplate) {
+ Decl *TU = getTuDecl(
+ R"(
+ template <typename T> struct A {
+ A(T);
+ };
+ template<typename T>
+ using B = A<T>;
+ B b{(int)0};
+ )",
+ Lang_CXX20, "input.cc");
+ auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().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);