aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabor Marton <gabor.marton@ericsson.com>2020-11-25 18:32:30 +0100
committerGabor Marton <gabor.marton@ericsson.com>2020-11-30 17:55:25 +0100
commit70eb2ce395be1fe39ceede6719aa667658d1e5a3 (patch)
tree39913f1739bbd4f266d9afb70e0edb47ec7c0bd7
parent7a91794d5b261bc87991d5acce9fa503e9a4f269 (diff)
downloadllvm-project-70eb2ce395be1fe39ceede6719aa667658d1e5a3.tar.gz
[ASTImporter] Support import of CXXDeductionGuideDecl
CXXDeductionGuideDecl is a FunctionDecl, but its constructor should be called appropriately, at least to set the kind variable properly. Differential Revision: https://reviews.llvm.org/D92109
-rw-r--r--clang/lib/AST/ASTImporter.cpp41
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp41
2 files changed, 74 insertions, 8 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 01ee8d275af1..1b014314996b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -499,6 +499,7 @@ namespace clang {
ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D);
ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D);
ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D);
+ ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
ExpectedDecl VisitFieldDecl(FieldDecl *D);
ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
ExpectedDecl VisitFriendDecl(FriendDecl *D);
@@ -3328,6 +3329,17 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
return ToPOrErr.takeError();
}
+ // Common code to import an explicit specifier of different kind of functions.
+ auto ImportExplicitExpr = [this, &Err](auto *Fun) -> ExpectedExpr {
+ Expr *ExplicitExpr = nullptr;
+ if (Fun->getExplicitSpecifier().getExpr()) {
+ ExplicitExpr = importChecked(Err, Fun->getExplicitSpecifier().getExpr());
+ if (Err)
+ return std::move(Err);
+ }
+ return ExplicitExpr;
+ };
+
// Create the imported function.
FunctionDecl *ToFunction = nullptr;
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
@@ -3369,17 +3381,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg);
} else if (CXXConversionDecl *FromConversion =
dyn_cast<CXXConversionDecl>(D)) {
- Expr *ExplicitExpr = nullptr;
- if (FromConversion->getExplicitSpecifier().getExpr()) {
- auto Imp = import(FromConversion->getExplicitSpecifier().getExpr());
- if (!Imp)
- return Imp.takeError();
- ExplicitExpr = *Imp;
- }
+ ExpectedExpr ExplicitExpr = ImportExplicitExpr(FromConversion);
+ if (!ExplicitExpr)
+ return ExplicitExpr.takeError();
if (GetImportedOrCreateDecl<CXXConversionDecl>(
ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
- ExplicitSpecifier(ExplicitExpr,
+ ExplicitSpecifier(*ExplicitExpr,
FromConversion->getExplicitSpecifier().getKind()),
D->getConstexprKind(), SourceLocation(), TrailingRequiresClause))
return ToFunction;
@@ -3390,6 +3398,18 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
Method->isInlineSpecified(), D->getConstexprKind(),
SourceLocation(), TrailingRequiresClause))
return ToFunction;
+ } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
+ ExpectedExpr ExplicitExpr = ImportExplicitExpr(Guide);
+ if (!ExplicitExpr)
+ return ExplicitExpr.takeError();
+ if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>(
+ ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
+ ExplicitSpecifier(*ExplicitExpr,
+ Guide->getExplicitSpecifier().getKind()),
+ NameInfo, T, TInfo, ToEndLoc))
+ return ToFunction;
+ cast<CXXDeductionGuideDecl>(ToFunction)
+ ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate());
} else {
if (GetImportedOrCreateDecl(
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
@@ -3517,6 +3537,11 @@ ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
return VisitCXXMethodDecl(D);
}
+ExpectedDecl
+ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
+ return VisitFunctionDecl(D);
+}
+
ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
// Import the major distinguishing characteristics of a variable.
DeclContext *DC, *LexicalDC;
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 81a92a10f48d..7e56b3ed501f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5957,6 +5957,47 @@ TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
EXPECT_EQ(Record, CompletedTags.front());
}
+TEST_P(ImportFunctions, CTADImplicit) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T> struct A {
+ A(T);
+ };
+ A a{(int)0};
+ )",
+ Lang_CXX17, "input.cc");
+ auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
+ FromTU,
+ cxxDeductionGuideDecl(hasParameter(0, hasType(asString("A<T>")))));
+ auto *ToD = Import(FromD, Lang_CXX17);
+ ASSERT_TRUE(ToD);
+ EXPECT_TRUE(ToD->isCopyDeductionCandidate());
+ // Check that the deduced class template is also imported.
+ EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
+ FromD->getDeducedTemplate()));
+}
+
+TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <typename T> struct A {
+ A(T);
+ };
+ template <typename T> explicit A(T) -> A<float>;
+ A a{(int)0}; // calls A<float>::A(float)
+ )",
+ Lang_CXX17, "input.cc");
+ auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
+ FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
+ // Not-implicit: i.e. not compiler-generated, user defined.
+ ASSERT_FALSE(FromD->isImplicit());
+ ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
+ auto *ToD = Import(FromD, Lang_CXX17);
+ ASSERT_TRUE(ToD);
+ EXPECT_FALSE(FromD->isImplicit());
+ EXPECT_TRUE(ToD->isExplicit());
+}
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions, );