forked from OSchip/llvm-project
[clang][AST] RecursiveASTVisitor should visit owned TagDecl of friend type.
A FriendDecl node can have a friend record type that owns a RecordDecl object. This object is different than the one got from TypeSourceInfo object of the FriendDecl. When building a ParentMapContext this owned tag decaration has to be encountered to have the parent set for it. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D131685
This commit is contained in:
parent
62cd26bf96
commit
23fbfb3f72
|
@ -1549,10 +1549,15 @@ DEF_TRAVERSE_DECL(ImportDecl, {})
|
|||
|
||||
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, {
|
||||
|
|
|
@ -119,5 +119,34 @@ TEST(GetParents, ImplicitLambdaNodes) {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue