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 @@ -154,6 +154,13 @@ }; } // namespace +static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) { + auto firstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto it) { + return isa(it); + }); + return llvm::make_range(Args.begin(), firstDefaultArg); +} + static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { switch (E.getOperator()) { // Comparison @@ -1111,7 +1118,11 @@ return true; } - syntax::CallArguments *buildCallArguments(CallExpr::arg_range Args) { + /// Builds `CallArguments` syntax node from arguments that appear in source + /// code, i.e. not default arguments. + syntax::CallArguments * + buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) { + auto Args = dropDefaultArgs(ArgsAndDefaultArgs); for (const auto &Arg : Args) { Builder.markExprChild(Arg, syntax::NodeRole::ListElement); const auto *DelimiterToken = @@ -1233,6 +1244,8 @@ } } + bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; } + bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { auto Tokens = Builder.getDeclarationRange(S); if (Tokens.front().kind() == tok::coloncolon) { 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 @@ -2733,6 +2733,54 @@ )txt"})); } +TEST_P(SyntaxTreeTest, CallExpression_DefaultArguments) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +void f(int i = 1, char c = '2'); +void test() { + [[f()]]; + [[f(1)]]; + [[f(1, '2')]]; +} +)cpp", + {R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +`-')' CloseParen + )txt", + R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +|-CallArguments Arguments +| `-IntegerLiteralExpression ListElement +| `-'1' LiteralToken +`-')' CloseParen + )txt", + R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +|-CallArguments Arguments +| |-IntegerLiteralExpression ListElement +| | `-'1' LiteralToken +| |-',' ListDelimiter +| `-CharacterLiteralExpression ListElement +| `-''2'' LiteralToken +`-')' CloseParen +)txt"})); +} + TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { EXPECT_TRUE(treeDumpEqual( R"cpp( @@ -3986,6 +4034,56 @@ )txt"})); } +TEST_P(SyntaxTreeTest, InitDeclarator_Paren_DefaultArguments) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + S(int i = 1, float = 2.); +}; +[[S s0;]] +// FIXME: 's...' is a declarator and '(...)' is initializer +[[S s1(1);]] +[[S s2(1, 2.);]] +)cpp", + {R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-'s0' +`-';' + )txt", + R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-UnknownExpression +| |-'s1' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| `-')' +`-';' + )txt", + R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-UnknownExpression +| |-'s2' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| |-',' +| |-FloatingLiteralExpression +| | `-'2.' LiteralToken +| `-')' +`-';' +)txt"})); +} + TEST_P(SyntaxTreeTest, ImplicitConversion_Argument) { if (!GetParam().isCXX()) { return; @@ -4114,6 +4212,48 @@ )txt"})); } +TEST_P(SyntaxTreeTest, ConstructorCall_DefaultArguments) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct X { + X(int i = 1, char c = '2'); +}; +X test() { + auto x0 = [[X()]]; + auto x1 = [[X(1)]]; + auto x2 = [[X(1, '2')]]; +} +)cpp", + {R"txt( +UnknownExpression +|-'X' +|-'(' +`-')' +)txt", + R"txt( +UnknownExpression +|-'X' +|-'(' +|-IntegerLiteralExpression +| `-'1' LiteralToken +`-')' +)txt", + R"txt( +UnknownExpression +|-'X' +|-'(' +|-IntegerLiteralExpression +| `-'1' LiteralToken +|-',' +|-CharacterLiteralExpression +| `-''2'' LiteralToken +`-')' +)txt"})); +} + TEST_P(SyntaxTreeTest, TypeConversion_FunctionalNotation) { if (!GetParam().isCXX()) { return; @@ -4375,6 +4515,61 @@ )txt")); } +TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Default_One) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +int func1([[int a = 1]]); +)cpp", + {R"txt( +ParameterDeclarationList Parameters +`-SimpleDeclaration ListElement + |-'int' + `-SimpleDeclarator Declarator + |-'a' + |-'=' + `-IntegerLiteralExpression + `-'1' LiteralToken +)txt"})); +} + +TEST_P(SyntaxTreeTest, + ParametersAndQualifiers_InFreeFunctions_Default_Multiple) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +int func2([[int *ap, int a = 1, char c = '2']]); +)cpp", + {R"txt( +ParameterDeclarationList Parameters +|-SimpleDeclaration ListElement +| |-'int' +| `-SimpleDeclarator Declarator +| |-'*' +| `-'ap' +|-',' ListDelimiter +|-SimpleDeclaration ListElement +| |-'int' +| `-SimpleDeclarator Declarator +| |-'a' +| |-'=' +| `-IntegerLiteralExpression +| `-'1' LiteralToken +|-',' ListDelimiter +`-SimpleDeclaration ListElement + |-'char' + `-SimpleDeclarator Declarator + |-'c' + |-'=' + `-CharacterLiteralExpression + `-''2'' LiteralToken +)txt"})); +} + TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) { if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {