This revision was automatically updated to reflect the committed changes.
Closed by commit rG23fbfb3f725b: [clang][AST] RecursiveASTVisitor should visit
owned TagDecl of friend type. (authored by balazske).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D131685/new/
https://reviews.llvm.org/D131685
Files:
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/AST/ASTContextParentMapTest.cpp
Index: clang/unittests/AST/ASTContextParentMapTest.cpp
===================================================================
--- clang/unittests/AST/ASTContextParentMapTest.cpp
+++ clang/unittests/AST/ASTContextParentMapTest.cpp
@@ -119,5 +119,34 @@
Lang_CXX11));
}
+TEST(GetParents, FriendTypeLoc) {
+ auto AST = tooling::buildASTFromCode("struct A { friend struct Fr; };"
+ "struct B { friend struct Fr; };"
+ "struct Fr;");
+ auto &Ctx = AST->getASTContext();
+ auto &TU = *Ctx.getTranslationUnitDecl();
+ auto &A = *TU.lookup(&Ctx.Idents.get("A")).front();
+ auto &B = *TU.lookup(&Ctx.Idents.get("B")).front();
+ auto &FrA = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(A).decls_begin()));
+ auto &FrB = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(B).decls_begin()));
+ TypeLoc FrALoc = FrA.getFriendType()->getTypeLoc();
+ TypeLoc FrBLoc = FrB.getFriendType()->getTypeLoc();
+ TagDecl *FrATagDecl =
+ FrALoc.getTypePtr()->getAs<ElaboratedType>()->getOwnedTagDecl();
+ TagDecl *FrBTagDecl =
+ FrBLoc.getTypePtr()->getAs<ElaboratedType>()->getOwnedTagDecl();
+
+ EXPECT_THAT(Ctx.getParents(A), ElementsAre(DynTypedNode::create(TU)));
+ EXPECT_THAT(Ctx.getParents(B), ElementsAre(DynTypedNode::create(TU)));
+ EXPECT_THAT(Ctx.getParents(FrA), ElementsAre(DynTypedNode::create(A)));
+ EXPECT_THAT(Ctx.getParents(FrB), ElementsAre(DynTypedNode::create(B)));
+ EXPECT_THAT(Ctx.getParents(FrALoc), ElementsAre(DynTypedNode::create(FrA)));
+ EXPECT_THAT(Ctx.getParents(FrBLoc), ElementsAre(DynTypedNode::create(FrB)));
+ EXPECT_TRUE(FrATagDecl);
+ EXPECT_FALSE(FrBTagDecl);
+ EXPECT_THAT(Ctx.getParents(*FrATagDecl),
+ ElementsAre(DynTypedNode::create(FrA)));
+}
+
} // end namespace ast_matchers
} // end namespace clang
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1549,10 +1549,15 @@
DEF_TRAVERSE_DECL(FriendDecl, {
// Friend is either decl or a type.
- if (D->getFriendType())
+ if (D->getFriendType()) {
TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
+ // Traverse any CXXRecordDecl owned by this type, since
+ // it will not be in the parent context:
+ if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>())
+ TRY_TO(TraverseDecl(ET->getOwnedTagDecl()));
+ } else {
TRY_TO(TraverseDecl(D->getFriendDecl()));
+ }
})
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
Index: clang/unittests/AST/ASTContextParentMapTest.cpp
===================================================================
--- clang/unittests/AST/ASTContextParentMapTest.cpp
+++ clang/unittests/AST/ASTContextParentMapTest.cpp
@@ -119,5 +119,34 @@
Lang_CXX11));
}
+TEST(GetParents, FriendTypeLoc) {
+ auto AST = tooling::buildASTFromCode("struct A { friend struct Fr; };"
+ "struct B { friend struct Fr; };"
+ "struct Fr;");
+ auto &Ctx = AST->getASTContext();
+ auto &TU = *Ctx.getTranslationUnitDecl();
+ auto &A = *TU.lookup(&Ctx.Idents.get("A")).front();
+ auto &B = *TU.lookup(&Ctx.Idents.get("B")).front();
+ auto &FrA = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(A).decls_begin()));
+ auto &FrB = *cast<FriendDecl>(*++(cast<CXXRecordDecl>(B).decls_begin()));
+ TypeLoc FrALoc = FrA.getFriendType()->getTypeLoc();
+ TypeLoc FrBLoc = FrB.getFriendType()->getTypeLoc();
+ TagDecl *FrATagDecl =
+ FrALoc.getTypePtr()->getAs<ElaboratedType>()->getOwnedTagDecl();
+ TagDecl *FrBTagDecl =
+ FrBLoc.getTypePtr()->getAs<ElaboratedType>()->getOwnedTagDecl();
+
+ EXPECT_THAT(Ctx.getParents(A), ElementsAre(DynTypedNode::create(TU)));
+ EXPECT_THAT(Ctx.getParents(B), ElementsAre(DynTypedNode::create(TU)));
+ EXPECT_THAT(Ctx.getParents(FrA), ElementsAre(DynTypedNode::create(A)));
+ EXPECT_THAT(Ctx.getParents(FrB), ElementsAre(DynTypedNode::create(B)));
+ EXPECT_THAT(Ctx.getParents(FrALoc), ElementsAre(DynTypedNode::create(FrA)));
+ EXPECT_THAT(Ctx.getParents(FrBLoc), ElementsAre(DynTypedNode::create(FrB)));
+ EXPECT_TRUE(FrATagDecl);
+ EXPECT_FALSE(FrBTagDecl);
+ EXPECT_THAT(Ctx.getParents(*FrATagDecl),
+ ElementsAre(DynTypedNode::create(FrA)));
+}
+
} // end namespace ast_matchers
} // end namespace clang
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1549,10 +1549,15 @@
DEF_TRAVERSE_DECL(FriendDecl, {
// Friend is either decl or a type.
- if (D->getFriendType())
+ if (D->getFriendType()) {
TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
+ // Traverse any CXXRecordDecl owned by this type, since
+ // it will not be in the parent context:
+ if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>())
+ TRY_TO(TraverseDecl(ET->getOwnedTagDecl()));
+ } else {
TRY_TO(TraverseDecl(D->getFriendDecl()));
+ }
})
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits