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 @@ -439,6 +439,17 @@ Declaration *getDeclaration(); }; +/// Models a function definition. C++ [dcl.fct.def] +/// e.g. `void func() {}` +class FunctionDefinition final : public Declaration { +public: + FunctionDefinition() : Declaration(NodeKind::FunctionDefinition) {} + static bool classof(const Node *N); + SimpleDeclarator *getDeclarator(); + // FIXME: support "= default;", "= delete;". + syntax::Statement *getFunctionBody(); +}; + /// namespace { } class NamespaceDefinition final : public Declaration { public: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.td b/clang/include/clang/Tooling/Syntax/Nodes.td --- a/clang/include/clang/Tooling/Syntax/Nodes.td +++ b/clang/include/clang/Tooling/Syntax/Nodes.td @@ -244,6 +244,7 @@ def SimpleDeclaration : External {} def TemplateDeclaration : External {} def ExplicitTemplateInstantiation : External {} +def FunctionDefinition : External {} def NamespaceDefinition : External {} def NamespaceAliasDefinition : External {} def UsingNamespaceDirective : External {} 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 @@ -707,6 +707,24 @@ return processDeclaratorAndDeclaration(DD); } + bool WalkUpFromFunctionDecl(FunctionDecl *FF) { + if (FF->isDefined()) { + auto Declarator = new (allocator()) syntax::SimpleDeclarator(); + auto DeclaratorRange = getDeclaratorRange( + Builder.sourceManager(), FF->getTypeSourceInfo()->getTypeLoc(), + getQualifiedNameStart(FF), getInitializerRange(FF)); + Builder.foldNode(Builder.getRange(DeclaratorRange), Declarator, nullptr); + Builder.markChild(Declarator, syntax::NodeRole::Declarator); + if (FF->doesThisDeclarationHaveABody()) + Builder.markStmtChild(FF->getBody(), syntax::NodeRole::BodyStatement); + Builder.foldNode(Builder.getRange(FF->getSourceRange()), + new (allocator()) syntax::FunctionDefinition, FF); + return true; + } + // this is not a function definition, build declaration instead. + return WalkUpFromDeclaratorDecl(FF); + } + bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) { return processDeclaratorAndDeclaration(TD); } 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 @@ -387,6 +387,16 @@ findChild(syntax::NodeRole::Declaration)); } +syntax::SimpleDeclarator *syntax::FunctionDefinition::getDeclarator() { + return cast_or_null( + findChild(syntax::NodeRole::Declarator)); +} + +syntax::Statement *syntax::FunctionDefinition::getFunctionBody() { + return cast_or_null( + findChild(syntax::NodeRole::BodyStatement)); +} + syntax::Leaf *syntax::ParenDeclarator::getLparen() { return cast_or_null(findChild(syntax::NodeRole::OpenParen)); } diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -151,6 +151,8 @@ return new (A.getAllocator()) syntax::ExplicitTemplateInstantiation; case syntax::NodeKind::NamespaceDefinition: return new (A.getAllocator()) syntax::NamespaceDefinition; + case syntax::NodeKind::FunctionDefinition: + return new (A.getAllocator()) syntax::FunctionDefinition; case syntax::NodeKind::NamespaceAliasDefinition: return new (A.getAllocator()) syntax::NamespaceAliasDefinition; case syntax::NodeKind::UsingNamespaceDirective: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -91,39 +91,6 @@ INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, BuildSyntaxTreeTest, testing::ValuesIn(allTestClangConfigs()), ); -TEST_P(BuildSyntaxTreeTest, Simple) { - EXPECT_TRUE(treeDumpEqual( - R"cpp( -int main() {} -void foo() {} -)cpp", - R"txt( -TranslationUnit Detached -|-SimpleDeclaration -| |-'int' -| |-DeclaratorList Declarators -| | `-SimpleDeclarator ListElement -| | |-'main' -| | `-ParametersAndQualifiers -| | |-'(' OpenParen -| | `-')' CloseParen -| `-CompoundStatement -| |-'{' OpenParen -| `-'}' CloseParen -`-SimpleDeclaration - |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'foo' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement - |-'{' OpenParen - `-'}' CloseParen -)txt")); -} - TEST_P(BuildSyntaxTreeTest, SimpleVariable) { EXPECT_TRUE(treeDumpEqual( R"cpp( @@ -151,36 +118,35 @@ } TEST_P(BuildSyntaxTreeTest, SimpleFunction) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( -void foo(int a, int b) {} +[[void foo(int a, int b) {}]] )cpp", - R"txt( + {R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'foo' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | |-ParameterDeclarationList Parameters - | | |-SimpleDeclaration ListElement - | | | |-'int' - | | | `-DeclaratorList Declarators - | | | `-SimpleDeclarator ListElement - | | | `-'a' - | | |-',' ListDelimiter - | | `-SimpleDeclaration ListElement - | | |-'int' - | | `-DeclaratorList Declarators - | | `-SimpleDeclarator ListElement - | | `-'b' - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'foo' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | |-ParameterDeclarationList Parameters + | | |-SimpleDeclaration ListElement + | | | |-'int' + | | | `-DeclaratorList Declarators + | | | `-SimpleDeclarator ListElement + | | | `-'a' + | | |-',' ListDelimiter + | | `-SimpleDeclaration ListElement + | | |-'int' + | | `-DeclaratorList Declarators + | | `-SimpleDeclarator ListElement + | | `-'b' + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen `-'}' CloseParen -)txt")); +)txt"})); } TEST_P(BuildSyntaxTreeTest, Simple_BackslashInsideToken) { @@ -457,59 +423,49 @@ TEST_P(BuildSyntaxTreeTest, Expressions) { // expressions should be wrapped in 'ExpressionStatement' when they appear // in a statement position. - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { - test(); - if (1) test(); else test(); + [[test();]] + [[if (1) test(); else test();]] } )cpp", - R"txt( -TranslationUnit Detached -`-SimpleDeclaration - |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement - |-'{' OpenParen - |-ExpressionStatement Statement - | |-CallExpression Expression - | | |-IdExpression Callee - | | | `-UnqualifiedId UnqualifiedId - | | | `-'test' - | | |-'(' OpenParen - | | `-')' CloseParen - | `-';' - |-IfStatement Statement - | |-'if' IntroducerKeyword - | |-'(' - | |-ExpressionStatement Condition - | | `-IntegerLiteralExpression Expression - | | `-'1' LiteralToken - | |-')' - | |-ExpressionStatement ThenStatement - | | |-CallExpression Expression - | | | |-IdExpression Callee - | | | | `-UnqualifiedId UnqualifiedId - | | | | `-'test' - | | | |-'(' OpenParen - | | | `-')' CloseParen - | | `-';' - | |-'else' ElseKeyword - | `-ExpressionStatement ElseStatement - | |-CallExpression Expression - | | |-IdExpression Callee - | | | `-UnqualifiedId UnqualifiedId - | | | `-'test' - | | |-'(' OpenParen - | | `-')' CloseParen - | `-';' - `-'}' CloseParen -)txt")); + {R"txt( +ExpressionStatement Statement +|-CallExpression Expression +| |-IdExpression Callee +| | `-UnqualifiedId UnqualifiedId +| | `-'test' +| |-'(' OpenParen +| `-')' CloseParen +`-';' +)txt", + R"txt( +IfStatement Statement +|-'if' IntroducerKeyword +|-'(' +|-ExpressionStatement Condition +| `-IntegerLiteralExpression Expression +| `-'1' LiteralToken +|-')' +|-ExpressionStatement ThenStatement +| |-CallExpression Expression +| | |-IdExpression Callee +| | | `-UnqualifiedId UnqualifiedId +| | | `-'test' +| | |-'(' OpenParen +| | `-')' CloseParen +| `-';' +|-'else' ElseKeyword +`-ExpressionStatement ElseStatement + |-CallExpression Expression + | |-IdExpression Callee + | | `-UnqualifiedId UnqualifiedId + | | `-'test' + | |-'(' OpenParen + | `-')' CloseParen + `-';' +)txt"})); } TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Identifier) { @@ -1437,30 +1393,16 @@ // hold source code and expected output because of a bug in MSVC up to MSVC // 2019 16.2: // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html - EXPECT_TRUE(treeDumpEqual( // + EXPECT_TRUE(treeDumpEqualOnAnnotations( // "void test() {\n" - " R\"SyntaxTree(\n" + " [[R\"SyntaxTree(\n" " Hello \"Syntax\" \\\"\n" - " )SyntaxTree\";\n" + " )SyntaxTree\"]];\n" "}\n", - "TranslationUnit Detached\n" - "`-SimpleDeclaration\n" - " |-'void'\n" - " |-DeclaratorList Declarators\n" - " | `-SimpleDeclarator ListElement\n" - " | |-'test'\n" - " | `-ParametersAndQualifiers\n" - " | |-'(' OpenParen\n" - " | `-')' CloseParen\n" - " `-CompoundStatement\n" - " |-'{' OpenParen\n" - " |-ExpressionStatement Statement\n" - " | |-StringLiteralExpression Expression\n" - " | | `-'R\"SyntaxTree(\n" - " Hello \"Syntax\" \\\"\n" - " )SyntaxTree\"' LiteralToken\n" - " | `-';'\n" - " `-'}' CloseParen\n")); + {"StringLiteralExpression Expression\n" + "`-'R\"SyntaxTree(\n" + " Hello \"Syntax\" \\\"\n" + " )SyntaxTree\"' LiteralToken\n"})); } TEST_P(BuildSyntaxTreeTest, BoolLiteral) { @@ -2250,7 +2192,7 @@ }]] )cpp", {R"txt( -CompoundStatement +CompoundStatement BodyStatement |-'{' OpenParen |-ExpressionStatement Statement | `-MemberExpression Expression @@ -3002,50 +2944,36 @@ } TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsInsideStatement) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void foo() { - int *a, b; - typedef int *ta, tb; + [[int *a, b]]; + [[typedef int *ta, tb]]; } )cpp", - R"txt( -TranslationUnit Detached -`-SimpleDeclaration - |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'foo' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement - |-'{' OpenParen - |-DeclarationStatement Statement - | |-SimpleDeclaration - | | |-'int' - | | `-DeclaratorList Declarators - | | |-SimpleDeclarator ListElement - | | | |-'*' - | | | `-'a' - | | |-',' ListDelimiter - | | `-SimpleDeclarator ListElement - | | `-'b' - | `-';' - |-DeclarationStatement Statement - | |-SimpleDeclaration - | | |-'typedef' - | | |-'int' - | | `-DeclaratorList Declarators - | | |-SimpleDeclarator ListElement - | | | |-'*' - | | | `-'ta' - | | |-',' ListDelimiter - | | `-SimpleDeclarator ListElement - | | `-'tb' - | `-';' - `-'}' CloseParen -)txt")); + {R"txt( +SimpleDeclaration +|-'int' +`-DeclaratorList Declarators + |-SimpleDeclarator ListElement + | |-'*' + | `-'a' + |-',' ListDelimiter + `-SimpleDeclarator ListElement + `-'b' +)txt", + R"txt( +SimpleDeclaration +|-'typedef' +|-'int' +`-DeclaratorList Declarators + |-SimpleDeclarator ListElement + | |-'*' + | `-'ta' + |-',' ListDelimiter + `-SimpleDeclarator ListElement + `-'tb' +)txt"})); } TEST_P(BuildSyntaxTreeTest, SizeTTypedef) { @@ -3324,16 +3252,15 @@ }; )cpp", {R"txt( -SimpleDeclaration +FunctionDefinition |-'static' |-'void' -|-DeclaratorList Declarators -| `-SimpleDeclarator ListElement -| |-'f' -| `-ParametersAndQualifiers -| |-'(' OpenParen -| `-')' CloseParen -`-CompoundStatement +|-SimpleDeclarator Declarator +| |-'f' +| `-ParametersAndQualifiers +| |-'(' OpenParen +| `-')' CloseParen +`-CompoundStatement BodyStatement |-'{' OpenParen `-'}' CloseParen )txt"})); @@ -3351,19 +3278,18 @@ [[void S::f(){}]] )cpp", {R"txt( -SimpleDeclaration +FunctionDefinition |-'void' -|-DeclaratorList Declarators -| `-SimpleDeclarator ListElement -| |-NestedNameSpecifier -| | |-IdentifierNameSpecifier ListElement -| | | `-'S' -| | `-'::' ListDelimiter -| |-'f' -| `-ParametersAndQualifiers -| |-'(' OpenParen -| `-')' CloseParen -`-CompoundStatement +|-SimpleDeclarator Declarator +| |-NestedNameSpecifier +| | |-IdentifierNameSpecifier ListElement +| | | `-'S' +| | `-'::' ListDelimiter +| |-'f' +| `-ParametersAndQualifiers +| |-'(' OpenParen +| `-')' CloseParen +`-CompoundStatement BodyStatement |-'{' OpenParen `-'}' CloseParen )txt"})); @@ -3985,15 +3911,14 @@ )cpp", R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen |-CompoundStatement Statement | |-'{' OpenParen @@ -4023,15 +3948,14 @@ )cpp", R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen unmodifiable `-'}' CloseParen unmodifiable )txt")); @@ -4047,15 +3971,14 @@ })cpp", R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen |-IfStatement Statement | |-'if' IntroducerKeyword unmodifiable @@ -4093,15 +4016,14 @@ )cpp", R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen |-ExpressionStatement Statement | |-UnknownExpression Expression @@ -4132,15 +4054,14 @@ })cpp", R"txt( TranslationUnit Detached -`-SimpleDeclaration +`-FunctionDefinition |-'void' - |-DeclaratorList Declarators - | `-SimpleDeclarator ListElement - | |-'test' - | `-ParametersAndQualifiers - | |-'(' OpenParen - | `-')' CloseParen - `-CompoundStatement + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement BodyStatement |-'{' OpenParen |-IfStatement Statement | |-'if' IntroducerKeyword unmodifiable @@ -4177,7 +4098,7 @@ }]] )cpp", {R"txt( -CompoundStatement +CompoundStatement BodyStatement |-'{' OpenParen |-ExpressionStatement Statement | |-CallExpression Expression diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -225,15 +225,14 @@ // nodes in the copy are `modifiable`. EXPECT_TRUE(treeDumpEqual(Copy, R"txt( TranslationUnit Detached synthesized -`-SimpleDeclaration synthesized +`-FunctionDefinition synthesized |-'void' synthesized - |-DeclaratorList Declarators synthesized - | `-SimpleDeclarator ListElement synthesized - | |-'test' synthesized - | `-ParametersAndQualifiers synthesized - | |-'(' OpenParen synthesized - | `-')' CloseParen synthesized - `-CompoundStatement synthesized + |-SimpleDeclarator Declarator synthesized + | |-'test' synthesized + | `-ParametersAndQualifiers synthesized + | |-'(' OpenParen synthesized + | `-')' CloseParen synthesized + `-CompoundStatement BodyStatement synthesized |-'{' OpenParen synthesized |-IfStatement Statement synthesized | |-'if' IntroducerKeyword synthesized