diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -45,6 +45,7 @@ BinaryOperatorExpression, CxxNullPtrExpression, IntegerLiteralExpression, + IdExpression, // Statements. UnknownStatement, @@ -84,7 +85,9 @@ ArraySubscript, TrailingReturnType, ParametersAndQualifiers, - MemberPointer + MemberPointer, + NestedNameSpecifier, + NameSpecifier }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K); @@ -150,7 +153,9 @@ ArraySubscript_sizeExpression, TrailingReturnType_declarator, ParametersAndQualifiers_parameter, - ParametersAndQualifiers_trailingReturn + ParametersAndQualifiers_trailingReturn, + IdExpression_unqualifiedId, + IdExpression_qualifier }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R); @@ -177,6 +182,36 @@ } }; +class NameSpecifier final : public Tree { +public: + NameSpecifier() : Tree(NodeKind::NameSpecifier) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::NameSpecifier; + } +}; + +class NestedNameSpecifier final : public Tree { +public: + NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {} + static bool classof(const Node *N) { + return N->kind() <= NodeKind::NestedNameSpecifier; + } + + std::vector specifiers(); +}; + +/// An identifier expression, e.g. `n::S::a`. Modeled according to the grammar +class IdExpression final : public Expression { +public: + IdExpression() : Expression(NodeKind::IdExpression) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::IdExpression; + } + + syntax::Leaf *unqualifiedId(); + syntax::NestedNameSpecifier *qualifier(); +}; + /// An expression of an unknown kind, i.e. one not currently handled by the /// syntax tree. class UnknownExpression final : public Expression { 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 @@ -608,6 +608,32 @@ return true; } + syntax::NestedNameSpecifier * + BuildNestedNameSpecifier(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) + return nullptr; + for (auto it = QualifierLoc; it; it = it.getPrefix()) { + auto *NS = new (allocator()) syntax::NameSpecifier; + Builder.foldNode(Builder.getRange(it.getLocalSourceRange()), NS, nullptr); + Builder.markChild(NS, syntax::NodeRole::Unknown); + } + auto *NNS = new (allocator()) syntax::NestedNameSpecifier; + Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS, + nullptr); + return NNS; + } + + bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { + if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc())) + Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier); + + Builder.markChildToken(S->getLocation(), + syntax::NodeRole::IdExpression_unqualifiedId); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::IdExpression, S); + return true; + } + bool WalkUpFromIntegerLiteral(IntegerLiteral *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -28,6 +28,8 @@ return OS << "PostfixUnaryOperatorExpression"; case NodeKind::BinaryOperatorExpression: return OS << "BinaryOperatorExpression"; + case NodeKind::IdExpression: + return OS << "IdExpression"; case NodeKind::UnknownStatement: return OS << "UnknownStatement"; case NodeKind::DeclarationStatement: @@ -94,6 +96,10 @@ return OS << "ParametersAndQualifiers"; case NodeKind::MemberPointer: return OS << "MemberPointer"; + case NodeKind::NameSpecifier: + return OS << "NameSpecifier"; + case NodeKind::NestedNameSpecifier: + return OS << "NestedNameSpecifier"; } llvm_unreachable("unknown node kind"); } @@ -158,10 +164,32 @@ return OS << "ParametersAndQualifiers_parameter"; case syntax::NodeRole::ParametersAndQualifiers_trailingReturn: return OS << "ParametersAndQualifiers_trailingReturn"; + case syntax::NodeRole::IdExpression_unqualifiedId: + return OS << "IdExpression_unqualifiedId"; + case syntax::NodeRole::IdExpression_qualifier: + return OS << "IdExpression_qualifier"; } llvm_unreachable("invalid role"); } +std::vector syntax::NestedNameSpecifier::specifiers() { + std::vector Children; + for (auto *C = firstChild(); C; C = C->nextSibling()) { + Children.push_back(llvm::cast(C)); + } + return Children; +} + +syntax::NestedNameSpecifier *syntax::IdExpression::qualifier() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::IdExpression_qualifier)); +} + +syntax::Leaf *syntax::IdExpression::unqualifiedId() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::IdExpression_unqualifiedId)); +} + syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); 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 @@ -485,7 +485,7 @@ | | |-SimpleDeclarator | | | `-x | | `-: - | |-UnknownExpression + | |-IdExpression | | `-a | |-) | `-EmptyStatement @@ -662,7 +662,7 @@ |-{ |-ExpressionStatement | |-UnknownExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-test | | |-( | | `-) @@ -675,7 +675,7 @@ | |-) | |-ExpressionStatement | | |-UnknownExpression - | | | |-UnknownExpression + | | | |-IdExpression | | | | `-test | | | |-( | | | `-) @@ -683,7 +683,7 @@ | |-else | `-ExpressionStatement | |-UnknownExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-test | | |-( | | `-) @@ -692,6 +692,135 @@ )txt")); } +TEST_P(SyntaxTreeTest, UnqualifiedId) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test(int b) { + int a; + a = b; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | `-b + | `-) + `-CompoundStatement + |-{ + |-DeclarationStatement + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | `-a + | `-; + |-ExpressionStatement + | |-BinaryOperatorExpression + | | |-IdExpression + | | | `-a + | | |-= + | | `-IdExpression + | | `-b + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, QualifiedId) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +namespace a { + namespace b { + struct S { + int i; + static void f(){} + }; + } +} +void test(int b) { + ::a::b::S::f(); +} +)cpp", + R"txt( +*: TranslationUnit +|-NamespaceDefinition +| |-namespace +| |-a +| |-{ +| |-NamespaceDefinition +| | |-namespace +| | |-b +| | |-{ +| | |-SimpleDeclaration +| | | |-struct +| | | |-S +| | | |-{ +| | | |-SimpleDeclaration +| | | | |-int +| | | | |-SimpleDeclarator +| | | | | `-i +| | | | `-; +| | | |-SimpleDeclaration +| | | | |-static +| | | | |-void +| | | | |-SimpleDeclarator +| | | | | |-f +| | | | | `-ParametersAndQualifiers +| | | | | |-( +| | | | | `-) +| | | | `-CompoundStatement +| | | | |-{ +| | | | `-} +| | | |-} +| | | `-; +| | `-} +| `-} +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | `-b + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | |-NestedNameSpecifier + | | | | |-NameSpecifier + | | | | | `-:: + | | | | |-NameSpecifier + | | | | | |-a + | | | | | `-:: + | | | | |-NameSpecifier + | | | | | |-b + | | | | | `-:: + | | | | `-NameSpecifier + | | | | |-S + | | | | `-:: + | | | `-f + | | |-( + | | `-) + | `-; + `-} +)txt")); +} + TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { if (!GetParam().isCXX11OrLater()) { return; @@ -889,13 +1018,13 @@ |-{ |-ExpressionStatement | |-PostfixUnaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | `-++ | `-; |-ExpressionStatement | |-PostfixUnaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | `--- | `-; @@ -941,61 +1070,61 @@ |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |--- - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-++ - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-~ - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-- - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-+ - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-& - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-* - | | `-UnknownExpression + | | `-IdExpression | | `-ap | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-! - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-__real - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-__imag - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; `-} @@ -1036,13 +1165,13 @@ |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-compl - | | `-UnknownExpression + | | `-IdExpression | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-not - | | `-UnknownExpression + | | `-IdExpression | | `-b | `-; `-} @@ -1095,7 +1224,7 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | |-= | | `-IntegerLiteralExpression @@ -1103,7 +1232,7 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | |-<<= | | `-IntegerLiteralExpression @@ -1127,7 +1256,7 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | |-^= | | `-IntegerLiteralExpression @@ -1191,7 +1320,7 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | |-xor_eq | | `-IntegerLiteralExpression @@ -1257,10 +1386,10 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression + | | | |-IdExpression | | | | `-a | | | |-+ - | | | `-UnknownExpression + | | | `-IdExpression | | | `-b | | |-+ | | `-IntegerLiteralExpression @@ -1268,11 +1397,11 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-a | | |-= | | `-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-b | | |-= | | `-IntegerLiteralExpression @@ -1281,11 +1410,11 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression + | | | |-IdExpression | | | | `-a | | | |-+ | | | `-BinaryOperatorExpression - | | | |-UnknownExpression + | | | |-IdExpression | | | | `-b | | | |-* | | | `-IntegerLiteralExpression @@ -1297,14 +1426,14 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression + | | | |-IdExpression | | | | `-a | | | |-% | | | `-IntegerLiteralExpression | | | `-2 | | |-+ | | `-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-b | | |-* | | `-IntegerLiteralExpression @@ -1415,30 +1544,30 @@ |-{ |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-x - | | |-UnknownExpression + | | |-IdExpression | | | `-= - | | `-UnknownExpression + | | `-IdExpression | | `-y | `-; |-ExpressionStatement | |-BinaryOperatorExpression | | |-UnknownExpression - | | | `-UnknownExpression + | | | `-IdExpression | | | `-x - | | |-UnknownExpression + | | |-IdExpression | | | `-+ - | | `-UnknownExpression + | | `-IdExpression | | `-y | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression + | | |-IdExpression | | | `-x - | | |-UnknownExpression + | | |-IdExpression | | | `-< - | | `-UnknownExpression + | | `-IdExpression | | `-y | `-; `-}