[clang] cad9ff5 - [clang][ASTImporter] Import ConstructorUsingShadowDecl correctly.
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 1 02:27:02 PDT 2021
Author: Balázs Kéri
Date: 2021-10-01T11:41:08+02:00
New Revision: cad9ff531c71e7c28d7bd5a64a26f9b214156b59
URL: https://github.com/llvm/llvm-project/commit/cad9ff531c71e7c28d7bd5a64a26f9b214156b59
DIFF: https://github.com/llvm/llvm-project/commit/cad9ff531c71e7c28d7bd5a64a26f9b214156b59.diff
LOG: [clang][ASTImporter] Import ConstructorUsingShadowDecl correctly.
Fix import of ConstructorUsingShadowDecl and add tests.
Reviewed By: martong
Differential Revision: https://reviews.llvm.org/D110398
Added:
Modified:
clang/lib/AST/ASTImporter.cpp
clang/unittests/AST/ASTImporterTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 0dbead08aca4..ece9e7fc0112 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -4780,16 +4780,22 @@ ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
UsingShadowDecl *ToShadow;
if (auto *FromConstructorUsingShadow =
dyn_cast<ConstructorUsingShadowDecl>(D)) {
+ Error Err = Error::success();
+ ConstructorUsingShadowDecl *Nominated = importChecked(
+ Err, FromConstructorUsingShadow->getNominatedBaseClassShadowDecl());
+ if (Err)
+ return std::move(Err);
+ // The 'Target' parameter of ConstructorUsingShadowDecl constructor
+ // is really the "NominatedBaseClassShadowDecl" value if it exists
+ // (see code of ConstructorUsingShadowDecl::ConstructorUsingShadowDecl).
+ // We should pass the NominatedBaseClassShadowDecl to it (if non-null) to
+ // get the correct values.
if (GetImportedOrCreateDecl<ConstructorUsingShadowDecl>(
ToShadow, D, Importer.getToContext(), DC, Loc,
- cast<UsingDecl>(*ToIntroducerOrErr), *ToTargetOrErr,
+ cast<UsingDecl>(*ToIntroducerOrErr),
+ Nominated ? Nominated : *ToTargetOrErr,
FromConstructorUsingShadow->constructsVirtualBase()))
return ToShadow;
- // FIXME import the below members!
- // FromConstructorUsingShadow->getNominatedBaseClassShadowDecl();
- // FromConstructorUsingShadow->getConstructedBaseClassShadowDecl();
- // FromConstructorUsingShadow->getNominatedBaseClass();
- // FromConstructorUsingShadow->getConstructedBaseClass();
} else {
if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
Name, *ToIntroducerOrErr, *ToTargetOrErr))
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index b9641d77bea4..b7be56b36610 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6884,15 +6884,14 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportEnumMemberSpecialization) {
TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {
Decl *FromTU = getTuDecl(
R"(
- class a {
- public:
- a(int);
+ struct A {
+ A(int);
};
- struct b : a {
- using a::a; // Ihnerited ctor.
+ struct B : A {
+ using A::A; // Inherited ctor.
};
- void c() {
- (b(0));
+ void f() {
+ (B(0));
}
)",
Lang_CXX11);
@@ -6906,6 +6905,220 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {
EXPECT_TRUE(ToD->isInheritingConstructor());
}
+TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ A(int, int);
+ };
+ struct B : A {
+ using A::A;
+ };
+ struct C : B {
+ using B::B;
+ };
+ )",
+ Lang_CXX11);
+
+ auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordC) {
+ auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("A")));
+ auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("B")));
+ auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
+ TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
+ parameterCountIs(2)));
+ auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowCA = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordC)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ EXPECT_EQ(ShadowBA->getTargetDecl(), ConstrA);
+ EXPECT_EQ(ShadowBA->getNominatedBaseClass(), RecordA);
+ EXPECT_EQ(ShadowBA->getConstructedBaseClass(), RecordA);
+ EXPECT_EQ(ShadowBA->getNominatedBaseClassShadowDecl(), nullptr);
+ EXPECT_EQ(ShadowBA->getConstructedBaseClassShadowDecl(), nullptr);
+ EXPECT_FALSE(ShadowBA->constructsVirtualBase());
+ EXPECT_EQ(ShadowCA->getTargetDecl(), ConstrA);
+ EXPECT_EQ(ShadowCA->getNominatedBaseClass(), RecordB);
+ EXPECT_EQ(ShadowCA->getConstructedBaseClass(), RecordB);
+ EXPECT_EQ(ShadowCA->getNominatedBaseClassShadowDecl(), ShadowBA);
+ EXPECT_EQ(ShadowCA->getConstructedBaseClassShadowDecl(), ShadowBA);
+ EXPECT_FALSE(ShadowCA->constructsVirtualBase());
+ };
+
+ auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("C")));
+
+ auto *ToC = Import(FromC, Lang_CXX11);
+ TranslationUnitDecl *ToTU = ToC->getTranslationUnitDecl();
+
+ CheckAST(FromTU, FromC);
+ CheckAST(ToTU, ToC);
+}
+
+AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,
+ InnerMatcher) {
+ return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
+}
+
+TEST_P(ASTImporterOptionSpecificTestBase,
+ ImportConstructorUsingShadowVirtualBase) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ R"(
+ struct A { A(int, int); };
+ struct B : A { using A::A; };
+
+ struct V1 : virtual B { using B::B; };
+ struct V2 : virtual B { using B::B; };
+
+ struct D2 : V1, V2 {
+ using V1::V1;
+ using V2::V2;
+ };
+ )",
+ Lang_CXX11);
+
+ auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordD2) {
+ auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("A")));
+ auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("B")));
+ auto *RecordV1 = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("V1")));
+ auto *RecordV2 = FirstDeclMatcher<CXXRecordDecl>().match(
+ TU, cxxRecordDecl(hasName("V2")));
+ auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
+ TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
+ parameterCountIs(2)));
+ auto *ConstrB = FirstDeclMatcher<CXXConstructorDecl>().match(
+ TU, cxxConstructorDecl(hasParent(equalsNode(RecordB)),
+ isCopyConstructor()));
+ auto *UsingD2V1 = FirstDeclMatcher<UsingDecl>().match(
+ TU, usingDecl(hasParent(equalsNode(RecordD2))));
+ auto *UsingD2V2 = LastDeclMatcher<UsingDecl>().match(
+ TU, usingDecl(hasParent(equalsNode(RecordD2))));
+ auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowV1A = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowV1B = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
+ hasTargetDecl(equalsNode(ConstrB)))));
+ auto *ShadowV2A = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowV2B = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
+ hasTargetDecl(equalsNode(ConstrB)))));
+ auto *ShadowD2V1A = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
+ hasIntroducerDecl(equalsNode(UsingD2V1)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowD2V1B = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
+ hasIntroducerDecl(equalsNode(UsingD2V1)),
+ hasTargetDecl(equalsNode(ConstrB)))));
+ auto *ShadowD2V2A = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
+ hasIntroducerDecl(equalsNode(UsingD2V2)),
+ hasTargetDecl(equalsNode(ConstrA)))));
+ auto *ShadowD2V2B = cast<ConstructorUsingShadowDecl>(
+ FirstDeclMatcher<UsingShadowDecl>().match(
+ TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
+ hasIntroducerDecl(equalsNode(UsingD2V2)),
+ hasTargetDecl(equalsNode(ConstrB)))));
+
+ EXPECT_EQ(ShadowD2V1A->getTargetDecl(), ConstrA);
+ EXPECT_EQ(ShadowD2V1A->getNominatedBaseClassShadowDecl(), ShadowV1A);
+ EXPECT_EQ(ShadowD2V1A->getNominatedBaseClass(), RecordV1);
+ EXPECT_EQ(ShadowD2V1A->getConstructedBaseClassShadowDecl(), ShadowBA);
+ EXPECT_EQ(ShadowD2V1A->getConstructedBaseClass(), RecordB);
+ EXPECT_TRUE(ShadowD2V1A->constructsVirtualBase());
+ EXPECT_EQ(ShadowD2V1B->getTargetDecl(), ConstrB);
+ EXPECT_EQ(ShadowD2V1B->getNominatedBaseClassShadowDecl(), ShadowV1B);
+ EXPECT_EQ(ShadowD2V1B->getNominatedBaseClass(), RecordV1);
+ EXPECT_EQ(ShadowD2V1B->getConstructedBaseClassShadowDecl(), nullptr);
+ EXPECT_EQ(ShadowD2V1B->getConstructedBaseClass(), RecordB);
+ EXPECT_TRUE(ShadowD2V1B->constructsVirtualBase());
+ EXPECT_EQ(ShadowD2V2A->getTargetDecl(), ConstrA);
+ EXPECT_EQ(ShadowD2V2A->getNominatedBaseClassShadowDecl(), ShadowV2A);
+ EXPECT_EQ(ShadowD2V2A->getNominatedBaseClass(), RecordV2);
+ EXPECT_EQ(ShadowD2V2A->getConstructedBaseClassShadowDecl(), ShadowBA);
+ EXPECT_EQ(ShadowD2V2A->getConstructedBaseClass(), RecordB);
+ EXPECT_TRUE(ShadowD2V2A->constructsVirtualBase());
+ EXPECT_EQ(ShadowD2V2B->getTargetDecl(), ConstrB);
+ EXPECT_EQ(ShadowD2V2B->getNominatedBaseClassShadowDecl(), ShadowV2B);
+ EXPECT_EQ(ShadowD2V2B->getNominatedBaseClass(), RecordV2);
+ EXPECT_EQ(ShadowD2V2B->getConstructedBaseClassShadowDecl(), nullptr);
+ EXPECT_EQ(ShadowD2V2B->getConstructedBaseClass(), RecordB);
+ EXPECT_TRUE(ShadowD2V2B->constructsVirtualBase());
+
+ EXPECT_TRUE(ShadowV1A->constructsVirtualBase());
+ EXPECT_TRUE(ShadowV1B->constructsVirtualBase());
+ EXPECT_TRUE(ShadowV2A->constructsVirtualBase());
+ EXPECT_TRUE(ShadowV2B->constructsVirtualBase());
+ EXPECT_FALSE(ShadowBA->constructsVirtualBase());
+ };
+
+ auto *FromD2 = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("D2")));
+
+ auto *ToD2 = Import(FromD2, Lang_CXX11);
+ TranslationUnitDecl *ToTU = ToD2->getTranslationUnitDecl();
+
+ CheckAST(FromTU, FromD2);
+ CheckAST(ToTU, ToD2);
+}
+
+TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingShadowList) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ void f();
+ void f(int);
+ };
+ struct B : A {
+ using A::f;
+ };
+ )",
+ Lang_CXX11);
+
+ auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
+ FromTU, cxxRecordDecl(hasName("B")));
+
+ auto *ToB = Import(FromB, Lang_CXX11);
+ TranslationUnitDecl *ToTU = ToB->getTranslationUnitDecl();
+
+ auto *ToUsing = FirstDeclMatcher<UsingDecl>().match(
+ ToTU, usingDecl(hasParent(equalsNode(ToB))));
+ auto *ToUsingShadowF1 = FirstDeclMatcher<UsingShadowDecl>().match(
+ ToTU, usingShadowDecl(hasTargetDecl(
+ functionDecl(hasName("f"), parameterCountIs(0)))));
+ auto *ToUsingShadowF2 = FirstDeclMatcher<UsingShadowDecl>().match(
+ ToTU, usingShadowDecl(hasTargetDecl(
+ functionDecl(hasName("f"), parameterCountIs(1)))));
+
+ EXPECT_EQ(ToUsing->shadow_size(), 2u);
+ auto ShadowI = ToUsing->shadow_begin();
+ EXPECT_EQ(*ShadowI, ToUsingShadowF1);
+ ++ShadowI;
+ EXPECT_EQ(*ShadowI, ToUsingShadowF2);
+}
+
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions);
More information about the cfe-commits
mailing list