martong updated this revision to Diff 200435.
martong marked an inline comment as done.
martong added a comment.
- Remove getUnderlyingType
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62064/new/
https://reviews.llvm.org/D62064
Files:
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/ASTImporterLookupTable.cpp
clang/unittests/AST/ASTImporterTest.cpp
Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -4248,11 +4248,16 @@
static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
QualType Ty = FD->getFriendType()->getType();
- QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
- return cast<RecordType>(NamedTy)->getDecl();
+ if (auto *Inner = dyn_cast<TypedefType>(Ty.getTypePtr())) {
+ Ty = Ty.getCanonicalType();
+ }
+ if (isa<ElaboratedType>(Ty))
+ Ty = cast<ElaboratedType>(Ty)->getNamedType();
+ return cast<RecordType>(Ty)->getDecl();
}
-TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
+TEST_P(ASTImporterLookupTableTest,
+ LookupFindsFwdFriendClassDeclWithElaboratedType) {
TranslationUnitDecl *ToTU = getToTuDecl(
R"(
class Y { friend class F; };
@@ -4276,6 +4281,52 @@
EXPECT_EQ(Res.size(), 0u);
}
+TEST_P(ASTImporterLookupTableTest,
+ LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class F;
+ class Y { friend F; };
+ )",
+ Lang_CXX11);
+
+ // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
+ // So we must dig up the underlying CXXRecordDecl.
+ ASTImporterLookupTable LT(*ToTU);
+ auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
+ const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
+ auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
+
+ DeclarationName Name = RD->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.size(), 1u);
+ EXPECT_EQ(*Res.begin(), RD);
+
+ Res = LT.lookup(Y, Name);
+ EXPECT_EQ(Res.size(), 0u);
+}
+
+TEST_P(ASTImporterLookupTableTest,
+ LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ class F;
+ using alias_of_f = F;
+ class Y { friend alias_of_f; };
+ )",
+ Lang_CXX11);
+
+ // ASTImporterLookupTable constructor handles using declarations correctly,
+ // no assert is expected.
+ ASTImporterLookupTable LT(*ToTU);
+
+ auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
+ ToTU, typeAliasDecl(hasName("alias_of_f")));
+ DeclarationName Name = Alias->getDeclName();
+ auto Res = LT.lookup(ToTU, Name);
+ EXPECT_EQ(Res.count(Alias), 1u);
+}
+
TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
TranslationUnitDecl *ToTU = getToTuDecl(
R"(
Index: clang/lib/AST/ASTImporterLookupTable.cpp
===================================================================
--- clang/lib/AST/ASTImporterLookupTable.cpp
+++ clang/lib/AST/ASTImporterLookupTable.cpp
@@ -26,17 +26,30 @@
LT.add(D);
return true;
}
+ // In most cases the FriendDecl contains the declaration of the befriended
+ // class as a child node, so it is discovered during the recursive
+ // visitation. However, there are cases when the befriended class is not a
+ // child, thus it must be fetched explicitly from the FriendDecl, and only
+ // then can we add it to the lookup table.
bool VisitFriendDecl(FriendDecl *D) {
if (D->getFriendType()) {
QualType Ty = D->getFriendType()->getType();
- // FIXME Can this be other than elaborated?
- QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
- if (!NamedTy->isDependentType()) {
- if (const auto *RTy = dyn_cast<RecordType>(NamedTy))
+ if (isa<ElaboratedType>(Ty))
+ Ty = cast<ElaboratedType>(Ty)->getNamedType();
+ // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
+ // always has that decl as child node.
+ // However, there are non-dependent cases which does not have the
+ // type as a child node. We have to dig up that type now.
+ if (!Ty->isDependentType()) {
+ if (const auto *RTy = dyn_cast<RecordType>(Ty))
LT.add(RTy->getAsCXXRecordDecl());
- else if (const auto *SpecTy =
- dyn_cast<TemplateSpecializationType>(NamedTy)) {
+ else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
LT.add(SpecTy->getAsCXXRecordDecl());
+ else if (isa<TypedefType>(Ty)) {
+ // We do not put friend typedefs to the lookup table because
+ // ASTImporter does not organize typedefs into redecl chains.
+ } else {
+ llvm_unreachable("Unhandled type of friend class");
}
}
}
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -2256,7 +2256,8 @@
if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
return Importer.MapImported(D, FoundTypedef);
}
- // FIXME Handle redecl chain.
+ // FIXME Handle redecl chain. When you do that make consistent changes
+ // in ASTImporterLookupTable too.
break;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits