diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -939,6 +939,8 @@ return true; } + // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test + // results. Find test coverage or remove it. bool TraverseParenTypeLoc(ParenTypeLoc L) { // We reverse order of traversal to get the proper syntax structure. if (!WalkUpFromParenTypeLoc(L)) @@ -987,6 +989,16 @@ return WalkUpFromFunctionTypeLoc(L); } + bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) { + // In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds + // to "Y::*" but it points to a `ParenTypeLoc` that corresponds to + // "(Y::*mp)" We thus reverse the order of traversal to get the proper + // syntax structure. + if (!WalkUpFromMemberPointerTypeLoc(L)) + return false; + return TraverseTypeLoc(L.getPointeeLoc()); + } + bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) { auto SR = L.getLocalSourceRange(); Builder.foldNode(Builder.getRange(SR), diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -4067,6 +4067,99 @@ )txt")); } +TEST_P(SyntaxTreeTest, MemberFunctionPointer) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct X { + struct Y {}; +}; +void (X::*xp)(); +void (X::**xpp)(const int*); +// FIXME: Generate the right syntax tree for this type, +// i.e. create a syntax node for the outer member pointer +void (X::Y::*xyp)(const int*, char); +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-SimpleDeclaration +| | |-struct +| | |-Y +| | |-{ +| | |-} +| | `-; +| |-} +| `-; +|-SimpleDeclaration +| |-void +| |-SimpleDeclarator +| | |-ParenDeclarator +| | | |-( +| | | |-MemberPointer +| | | | |-X +| | | | |-:: +| | | | `-* +| | | |-xp +| | | `-) +| | `-ParametersAndQualifiers +| | |-( +| | `-) +| `-; +|-SimpleDeclaration +| |-void +| |-SimpleDeclarator +| | |-ParenDeclarator +| | | |-( +| | | |-MemberPointer +| | | | |-X +| | | | |-:: +| | | | `-* +| | | |-* +| | | |-xpp +| | | `-) +| | `-ParametersAndQualifiers +| | |-( +| | |-SimpleDeclaration +| | | |-const +| | | |-int +| | | `-SimpleDeclarator +| | | `-* +| | `-) +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-ParenDeclarator + | | |-( + | | |-X + | | |-:: + | | |-MemberPointer + | | | |-Y + | | | |-:: + | | | `-* + | | |-xyp + | | `-) + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-const + | | |-int + | | `-SimpleDeclarator + | | `-* + | |-, + | |-SimpleDeclaration + | | `-char + | `-) + `-; +)txt")); +} + TEST_P(SyntaxTreeTest, ComplexDeclarator) { EXPECT_TRUE(treeDumpEqual( R"cpp(