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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits