llvm-for-llvmta/tools/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp

5767 lines
116 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===- BuildTreeTest.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file tests the syntax tree generation from the ClangAST.
//
//===----------------------------------------------------------------------===//
#include "TreeTestBase.h"
using namespace clang;
using namespace clang::syntax;
namespace {
class BuildSyntaxTreeTest : public SyntaxTreeTest {
protected:
::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
auto *Root = buildTree(Code, GetParam());
if (Diags->getClient()->getNumErrors() != 0) {
return ::testing::AssertionFailure()
<< "Source file has syntax errors, they were printed to the test "
"log";
}
auto Actual = StringRef(Root->dump(Arena->getSourceManager())).trim().str();
// EXPECT_EQ shows the diff between the two strings if they are different.
EXPECT_EQ(Tree.trim().str(), Actual);
if (Actual != Tree.trim().str()) {
return ::testing::AssertionFailure();
}
return ::testing::AssertionSuccess();
}
::testing::AssertionResult
treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations,
ArrayRef<StringRef> TreeDumps) {
SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations);
auto *Root = buildTree(AnnotatedCode.code(), GetParam());
if (Diags->getClient()->getNumErrors() != 0) {
return ::testing::AssertionFailure()
<< "Source file has syntax errors, they were printed to the test "
"log";
}
auto AnnotatedRanges = AnnotatedCode.ranges();
if (AnnotatedRanges.size() != TreeDumps.size()) {
return ::testing::AssertionFailure()
<< "The number of annotated ranges in the source code is "
"different "
"to the number of their corresponding tree dumps.";
}
bool Failed = false;
for (unsigned i = 0; i < AnnotatedRanges.size(); i++) {
auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root);
assert(AnnotatedNode);
auto AnnotatedNodeDump =
StringRef(AnnotatedNode->dump(Arena->getSourceManager()))
.trim()
.str();
// EXPECT_EQ shows the diff between the two strings if they are different.
EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump)
<< "Dumps diverged for the code:\n"
<< AnnotatedCode.code().slice(AnnotatedRanges[i].Begin,
AnnotatedRanges[i].End);
if (AnnotatedNodeDump != TreeDumps[i].trim().str())
Failed = true;
}
return Failed ? ::testing::AssertionFailure()
: ::testing::AssertionSuccess();
}
};
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(
int a;
int b = 42;
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'a'
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'b'
| |-'='
| `-IntegerLiteralExpression
| `-'42' LiteralToken
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, SimpleFunction) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void foo(int a, int b) {}
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'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
|-'{' OpenParen
`-'}' CloseParen
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Simple_BackslashInsideToken) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
in\
t a;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'in\
t'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-'a'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, If) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[if (1) {}]]
[[if (1) {} else if (0) {}]]
}
)cpp",
{R"txt(
IfStatement Statement
|-'if' IntroducerKeyword
|-'('
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-')'
`-CompoundStatement ThenStatement
|-'{' OpenParen
`-'}' CloseParen
)txt",
R"txt(
IfStatement Statement
|-'if' IntroducerKeyword
|-'('
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-')'
|-CompoundStatement ThenStatement
| |-'{' OpenParen
| `-'}' CloseParen
|-'else' ElseKeyword
`-IfStatement ElseStatement
|-'if' IntroducerKeyword
|-'('
|-IntegerLiteralExpression
| `-'0' LiteralToken
|-')'
`-CompoundStatement ThenStatement
|-'{' OpenParen
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, For) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[for (;;) {}]]
}
)cpp",
{R"txt(
ForStatement Statement
|-'for' IntroducerKeyword
|-'('
|-';'
|-';'
|-')'
`-CompoundStatement BodyStatement
|-'{' OpenParen
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, RangeBasedFor) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
int a[3];
[[for (int x : a)
;]]
}
)cpp",
{R"txt(
RangeBasedForStatement Statement
|-'for' IntroducerKeyword
|-'('
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'x'
| `-':'
|-IdExpression
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-')'
`-EmptyStatement BodyStatement
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, DeclarationStatement) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[int a = 10;]]
}
)cpp",
{R"txt(
DeclarationStatement Statement
|-SimpleDeclaration
| |-'int'
| `-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'a'
| |-'='
| `-IntegerLiteralExpression
| `-'10' LiteralToken
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, Switch) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[switch (1) {
case 0:
default:;
}]]
}
)cpp",
{R"txt(
SwitchStatement Statement
|-'switch' IntroducerKeyword
|-'('
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-')'
`-CompoundStatement BodyStatement
|-'{' OpenParen
|-CaseStatement Statement
| |-'case' IntroducerKeyword
| |-IntegerLiteralExpression CaseValue
| | `-'0' LiteralToken
| |-':'
| `-DefaultStatement BodyStatement
| |-'default' IntroducerKeyword
| |-':'
| `-EmptyStatement BodyStatement
| `-';'
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, While) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[while (1) { continue; break; }]]
}
)cpp",
{R"txt(
WhileStatement Statement
|-'while' IntroducerKeyword
|-'('
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-')'
`-CompoundStatement BodyStatement
|-'{' OpenParen
|-ContinueStatement Statement
| |-'continue' IntroducerKeyword
| `-';'
|-BreakStatement Statement
| |-'break' IntroducerKeyword
| `-';'
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnhandledStatement) {
// Unhandled statements should end up as 'unknown statement'.
// This example uses a 'label statement', which does not yet have a syntax
// counterpart.
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
int test() {
[[foo: return 100;]]
}
)cpp",
{R"txt(
UnknownStatement Statement
|-'foo'
|-':'
`-ReturnStatement
|-'return' IntroducerKeyword
|-IntegerLiteralExpression ReturnValue
| `-'100' LiteralToken
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, Expressions) {
// expressions should be wrapped in 'ExpressionStatement' when they appear
// in a statement position.
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void 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
| |-'('
| |-IntegerLiteralExpression
| | `-'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"));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Identifier) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a) {
[[a]];
}
)cpp",
{R"txt(
IdExpression Expression
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_OperatorFunctionId) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
friend X operator+(const X&, const X&);
};
void test(X x) {
[[operator+(x, x)]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| |-'operator'
| `-'+'
|-'(' OpenParen
|-CallArguments Arguments
| |-IdExpression ListElement
| | `-UnqualifiedId UnqualifiedId
| | `-'x'
| |-',' ListDelimiter
| `-IdExpression ListElement
| `-UnqualifiedId UnqualifiedId
| `-'x'
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_ConversionFunctionId) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
operator int();
};
void test(X x) {
[[x.operator int()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'x'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| |-'operator'
| `-'int'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_LiteralOperatorId) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
unsigned operator "" _w(char);
void test() {
[[operator "" _w('1')]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| |-'operator'
| |-'""'
| `-'_w'
|-'(' OpenParen
|-CallArguments Arguments
| `-CharacterLiteralExpression ListElement
| `-''1'' LiteralToken
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Destructor) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X { };
void test(X x) {
[[x.~X()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'x'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| |-'~'
| `-'X'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_DecltypeDestructor) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X { };
void test(X x) {
// FIXME: Make `decltype(x)` a child of `MemberExpression`. It is currently
// not because `Expr::getSourceRange()` returns the range of `x.~` for the
// `MemberExpr` instead of the expected `x.~decltype(x)`, this is a bug in
// clang.
[[x.~decltype(x)()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'x'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| `-'~'
|-'decltype'
|-'('
|-'x'
|-')'
|-'('
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UnqualifiedId_TemplateId) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T>
T f();
void test() {
[[f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_NamespaceSpecifier) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
namespace n {
struct S { };
}
void test() {
[[::n::S s1]];
[[n::S s2]];
}
)cpp",
{R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-'::' ListDelimiter
| |-IdentifierNameSpecifier ListElement
| | `-'n'
| `-'::' ListDelimiter
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-'s1'
)txt",
R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-IdentifierNameSpecifier ListElement
| | `-'n'
| `-'::' ListDelimiter
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-'s2'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_TemplateSpecifier) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T>
struct ST {
struct S { };
};
void test() {
[[::template ST<int>::S s1]];
[[::ST<int>::S s2]];
}
)cpp",
{R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-'::' ListDelimiter
| |-SimpleTemplateNameSpecifier ListElement
| | |-'template'
| | |-'ST'
| | |-'<'
| | |-'int'
| | `-'>'
| `-'::' ListDelimiter
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-'s1'
)txt",
R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-'::' ListDelimiter
| |-SimpleTemplateNameSpecifier ListElement
| | |-'ST'
| | |-'<'
| | |-'int'
| | `-'>'
| `-'::' ListDelimiter
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-'s2'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_DecltypeSpecifier) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
static void f(){}
};
void test(S s) {
[[decltype(s)::f()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-DecltypeNameSpecifier ListElement
| | | |-'decltype'
| | | |-'('
| | | |-IdExpression
| | | | `-UnqualifiedId UnqualifiedId
| | | | `-'s'
| | | `-')'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_OptionalTemplateKw) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
template<typename U>
static U f();
};
void test() {
[[S::f<int>()]];
[[S::template f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'S'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'S'
| | `-'::' ListDelimiter
| |-'template' TemplateKeyword
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_Complex) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
namespace n {
template<typename T>
struct ST {
template<typename U>
static U f();
};
}
void test() {
[[::n::template ST<int>::template f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-'::' ListDelimiter
| | |-IdentifierNameSpecifier ListElement
| | | `-'n'
| | |-'::' ListDelimiter
| | |-SimpleTemplateNameSpecifier ListElement
| | | |-'template'
| | | |-'ST'
| | | |-'<'
| | | |-'int'
| | | `-'>'
| | `-'::' ListDelimiter
| |-'template' TemplateKeyword
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, QualifiedId_DependentType) {
if (!GetParam().isCXX()) {
return;
}
if (GetParam().hasDelayedTemplateParsing()) {
// FIXME: Make this test work on Windows by generating the expected syntax
// tree when `-fdelayed-template-parsing` is active.
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <typename T>
void test() {
[[T::template U<int>::f()]];
[[T::U::f()]];
[[T::template f<0>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'T'
| | |-'::' ListDelimiter
| | |-SimpleTemplateNameSpecifier ListElement
| | | |-'template'
| | | |-'U'
| | | |-'<'
| | | |-'int'
| | | `-'>'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'T'
| | |-'::' ListDelimiter
| | |-IdentifierNameSpecifier ListElement
| | | `-'U'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-IdExpression Callee
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'T'
| | `-'::' ListDelimiter
| |-'template' TemplateKeyword
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-IntegerLiteralExpression
| | `-'0' LiteralToken
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, This_Simple) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
S* test(){
return [[this]];
}
};
)cpp",
{R"txt(
ThisExpression ReturnValue
`-'this' IntroducerKeyword
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, This_ExplicitMemberAccess) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
int a;
void test(){
[[this->a]];
}
};
)cpp",
{R"txt(
MemberExpression Expression
|-ThisExpression Object
| `-'this' IntroducerKeyword
|-'->' AccessToken
`-IdExpression Member
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, This_ImplicitMemberAccess) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
int a;
void test(){
[[a]];
}
};
)cpp",
{R"txt(
IdExpression Expression
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ParenExpr) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[(1)]];
[[((1))]];
[[(1 + (2))]];
}
)cpp",
{R"txt(
ParenExpression Expression
|-'(' OpenParen
|-IntegerLiteralExpression SubExpression
| `-'1' LiteralToken
`-')' CloseParen
)txt",
R"txt(
ParenExpression Expression
|-'(' OpenParen
|-ParenExpression SubExpression
| |-'(' OpenParen
| |-IntegerLiteralExpression SubExpression
| | `-'1' LiteralToken
| `-')' CloseParen
`-')' CloseParen
)txt",
R"txt(
ParenExpression Expression
|-'(' OpenParen
|-BinaryOperatorExpression SubExpression
| |-IntegerLiteralExpression LeftHandSide
| | `-'1' LiteralToken
| |-'+' OperatorToken
| `-ParenExpression RightHandSide
| |-'(' OpenParen
| |-IntegerLiteralExpression SubExpression
| | `-'2' LiteralToken
| `-')' CloseParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Char) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
unsigned operator "" _c(char);
void test() {
[['2'_c]];
}
)cpp",
{R"txt(
CharUserDefinedLiteralExpression Expression
`-''2'_c' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_String) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
typedef decltype(sizeof(void *)) size_t;
unsigned operator "" _s(const char*, size_t);
void test() {
[["12"_s]];
}
)cpp",
{R"txt(
StringUserDefinedLiteralExpression Expression
`-'"12"_s' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Integer) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
unsigned operator "" _i(unsigned long long);
unsigned operator "" _r(const char*);
template <char...>
unsigned operator "" _t();
void test() {
[[12_i]];
[[12_r]];
[[12_t]];
}
)cpp",
{R"txt(
IntegerUserDefinedLiteralExpression Expression
`-'12_i' LiteralToken
)txt",
R"txt(
IntegerUserDefinedLiteralExpression Expression
`-'12_r' LiteralToken
)txt",
R"txt(
IntegerUserDefinedLiteralExpression Expression
`-'12_t' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Float) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
unsigned operator "" _f(long double);
unsigned operator "" _r(const char*);
template <char...>
unsigned operator "" _t();
void test() {
[[1.2_f]];
[[1.2_r]];
[[1.2_t]];
}
)cpp",
{R"txt(
FloatUserDefinedLiteralExpression Expression
`-'1.2_f' LiteralToken
)txt",
R"txt(
FloatUserDefinedLiteralExpression Expression
`-'1.2_r' LiteralToken
)txt",
R"txt(
FloatUserDefinedLiteralExpression Expression
`-'1.2_t' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, IntegerLiteral_LongLong) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[12ll]];
[[12ull]];
}
)cpp",
{R"txt(
IntegerLiteralExpression Expression
`-'12ll' LiteralToken
)txt",
R"txt(
IntegerLiteralExpression Expression
`-'12ull' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, IntegerLiteral_Binary) {
if (!GetParam().isCXX14OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[0b1100]];
}
)cpp",
{R"txt(
IntegerLiteralExpression Expression
`-'0b1100' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, IntegerLiteral_WithDigitSeparators) {
if (!GetParam().isCXX14OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[1'2'0ull]];
}
)cpp",
{R"txt(
IntegerLiteralExpression Expression
`-'1'2'0ull' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CharacterLiteral) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[['a']];
[['\n']];
[['\x20']];
[['\0']];
[[L'a']];
[[L'α']];
}
)cpp",
{R"txt(
CharacterLiteralExpression Expression
`-''a'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-''\n'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-''\x20'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-''\0'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'L'a'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'L'α'' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[u'a']];
[[u'構']];
[[U'a']];
[[U'🌲']];
}
)cpp",
{R"txt(
CharacterLiteralExpression Expression
`-'u'a'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'u''' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'U'a'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'U'🌲'' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf8) {
if (!GetParam().isCXX17OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[u8'a']];
[[u8'\x7f']];
}
)cpp",
{R"txt(
CharacterLiteralExpression Expression
`-'u8'a'' LiteralToken
)txt",
R"txt(
CharacterLiteralExpression Expression
`-'u8'\x7f'' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, FloatingLiteral) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[1e-2]];
[[2.]];
[[.2]];
[[2.f]];
}
)cpp",
{R"txt(
FloatingLiteralExpression Expression
`-'1e-2' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'2.' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'.2' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'2.f' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, FloatingLiteral_Hexadecimal) {
if (!GetParam().isCXX17OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[0xfp1]];
[[0xf.p1]];
[[0x.fp1]];
[[0xf.fp1f]];
}
)cpp",
{R"txt(
FloatingLiteralExpression Expression
`-'0xfp1' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'0xf.p1' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'0x.fp1' LiteralToken
)txt",
R"txt(
FloatingLiteralExpression Expression
`-'0xf.fp1f' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, StringLiteral) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[["a\n\0\x20"]];
[[L"αβ"]];
}
)cpp",
{R"txt(
StringLiteralExpression Expression
`-'"a\n\0\x20"' LiteralToken
)txt",
R"txt(
StringLiteralExpression Expression
`-'L"αβ"' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, StringLiteral_Utf) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[u8"a\x1f\x05"]];
[[u"C++抽象構文木"]];
[[U"📖🌲\n"]];
}
)cpp",
{R"txt(
StringLiteralExpression Expression
`-'u8"a\x1f\x05"' LiteralToken
)txt",
R"txt(
StringLiteralExpression Expression
`-'u"C++抽象構文木"' LiteralToken
)txt",
R"txt(
StringLiteralExpression Expression
`-'U"📖🌲\n"' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, StringLiteral_Raw) {
if (!GetParam().isCXX11OrLater()) {
return;
}
// This test uses regular string literals instead of raw string literals to
// 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( //
"void test() {\n"
" R\"SyntaxTree(\n"
" Hello \"Syntax\" \\\"\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"));
}
TEST_P(BuildSyntaxTreeTest, BoolLiteral) {
if (GetParam().isC()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[true]];
[[false]];
}
)cpp",
{R"txt(
BoolLiteralExpression Expression
`-'true' LiteralToken
)txt",
R"txt(
BoolLiteralExpression Expression
`-'false' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CxxNullPtrLiteral) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[nullptr]];
}
)cpp",
{R"txt(
CxxNullPtrExpression Expression
`-'nullptr' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, PostfixUnaryOperator) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a) {
[[a++]];
[[a--]];
}
)cpp",
{R"txt(
PostfixUnaryOperatorExpression Expression
|-IdExpression Operand
| `-UnqualifiedId UnqualifiedId
| `-'a'
`-'++' OperatorToken
)txt",
R"txt(
PostfixUnaryOperatorExpression Expression
|-IdExpression Operand
| `-UnqualifiedId UnqualifiedId
| `-'a'
`-'--' OperatorToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperator) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a, int *ap) {
[[--a]]; [[++a]];
[[~a]];
[[-a]];
[[+a]];
[[&a]];
[[*ap]];
[[!a]];
[[__real a]]; [[__imag a]];
}
)cpp",
{R"txt(
PrefixUnaryOperatorExpression Expression
|-'--' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'++' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'~' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'-' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'+' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'&' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'*' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'ap'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'!' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'__real' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'__imag' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperatorCxx) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a, bool b) {
[[compl a]];
[[not b]];
}
)cpp",
{R"txt(
PrefixUnaryOperatorExpression Expression
|-'compl' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'a'
)txt",
R"txt(
PrefixUnaryOperatorExpression Expression
|-'not' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'b'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, BinaryOperator) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a) {
[[1 - 2]];
[[1 == 2]];
[[a = 1]];
[[a <<= 1]];
[[1 || 0]];
[[1 & 2]];
[[a != 3]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IntegerLiteralExpression LeftHandSide
| `-'1' LiteralToken
|-'-' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'2' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IntegerLiteralExpression LeftHandSide
| `-'1' LiteralToken
|-'==' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'2' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-'=' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'1' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-'<<=' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'1' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IntegerLiteralExpression LeftHandSide
| `-'1' LiteralToken
|-'||' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'0' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IntegerLiteralExpression LeftHandSide
| `-'1' LiteralToken
|-'&' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'2' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-'!=' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'3' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, BinaryOperatorCxx) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a) {
[[true || false]];
[[true or false]];
[[1 bitand 2]];
[[a xor_eq 3]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-BoolLiteralExpression LeftHandSide
| `-'true' LiteralToken
|-'||' OperatorToken
`-BoolLiteralExpression RightHandSide
`-'false' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-BoolLiteralExpression LeftHandSide
| `-'true' LiteralToken
|-'or' OperatorToken
`-BoolLiteralExpression RightHandSide
`-'false' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IntegerLiteralExpression LeftHandSide
| `-'1' LiteralToken
|-'bitand' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'2' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-'xor_eq' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'3' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, BinaryOperator_NestedWithParenthesis) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[(1 + 2) * (4 / 2)]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-ParenExpression LeftHandSide
| |-'(' OpenParen
| |-BinaryOperatorExpression SubExpression
| | |-IntegerLiteralExpression LeftHandSide
| | | `-'1' LiteralToken
| | |-'+' OperatorToken
| | `-IntegerLiteralExpression RightHandSide
| | `-'2' LiteralToken
| `-')' CloseParen
|-'*' OperatorToken
`-ParenExpression RightHandSide
|-'(' OpenParen
|-BinaryOperatorExpression SubExpression
| |-IntegerLiteralExpression LeftHandSide
| | `-'4' LiteralToken
| |-'/' OperatorToken
| `-IntegerLiteralExpression RightHandSide
| `-'2' LiteralToken
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, BinaryOperator_Associativity) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test(int a, int b) {
[[a + b + 42]];
[[a = b = 42]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-BinaryOperatorExpression LeftHandSide
| |-IdExpression LeftHandSide
| | `-UnqualifiedId UnqualifiedId
| | `-'a'
| |-'+' OperatorToken
| `-IdExpression RightHandSide
| `-UnqualifiedId UnqualifiedId
| `-'b'
|-'+' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'42' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'a'
|-'=' OperatorToken
`-BinaryOperatorExpression RightHandSide
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'b'
|-'=' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'42' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, BinaryOperator_Precedence) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void test() {
[[1 + 2 * 3 + 4]];
[[1 % 2 + 3 * 4]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-BinaryOperatorExpression LeftHandSide
| |-IntegerLiteralExpression LeftHandSide
| | `-'1' LiteralToken
| |-'+' OperatorToken
| `-BinaryOperatorExpression RightHandSide
| |-IntegerLiteralExpression LeftHandSide
| | `-'2' LiteralToken
| |-'*' OperatorToken
| `-IntegerLiteralExpression RightHandSide
| `-'3' LiteralToken
|-'+' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'4' LiteralToken
)txt",
R"txt(
BinaryOperatorExpression Expression
|-BinaryOperatorExpression LeftHandSide
| |-IntegerLiteralExpression LeftHandSide
| | `-'1' LiteralToken
| |-'%' OperatorToken
| `-IntegerLiteralExpression RightHandSide
| `-'2' LiteralToken
|-'+' OperatorToken
`-BinaryOperatorExpression RightHandSide
|-IntegerLiteralExpression LeftHandSide
| `-'3' LiteralToken
|-'*' OperatorToken
`-IntegerLiteralExpression RightHandSide
`-'4' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Assignment) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X& operator=(const X&);
};
void test(X x, X y) {
[[x = y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-'=' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'y'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Plus) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
friend X operator+(X, const X&);
};
void test(X x, X y) {
[[x + y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-'+' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'y'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Less) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
friend bool operator<(const X&, const X&);
};
void test(X x, X y) {
[[x < y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-'<' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'y'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_LeftShift) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
friend X operator<<(X&, const X&);
};
void test(X x, X y) {
[[x << y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-'<<' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'y'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Comma) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X operator,(X&);
};
void test(X x, X y) {
[[x, y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-',' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'y'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PointerToMember) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X operator->*(int);
};
void test(X* xp, int X::* pmi) {
[[xp->*pmi]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
|-IdExpression LeftHandSide
| `-UnqualifiedId UnqualifiedId
| `-'xp'
|-'->*' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
`-'pmi'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Negation) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
bool operator!();
};
void test(X x) {
[[!x]];
}
)cpp",
{R"txt(
PrefixUnaryOperatorExpression Expression
|-'!' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'x'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_AddressOf) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X* operator&();
};
void test(X x) {
[[&x]];
}
)cpp",
{R"txt(
PrefixUnaryOperatorExpression Expression
|-'&' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'x'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PrefixIncrement) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X operator++();
};
void test(X x) {
[[++x]];
}
)cpp",
{R"txt(
PrefixUnaryOperatorExpression Expression
|-'++' OperatorToken
`-IdExpression Operand
`-UnqualifiedId UnqualifiedId
`-'x'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PostfixIncrement) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X operator++(int);
};
void test(X x) {
[[x++]];
}
)cpp",
{R"txt(
PostfixUnaryOperatorExpression Expression
|-IdExpression Operand
| `-UnqualifiedId UnqualifiedId
| `-'x'
`-'++' OperatorToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithDot) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
int a;
};
void test(struct S s) {
[[s.a]];
}
)cpp",
{R"txt(
MemberExpression Expression
|-IdExpression Object
| `-UnqualifiedId UnqualifiedId
| `-'s'
|-'.' AccessToken
`-IdExpression Member
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_StaticDataMember) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
static int a;
};
void test(S s) {
[[s.a]];
}
)cpp",
{R"txt(
MemberExpression Expression
|-IdExpression Object
| `-UnqualifiedId UnqualifiedId
| `-'s'
|-'.' AccessToken
`-IdExpression Member
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithArrow) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
int a;
};
void test(struct S* sp) {
[[sp->a]];
}
)cpp",
{R"txt(
MemberExpression Expression
|-IdExpression Object
| `-UnqualifiedId UnqualifiedId
| `-'sp'
|-'->' AccessToken
`-IdExpression Member
`-UnqualifiedId UnqualifiedId
`-'a'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_Chaining) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
struct S* next;
};
void test(struct S s){
[[s.next->next]];
}
)cpp",
{R"txt(
MemberExpression Expression
|-MemberExpression Object
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| `-'next'
|-'->' AccessToken
`-IdExpression Member
`-UnqualifiedId UnqualifiedId
`-'next'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_OperatorFunction) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
bool operator!();
};
void test(S s) {
[[s.operator!()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| |-'operator'
| `-'!'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_VariableTemplate) {
if (!GetParam().isCXX14OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
template<typename T>
static constexpr T x = 42;
};
// FIXME: `<int>` should be a child of `MemberExpression` and `;` of
// `ExpressionStatement`. This is a bug in clang, in `getSourceRange` methods.
void test(S s) [[{
s.x<int>;
}]]
)cpp",
{R"txt(
CompoundStatement
|-'{' OpenParen
|-ExpressionStatement Statement
| `-MemberExpression Expression
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| `-'x'
|-'<'
|-'int'
|-'>'
|-';'
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_FunctionTemplate) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
template<typename T>
T f();
};
void test(S* sp){
[[sp->f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'sp'
| |-'->' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
MemberExpression_FunctionTemplateWithTemplateKeyword) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
template<typename T>
T f();
};
void test(S s){
[[s.template f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| |-'template'
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_WithQualifier) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct Base {
void f();
};
struct S : public Base {};
void test(S s){
[[s.Base::f()]];
[[s.::S::~S()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'Base'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| |-NestedNameSpecifier Qualifier
| | |-'::' ListDelimiter
| | |-IdentifierNameSpecifier ListElement
| | | `-'S'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| |-'~'
| `-'S'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberExpression_Complex) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T>
struct U {
template<typename U>
U f();
};
struct S {
U<int> getU();
};
void test(S* sp) {
// FIXME: The first 'template' keyword is a child of `NestedNameSpecifier`,
// but it should be a child of `MemberExpression` according to the grammar.
// However one might argue that the 'template' keyword fits better inside
// `NestedNameSpecifier` because if we change `U<int>` to `UI` we would like
// equally to change the `NameSpecifier` `template U<int>` to just `UI`.
[[sp->getU().template U<int>::template f<int>()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-CallExpression Object
| | |-MemberExpression Callee
| | | |-IdExpression Object
| | | | `-UnqualifiedId UnqualifiedId
| | | | `-'sp'
| | | |-'->' AccessToken
| | | `-IdExpression Member
| | | `-UnqualifiedId UnqualifiedId
| | | `-'getU'
| | |-'(' OpenParen
| | `-')' CloseParen
| |-'.' AccessToken
| `-IdExpression Member
| |-NestedNameSpecifier Qualifier
| | |-SimpleTemplateNameSpecifier ListElement
| | | |-'template'
| | | |-'U'
| | | |-'<'
| | | |-'int'
| | | `-'>'
| | `-'::' ListDelimiter
| |-'template' TemplateKeyword
| `-UnqualifiedId UnqualifiedId
| |-'f'
| |-'<'
| |-'int'
| `-'>'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_Member) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S{
void f();
};
void test(S s) {
[[s.f()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-IdExpression Object
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'.' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParens) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
void operator()();
};
void test(S s) {
[[s()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| `-'s'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParensChaining) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
S operator()();
};
void test(S s) {
[[s()()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-CallExpression Callee
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'s'
| |-'(' OpenParen
| `-')' CloseParen
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberWithThis) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct Base {
void f();
};
struct S: public Base {
void f();
void test() {
[[this->f()]];
[[f()]];
[[this->Base::f()]];
}
};
)cpp",
{R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-ThisExpression Object
| | `-'this' IntroducerKeyword
| |-'->' AccessToken
| `-IdExpression Member
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-MemberExpression Callee
| |-ThisExpression Object
| | `-'this' IntroducerKeyword
| |-'->' AccessToken
| `-IdExpression Member
| |-NestedNameSpecifier Qualifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'Base'
| | `-'::' ListDelimiter
| `-UnqualifiedId UnqualifiedId
| `-'f'
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_FunctionPointer) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void (*pf)();
void test() {
[[pf()]];
[[(*pf)()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| `-'pf'
|-'(' OpenParen
`-')' CloseParen
)txt",
R"txt(
CallExpression Expression
|-ParenExpression Callee
| |-'(' OpenParen
| |-PrefixUnaryOperatorExpression SubExpression
| | |-'*' OperatorToken
| | `-IdExpression Operand
| | `-UnqualifiedId UnqualifiedId
| | `-'pf'
| `-')' CloseParen
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberFunctionPointer) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
void f();
};
void test(S s) {
void (S::*pmf)();
pmf = &S::f;
[[(s.*pmf)()]];
}
)cpp",
{R"txt(
CallExpression Expression
|-ParenExpression Callee
| |-'(' OpenParen
| |-BinaryOperatorExpression SubExpression
| | |-IdExpression LeftHandSide
| | | `-UnqualifiedId UnqualifiedId
| | | `-'s'
| | |-'.*' OperatorToken
| | `-IdExpression RightHandSide
| | `-UnqualifiedId UnqualifiedId
| | `-'pmf'
| `-')' CloseParen
|-'(' OpenParen
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Zero) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void f();
void test() {
[[f();]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_One) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void f(int);
void test() {
[[f(1);]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | `-IntegerLiteralExpression ListElement
| | `-'1' LiteralToken
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Multiple) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void f(int, char, float);
void test() {
[[f(1, '2', 3.);]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | |-IntegerLiteralExpression ListElement
| | | `-'1' LiteralToken
| | |-',' ListDelimiter
| | |-CharacterLiteralExpression ListElement
| | | `-''2'' LiteralToken
| | |-',' ListDelimiter
| | `-FloatingLiteralExpression ListElement
| | `-'3.' LiteralToken
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Assignment) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void f(int);
void test(int a) {
[[f(a = 1);]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | `-BinaryOperatorExpression ListElement
| | |-IdExpression LeftHandSide
| | | `-UnqualifiedId UnqualifiedId
| | | `-'a'
| | |-'=' OperatorToken
| | `-IntegerLiteralExpression RightHandSide
| | `-'1' LiteralToken
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Empty) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
void f(int[]);
void test() {
[[f({});]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | `-UnknownExpression ListElement
| | `-UnknownExpression
| | |-'{'
| | `-'}'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Simple) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct TT {};
struct T{
int a;
TT b;
};
void f(T);
void test() {
[[f({1, {}});]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | `-UnknownExpression ListElement
| | `-UnknownExpression
| | |-'{'
| | |-IntegerLiteralExpression
| | | `-'1' LiteralToken
| | |-','
| | |-UnknownExpression
| | | `-UnknownExpression
| | | |-'{'
| | | `-'}'
| | `-'}'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
CallExpression_Arguments_BracedInitList_Designated) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct TT {};
struct T{
int a;
TT b;
};
void f(T);
void test() {
[[f({.a = 1, .b {}});]]
}
)cpp",
{R"txt(
ExpressionStatement Statement
|-CallExpression Expression
| |-IdExpression Callee
| | `-UnqualifiedId UnqualifiedId
| | `-'f'
| |-'(' OpenParen
| |-CallArguments Arguments
| | `-UnknownExpression ListElement
| | `-UnknownExpression
| | |-'{'
| | |-UnknownExpression
| | | |-'.'
| | | |-'a'
| | | |-'='
| | | `-IntegerLiteralExpression
| | | `-'1' LiteralToken
| | |-','
| | |-UnknownExpression
| | | |-'.'
| | | |-'b'
| | | `-UnknownExpression
| | | `-UnknownExpression
| | | |-'{'
| | | `-'}'
| | `-'}'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_ParameterPack) {
if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T, typename... Args>
void test(T t, Args... args) {
[[test(args...)]];
}
)cpp",
{R"txt(
CallExpression Expression
|-UnknownExpression Callee
| `-'test'
|-'(' OpenParen
|-CallArguments Arguments
| `-UnknownExpression ListElement
| |-IdExpression
| | `-UnqualifiedId UnqualifiedId
| | `-'args'
| `-'...'
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, 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(BuildSyntaxTreeTest, MultipleDeclaratorsGrouping) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int *a, b;
int *c, d;
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | |-SimpleDeclarator ListElement
| | | |-'*'
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclarator ListElement
| | `-'b'
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| |-SimpleDeclarator ListElement
| | |-'*'
| | `-'c'
| |-',' ListDelimiter
| `-SimpleDeclarator ListElement
| `-'d'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
typedef int *a, b;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'typedef'
|-'int'
|-DeclaratorList Declarators
| |-SimpleDeclarator ListElement
| | |-'*'
| | `-'a'
| |-',' ListDelimiter
| `-SimpleDeclarator ListElement
| `-'b'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void foo() {
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"));
}
TEST_P(BuildSyntaxTreeTest, SizeTTypedef) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
typedef decltype(sizeof(void *)) size_t;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'typedef'
|-'decltype'
|-'('
|-UnknownExpression
| |-'sizeof'
| |-'('
| |-'void'
| |-'*'
| `-')'
|-')'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-'size_t'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Namespace_Nested) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
namespace a { namespace b {} }
)cpp",
R"txt(
TranslationUnit Detached
`-NamespaceDefinition
|-'namespace'
|-'a'
|-'{'
|-NamespaceDefinition
| |-'namespace'
| |-'b'
| |-'{'
| `-'}'
`-'}'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Namespace_NestedDefinition) {
if (!GetParam().isCXX17OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
namespace a::b {}
)cpp",
R"txt(
TranslationUnit Detached
`-NamespaceDefinition
|-'namespace'
|-'a'
|-'::'
|-'b'
|-'{'
`-'}'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Namespace_Unnamed) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
namespace {}
)cpp",
R"txt(
TranslationUnit Detached
`-NamespaceDefinition
|-'namespace'
|-'{'
`-'}'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Namespace_Alias) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
namespace a {}
[[namespace foo = a;]]
)cpp",
{R"txt(
NamespaceAliasDefinition
|-'namespace'
|-'foo'
|-'='
|-'a'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UsingDirective) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
namespace ns {}
[[using namespace ::ns;]]
)cpp",
{R"txt(
UsingNamespaceDirective
|-'using'
|-'namespace'
|-NestedNameSpecifier
| `-'::' ListDelimiter
|-'ns'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UsingDeclaration_Namespace) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
namespace ns { int a; }
[[using ns::a;]]
)cpp",
{R"txt(
UsingDeclaration
|-'using'
|-NestedNameSpecifier
| |-IdentifierNameSpecifier ListElement
| | `-'ns'
| `-'::' ListDelimiter
|-'a'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UsingDeclaration_ClassMember) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X {
[[using T::foo;]]
[[using typename T::bar;]]
};
)cpp",
{R"txt(
UsingDeclaration
|-'using'
|-NestedNameSpecifier
| |-IdentifierNameSpecifier ListElement
| | `-'T'
| `-'::' ListDelimiter
|-'foo'
`-';'
)txt",
R"txt(
UsingDeclaration
|-'using'
|-'typename'
|-NestedNameSpecifier
| |-IdentifierNameSpecifier ListElement
| | `-'T'
| `-'::' ListDelimiter
|-'bar'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, UsingTypeAlias) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
using type = int;
)cpp",
R"txt(
TranslationUnit Detached
`-TypeAliasDeclaration
|-'using'
|-'type'
|-'='
|-'int'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, FreeStandingClass_ForwardDeclaration) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
[[struct X;]]
[[struct Y *y1;]]
)cpp",
{R"txt(
SimpleDeclaration
|-'struct'
|-'X'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'struct'
|-'Y'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| `-'y1'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, FreeStandingClasses_Definition) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
[[struct X {};]]
[[struct Y {} *y2;]]
[[struct {} *a1;]]
)cpp",
{R"txt(
SimpleDeclaration
|-'struct'
|-'X'
|-'{'
|-'}'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'struct'
|-'Y'
|-'{'
|-'}'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| `-'y2'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'struct'
|-'{'
|-'}'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| `-'a1'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, StaticMemberFunction) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
[[static void f(){}]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-'static'
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OutOfLineMemberFunctionDefinition) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
void f();
};
[[void S::f(){}]]
)cpp",
{R"txt(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-NestedNameSpecifier
| | |-IdentifierNameSpecifier ListElement
| | | `-'S'
| | `-'::' ListDelimiter
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ConversionMemberFunction) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
[[operator int();]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'operator'
| |-'int'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, LiteralOperatorDeclaration) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
unsigned operator "" _c(char);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'unsigned'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'operator'
| |-'""'
| |-'_c'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | `-'char'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
template <char...>
unsigned operator "" _t();
)cpp",
R"txt(
TranslationUnit Detached
`-TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-SimpleDeclaration
| `-'char'
|-'...'
|-'>'
`-SimpleDeclaration
|-'unsigned'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'operator'
| |-'""'
| |-'_t'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperatorDeclaration) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
[[X& operator=(const X&);]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-'X'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'&'
| |-'operator'
| |-'='
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'X'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'&'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
[[friend X operator+(X, const X&);]]
};
)cpp",
{R"txt(
UnknownDeclaration
`-SimpleDeclaration
|-'friend'
|-'X'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'operator'
| |-'+'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | `-'X'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'X'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'&'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ClassTemplateDeclaration) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
template<typename T>
struct ST {};
)cpp",
R"txt(
TranslationUnit Detached
`-TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'typename'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'struct'
|-'ST'
|-'{'
|-'}'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, FunctionTemplateDeclaration) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
template<typename T>
T f();
)cpp",
R"txt(
TranslationUnit Detached
`-TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'typename'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'T'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, VariableTemplateDeclaration) {
if (!GetParam().isCXX14OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
template <class T> T var = 10;
)cpp",
R"txt(
TranslationUnit Detached
`-TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'class'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'T'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'var'
| |-'='
| `-IntegerLiteralExpression
| `-'10' LiteralToken
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, StaticMemberFunctionTemplate) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
[[template<typename U>
static U f();]]
};
)cpp",
{R"txt(
TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'typename'
| `-'U'
|-'>'
`-SimpleDeclaration
|-'static'
|-'U'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, NestedTemplates) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
template <class T>
struct X {
template <class U>
U foo();
};
)cpp",
R"txt(
TranslationUnit Detached
`-TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'class'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'struct'
|-'X'
|-'{'
|-TemplateDeclaration Declaration
| |-'template' IntroducerKeyword
| |-'<'
| |-UnknownDeclaration
| | |-'class'
| | `-'U'
| |-'>'
| `-SimpleDeclaration
| |-'U'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'foo'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | `-')' CloseParen
| `-';'
|-'}'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, NestedTemplatesInNamespace) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
namespace n {
template<typename T>
struct ST {
template<typename U>
static U f();
};
}
)cpp",
R"txt(
TranslationUnit Detached
`-NamespaceDefinition
|-'namespace'
|-'n'
|-'{'
|-TemplateDeclaration Declaration
| |-'template' IntroducerKeyword
| |-'<'
| |-UnknownDeclaration
| | |-'typename'
| | `-'T'
| |-'>'
| `-SimpleDeclaration
| |-'struct'
| |-'ST'
| |-'{'
| |-TemplateDeclaration Declaration
| | |-'template' IntroducerKeyword
| | |-'<'
| | |-UnknownDeclaration
| | | |-'typename'
| | | `-'U'
| | |-'>'
| | `-SimpleDeclaration
| | |-'static'
| | |-'U'
| | |-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | |-'f'
| | | `-ParametersAndQualifiers
| | | |-'(' OpenParen
| | | `-')' CloseParen
| | `-';'
| |-'}'
| `-';'
`-'}'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X { struct Y; };
[[template <class T> struct X<T>::Y {};]]
)cpp",
{R"txt(
TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'class'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'struct'
|-NestedNameSpecifier
| |-SimpleTemplateNameSpecifier ListElement
| | |-'X'
| | |-'<'
| | |-'T'
| | `-'>'
| `-'::' ListDelimiter
|-'Y'
|-'{'
|-'}'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Definition) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X {};
[[template struct X<double>;]]
)cpp",
{R"txt(
ExplicitTemplateInstantiation
|-'template' IntroducerKeyword
`-SimpleDeclaration Declaration
|-'struct'
|-'X'
|-'<'
|-'double'
|-'>'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Declaration) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X {};
[[extern template struct X<float>;]]
)cpp",
{R"txt(
ExplicitTemplateInstantiation
|-'extern' ExternKeyword
|-'template' IntroducerKeyword
`-SimpleDeclaration Declaration
|-'struct'
|-'X'
|-'<'
|-'float'
|-'>'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Partial) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X {};
[[template <class T> struct X<T*> {};]]
)cpp",
{R"txt(
TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-UnknownDeclaration
| |-'class'
| `-'T'
|-'>'
`-SimpleDeclaration
|-'struct'
|-'X'
|-'<'
|-'T'
|-'*'
|-'>'
|-'{'
|-'}'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Full) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template <class T> struct X {};
[[template <> struct X<int> {};]]
)cpp",
{R"txt(
TemplateDeclaration Declaration
|-'template' IntroducerKeyword
|-'<'
|-'>'
`-SimpleDeclaration
|-'struct'
|-'X'
|-'<'
|-'int'
|-'>'
|-'{'
|-'}'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, EmptyDeclaration) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
;
)cpp",
R"txt(
TranslationUnit Detached
`-EmptyDeclaration
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, StaticAssert) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
static_assert(true, "message");
)cpp",
R"txt(
TranslationUnit Detached
`-StaticAssertDeclaration
|-'static_assert'
|-'('
|-BoolLiteralExpression Condition
| `-'true' LiteralToken
|-','
|-StringLiteralExpression Message
| `-'"message"' LiteralToken
|-')'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, StaticAssert_WithoutMessage) {
if (!GetParam().isCXX17OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
static_assert(true);
)cpp",
R"txt(
TranslationUnit Detached
`-StaticAssertDeclaration
|-'static_assert'
|-'('
|-BoolLiteralExpression Condition
| `-'true' LiteralToken
|-')'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ExternC) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
extern "C" int a;
extern "C" { int b; int c; }
)cpp",
R"txt(
TranslationUnit Detached
|-LinkageSpecificationDeclaration
| |-'extern'
| |-'"C"'
| `-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'a'
| `-';'
`-LinkageSpecificationDeclaration
|-'extern'
|-'"C"'
|-'{'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'b'
| `-';'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'c'
| `-';'
`-'}'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_Leaf) {
// All nodes can be mutated.
EXPECT_TRUE(treeDumpEqual(
R"cpp(
#define OPEN {
#define CLOSE }
void test() {
OPEN
1;
CLOSE
OPEN
2;
}
}
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
|-CompoundStatement Statement
| |-'{' OpenParen
| |-ExpressionStatement Statement
| | |-IntegerLiteralExpression Expression
| | | `-'1' LiteralToken
| | `-';'
| `-'}' CloseParen
|-CompoundStatement Statement
| |-'{' OpenParen
| |-ExpressionStatement Statement
| | |-IntegerLiteralExpression Expression
| | | `-'2' LiteralToken
| | `-';'
| `-'}' CloseParen
`-'}' CloseParen
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MatchTree) {
// Some nodes are unmodifiable, they are marked with 'unmodifiable'.
EXPECT_TRUE(treeDumpEqual(
R"cpp(
#define BRACES {}
void test() BRACES
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen unmodifiable
`-'}' CloseParen unmodifiable
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MismatchTree) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
#define HALF_IF if (1+
#define HALF_IF_2 1) {}
void test() {
HALF_IF HALF_IF_2 else {}
})cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
|-IfStatement Statement
| |-'if' IntroducerKeyword unmodifiable
| |-'(' unmodifiable
| |-BinaryOperatorExpression unmodifiable
| | |-IntegerLiteralExpression LeftHandSide unmodifiable
| | | `-'1' LiteralToken unmodifiable
| | |-'+' OperatorToken unmodifiable
| | `-IntegerLiteralExpression RightHandSide unmodifiable
| | `-'1' LiteralToken unmodifiable
| |-')' unmodifiable
| |-CompoundStatement ThenStatement unmodifiable
| | |-'{' OpenParen unmodifiable
| | `-'}' CloseParen unmodifiable
| |-'else' ElseKeyword
| `-CompoundStatement ElseStatement
| |-'{' OpenParen
| `-'}' CloseParen
`-'}' CloseParen
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_ModifiableArguments) {
// FIXME: Note that the substitutions for `X` and `Y` are marked modifiable.
// However we cannot change `X` freely. Indeed if we change its substitution
// in the condition we should also change it the then-branch.
EXPECT_TRUE(treeDumpEqual(
R"cpp(
#define MIN(X,Y) X < Y ? X : Y
void test() {
MIN(1,2);
}
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
|-ExpressionStatement Statement
| |-UnknownExpression Expression
| | |-BinaryOperatorExpression unmodifiable
| | | |-IntegerLiteralExpression LeftHandSide
| | | | `-'1' LiteralToken
| | | |-'<' OperatorToken unmodifiable
| | | `-IntegerLiteralExpression RightHandSide
| | | `-'2' LiteralToken
| | |-'?' unmodifiable
| | |-IntegerLiteralExpression
| | | `-'1' LiteralToken
| | |-':' unmodifiable
| | `-IntegerLiteralExpression
| | `-'2' LiteralToken
| `-';'
`-'}' CloseParen
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_MismatchTree) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
#define HALF_IF(X) if (X &&
#define HALF_IF_2(Y) Y) {}
void test() {
HALF_IF(1) HALF_IF_2(0) else {}
})cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
|-IfStatement Statement
| |-'if' IntroducerKeyword unmodifiable
| |-'(' unmodifiable
| |-BinaryOperatorExpression unmodifiable
| | |-IntegerLiteralExpression LeftHandSide
| | | `-'1' LiteralToken
| | |-'&&' OperatorToken unmodifiable
| | `-IntegerLiteralExpression RightHandSide
| | `-'0' LiteralToken
| |-')' unmodifiable
| |-CompoundStatement ThenStatement unmodifiable
| | |-'{' OpenParen unmodifiable
| | `-'}' CloseParen unmodifiable
| |-'else' ElseKeyword
| `-CompoundStatement ElseStatement
| |-'{' OpenParen
| `-'}' CloseParen
`-'}' CloseParen
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_Variadic) {
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
#define CALL(F_NAME, ...) F_NAME(__VA_ARGS__)
void f(int);
void g(int, int);
void test() [[{
CALL(f, 0);
CALL(g, 0, 1);
}]]
)cpp",
{R"txt(
CompoundStatement
|-'{' OpenParen
|-ExpressionStatement Statement
| |-CallExpression Expression
| | |-IdExpression Callee
| | | `-UnqualifiedId UnqualifiedId
| | | `-'f'
| | |-'(' OpenParen unmodifiable
| | |-CallArguments Arguments
| | | `-IntegerLiteralExpression ListElement
| | | `-'0' LiteralToken
| | `-')' CloseParen unmodifiable
| `-';'
|-ExpressionStatement Statement
| |-CallExpression Expression
| | |-IdExpression Callee
| | | `-UnqualifiedId UnqualifiedId
| | | `-'g'
| | |-'(' OpenParen unmodifiable
| | |-CallArguments Arguments
| | | |-IntegerLiteralExpression ListElement
| | | | `-'0' LiteralToken
| | | |-',' ListDelimiter
| | | `-IntegerLiteralExpression ListElement
| | | `-'1' LiteralToken
| | `-')' CloseParen unmodifiable
| `-';'
`-'}' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, InitDeclarator_Equal) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S { S(int);};
void test() {
[[S s = 1]];
}
)cpp",
{R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'s'
|-'='
`-IntegerLiteralExpression
`-'1' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, InitDeclarator_Brace) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
S();
S(int);
S(int, float);
};
void test(){
// FIXME: 's...' is a declarator and '{...}' is initializer
[[S s0{}]];
[[S s1{1}]];
[[S s2{1, 2.}]];
}
)cpp",
{R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-UnknownExpression
|-'s0'
|-'{'
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-UnknownExpression
|-'s1'
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
`-UnknownExpression
|-'s2'
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-','
|-FloatingLiteralExpression
| `-'2.' LiteralToken
`-'}'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, InitDeclarator_EqualBrace) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
S();
S(int);
S(int, float);
};
void test() {
// FIXME: '= {...}' is initializer
[[S s0 = {}]];
[[S s1 = {1}]];
[[S s2 = {1, 2.}]];
}
)cpp",
{R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'s0'
|-'='
`-UnknownExpression
|-'{'
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'s1'
|-'='
`-UnknownExpression
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'s2'
|-'='
`-UnknownExpression
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-','
|-FloatingLiteralExpression
| `-'2.' LiteralToken
`-'}'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct S {
S(int);
S(int, float);
};
// FIXME: 's...' is a declarator and '(...)' is initializer
[[S s1(1);]]
[[S s2(1, 2.);]]
)cpp",
{R"txt(
SimpleDeclaration
|-'S'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-UnknownExpression
| |-'s1'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-UnknownExpression
| |-'s2'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-FloatingLiteralExpression
| | `-'2.' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, 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'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-'s0'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-UnknownExpression
| |-'s1'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| `-UnknownExpression
| |-'s2'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-FloatingLiteralExpression
| | `-'2.' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Argument) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X(int);
};
void TakeX(const X&);
void test() {
[[TakeX(1)]];
}
)cpp",
{R"txt(
CallExpression Expression
|-IdExpression Callee
| `-UnqualifiedId UnqualifiedId
| `-'TakeX'
|-'(' OpenParen
|-CallArguments Arguments
| `-IntegerLiteralExpression ListElement
| `-'1' LiteralToken
`-')' CloseParen
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Return) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X(int);
};
X CreateX(){
[[return 1;]]
}
)cpp",
{R"txt(
ReturnStatement Statement
|-'return' IntroducerKeyword
|-IntegerLiteralExpression ReturnValue
| `-'1' LiteralToken
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ConstructorCall_ZeroArguments) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X();
};
X test() {
[[return X();]]
}
)cpp",
{R"txt(
ReturnStatement Statement
|-'return' IntroducerKeyword
|-UnknownExpression ReturnValue
| |-'X'
| |-'('
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ConstructorCall_OneArgument) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X(int);
};
X test() {
[[return X(1);]]
}
)cpp",
{R"txt(
ReturnStatement Statement
|-'return' IntroducerKeyword
|-UnknownExpression ReturnValue
| |-'X'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ConstructorCall_MultipleArguments) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {
X(int, char);
};
X test() {
[[return X(1, '2');]]
}
)cpp",
{R"txt(
ReturnStatement Statement
|-'return' IntroducerKeyword
|-UnknownExpression ReturnValue
| |-'X'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-CharacterLiteralExpression
| | `-''2'' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, 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(BuildSyntaxTreeTest, TypeConversion_FunctionalNotation) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
float test() {
[[return float(1);]]
}
)cpp",
{R"txt(
ReturnStatement Statement
|-'return' IntroducerKeyword
|-UnknownExpression ReturnValue
| |-'float'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Simple) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int a[10];
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'a'
| `-ArraySubscript
| |-'[' OpenParen
| |-IntegerLiteralExpression Size
| | `-'10' LiteralToken
| `-']' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Multidimensional) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int b[1][2][3];
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'b'
| |-ArraySubscript
| | |-'[' OpenParen
| | |-IntegerLiteralExpression Size
| | | `-'1' LiteralToken
| | `-']' CloseParen
| |-ArraySubscript
| | |-'[' OpenParen
| | |-IntegerLiteralExpression Size
| | | `-'2' LiteralToken
| | `-']' CloseParen
| `-ArraySubscript
| |-'[' OpenParen
| |-IntegerLiteralExpression Size
| | `-'3' LiteralToken
| `-']' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_UnknownBound) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int c[] = {1,2,3};
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'c'
| |-ArraySubscript
| | |-'[' OpenParen
| | `-']' CloseParen
| |-'='
| `-UnknownExpression
| `-UnknownExpression
| |-'{'
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-IntegerLiteralExpression
| | `-'2' LiteralToken
| |-','
| |-IntegerLiteralExpression
| | `-'3' LiteralToken
| `-'}'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Static) {
if (!GetParam().isC99OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void f(int xs[static 10]);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'xs'
| | `-ArraySubscript
| | |-'[' OpenParen
| | |-'static'
| | |-IntegerLiteralExpression Size
| | | `-'10' LiteralToken
| | `-']' CloseParen
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func();
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func1(int a);
int func2(int *ap);
int func3(int a, float b);
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'func1'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'a'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'func2'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | |-'*'
| | | `-'ap'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func3'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'float'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'b'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func1(int);
int func2(int *);
int func3(int, float);
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'func1'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | `-'int'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'func2'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'*'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func3'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | `-'int'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | `-'float'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest,
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'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'a'
|-'='
`-IntegerLiteralExpression
`-'1' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
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'
| `-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| `-'ap'
|-',' ListDelimiter
|-SimpleDeclaration ListElement
| |-'int'
| `-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'a'
| |-'='
| `-IntegerLiteralExpression
| `-'1' LiteralToken
|-',' ListDelimiter
`-SimpleDeclaration ListElement
|-'char'
`-DeclaratorList Declarators
`-SimpleDeclarator ListElement
|-'c'
|-'='
`-CharacterLiteralExpression
`-''2'' LiteralToken
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T, typename... Args>
[[void test(T , Args... );]]
)cpp",
{R"txt(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | `-'T'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'Args'
| | `-'...'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
template<typename T, typename... Args>
[[void test(T t, Args... args);]]
)cpp",
{R"txt(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'T'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'t'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'Args'
| | |-'...'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'args'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void test(int , char ...);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | `-'int'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | `-'char'
| |-'...'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func(const int a, volatile int b, const volatile int c);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'const'
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'a'
| | |-',' ListDelimiter
| | |-SimpleDeclaration ListElement
| | | |-'volatile'
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'b'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'volatile'
| | |-'int'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'c'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func(int& a);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'&'
| | `-'a'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int func(int&& a);
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'&&'
| | `-'a'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
struct Test {
int a();
};
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'struct'
|-'Test'
|-'{'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'a'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | `-')' CloseParen
| `-';'
|-'}'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest,
ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct Test {
[[int b() const;]]
[[int c() volatile;]]
[[int d() const volatile;]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'b'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'const'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'c'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'volatile'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'d'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'const'
| `-'volatile'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct Test {
[[int e() &;]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'e'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'&'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct Test {
[[int f() &&;]]
};
)cpp",
{R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'&&'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, TrailingReturn) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
auto foo() -> int;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'auto'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'foo'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-TrailingReturnType TrailingReturn
| |-'->' ArrowToken
| `-'int'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, DynamicExceptionSpecification) {
if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct MyException1 {};
struct MyException2 {};
[[int a() throw();]]
[[int b() throw(...);]]
[[int c() throw(MyException1);]]
[[int d() throw(MyException1, MyException2);]]
)cpp",
{R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'a'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'b'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| |-'...'
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'c'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| |-'MyException1'
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'d'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| |-'MyException1'
| |-','
| |-'MyException2'
| `-')'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, NoexceptExceptionSpecification) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int a() noexcept;
int b() noexcept(true);
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'a'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-')' CloseParen
| | `-'noexcept'
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'b'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'noexcept'
| |-'('
| |-BoolLiteralExpression
| | `-'true' LiteralToken
| `-')'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, DeclaratorsInParentheses) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
int (a);
int *(b);
int (*c)(int);
int *(d)(int);
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-ParenDeclarator
| | |-'(' OpenParen
| | |-'a'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'*'
| | `-ParenDeclarator
| | |-'(' OpenParen
| | |-'b'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-ParenDeclarator
| | | |-'(' OpenParen
| | | |-'*'
| | | |-'c'
| | | `-')' CloseParen
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | `-'int'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-'d'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | `-'int'
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
const int west = -1;
int const east = 1;
)cpp",
R"txt(
TranslationUnit Detached
|-SimpleDeclaration
| |-'const'
| |-'int'
| |-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-'west'
| | |-'='
| | `-PrefixUnaryOperatorExpression
| | |-'-' OperatorToken
| | `-IntegerLiteralExpression Operand
| | `-'1' LiteralToken
| `-';'
`-SimpleDeclaration
|-'int'
|-'const'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'east'
| |-'='
| `-IntegerLiteralExpression
| `-'1' LiteralToken
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
const int const universal = 0;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'const'
|-'int'
|-'const'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'universal'
| |-'='
| `-IntegerLiteralExpression
| `-'0' LiteralToken
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest,
Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
const int const *const *volatile b;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'const'
|-'int'
|-'const'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'*'
| |-'const'
| |-'*'
| |-'volatile'
| `-'b'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
if (!GetParam().isCXX11OrLater()) {
return;
}
EXPECT_TRUE(treeDumpEqual(
R"cpp(
auto foo() -> auto(*)(int) -> double*;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'auto'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'foo'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-TrailingReturnType TrailingReturn
| |-'->' ArrowToken
| |-'auto'
| `-SimpleDeclarator Declarator
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-'*'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | `-'int'
| |-')' CloseParen
| `-TrailingReturnType TrailingReturn
| |-'->' ArrowToken
| |-'double'
| `-SimpleDeclarator Declarator
| `-'*'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, MemberPointers) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
struct X {};
[[int X::* a;]]
[[const int X::* b;]]
)cpp",
{R"txt(
SimpleDeclaration
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-MemberPointer
| | |-'X'
| | |-'::'
| | `-'*'
| `-'a'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'const'
|-'int'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-MemberPointer
| | |-'X'
| | |-'::'
| | `-'*'
| `-'b'
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, MemberFunctionPointer) {
if (!GetParam().isCXX()) {
return;
}
EXPECT_TRUE(treeDumpEqualOnAnnotations(
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(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-MemberPointer
| | | |-'X'
| | | |-'::'
| | | `-'*'
| | |-'xp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-MemberPointer
| | | |-'X'
| | | |-'::'
| | | `-'*'
| | |-'*'
| | |-'xpp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'int'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | `-'*'
| `-')' CloseParen
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-'X'
| | |-'::'
| | |-MemberPointer
| | | |-'Y'
| | | |-'::'
| | | `-'*'
| | |-'xyp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'const'
| | | |-'int'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'*'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | `-'char'
| `-')' CloseParen
`-';'
)txt"}));
}
TEST_P(BuildSyntaxTreeTest, ComplexDeclarator) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void x(char a, short (*b)(int));
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'x'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'char'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'short'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-ParenDeclarator
| | | |-'(' OpenParen
| | | |-'*'
| | | |-'b'
| | | `-')' CloseParen
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | `-'int'
| | `-')' CloseParen
| `-')' CloseParen
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, ComplexDeclarator2) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
void x(char a, short (*b)(int), long (**c)(long long));
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'void'
|-DeclaratorList Declarators
| `-SimpleDeclarator ListElement
| |-'x'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'char'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | `-'a'
| | |-',' ListDelimiter
| | |-SimpleDeclaration ListElement
| | | |-'short'
| | | `-DeclaratorList Declarators
| | | `-SimpleDeclarator ListElement
| | | |-ParenDeclarator
| | | | |-'(' OpenParen
| | | | |-'*'
| | | | |-'b'
| | | | `-')' CloseParen
| | | `-ParametersAndQualifiers
| | | |-'(' OpenParen
| | | |-ParameterDeclarationList Parameters
| | | | `-SimpleDeclaration ListElement
| | | | `-'int'
| | | `-')' CloseParen
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'long'
| | `-DeclaratorList Declarators
| | `-SimpleDeclarator ListElement
| | |-ParenDeclarator
| | | |-'(' OpenParen
| | | |-'*'
| | | |-'*'
| | | |-'c'
| | | `-')' CloseParen
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'long'
| | | `-'long'
| | `-')' CloseParen
| `-')' CloseParen
`-';'
)txt"));
}
} // namespace