[SyntaxTree] Fix crash on functions with default arguments.

* Do not visit `CXXDefaultArgExpr`
* To build `CallArguments` nodes, just go through non-default arguments

Differential Revision: https://reviews.llvm.org/D87249
This commit is contained in:
Eduardo Caldas 2020-09-07 17:47:09 +00:00
parent 134455a07c
commit f5087d5c72
2 changed files with 209 additions and 1 deletions

View File

@ -154,6 +154,13 @@ private:
};
} // namespace
static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) {
auto firstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto it) {
return isa<CXXDefaultArgExpr>(it);
});
return llvm::make_range(Args.begin(), firstDefaultArg);
}
static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) {
switch (E.getOperator()) {
// Comparison
@ -1111,7 +1118,11 @@ public:
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 @@ public:
}
}
bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; }
bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
auto Tokens = Builder.getDeclarationRange(S);
if (Tokens.front().kind() == tok::coloncolon) {

View File

@ -2733,6 +2733,54 @@ CallExpression Expression
)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 @@ SimpleDeclaration
)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 @@ ReturnStatement Statement
)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 @@ TranslationUnit Detached
)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()) {