2020-09-22 13:17:33 +00:00

5637 lines
110 KiB
C++
Raw 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'
| |-SimpleDeclarator Declarator
| | |-'main'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | `-')' CloseParen
| `-CompoundStatement
| |-'{' OpenParen
| `-'}' CloseParen
`-SimpleDeclaration
|-'void'
|-SimpleDeclarator Declarator
| |-'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'
| |-SimpleDeclarator Declarator
| | `-'a'
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'foo'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-SimpleDeclarator Declarator
| | `-'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'
|-SimpleDeclarator Declarator
| `-'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'
| |-SimpleDeclarator Declarator
| | `-'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'
| `-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
`-SimpleDeclarator Declarator
`-'s1'
)txt",
R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-IdentifierNameSpecifier ListElement
| | `-'n'
| `-'::' ListDelimiter
|-'S'
`-SimpleDeclarator Declarator
`-'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'
`-SimpleDeclarator Declarator
`-'s1'
)txt",
R"txt(
SimpleDeclaration
|-NestedNameSpecifier
| |-'::' ListDelimiter
| |-SimpleTemplateNameSpecifier ListElement
| | |-'ST'
| | |-'<'
| | |-'int'
| | `-'>'
| `-'::' ListDelimiter
|-'S'
`-SimpleDeclarator Declarator
`-'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"
" |-SimpleDeclarator Declarator\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'
| |-SimpleDeclarator Declarator
| | |-'*'
| | `-'a'
| |-','
| |-SimpleDeclarator Declarator
| | `-'b'
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'*'
| `-'c'
|-','
|-SimpleDeclarator Declarator
| `-'d'
`-';'
)txt"));
}
TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
typedef int *a, b;
)cpp",
R"txt(
TranslationUnit Detached
`-SimpleDeclaration
|-'typedef'
|-'int'
|-SimpleDeclarator Declarator
| |-'*'
| `-'a'
|-','
|-SimpleDeclarator Declarator
| `-'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'
|-SimpleDeclarator Declarator
| |-'foo'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-CompoundStatement
|-'{' OpenParen
|-DeclarationStatement Statement
| |-SimpleDeclaration
| | |-'int'
| | |-SimpleDeclarator Declarator
| | | |-'*'
| | | `-'a'
| | |-','
| | `-SimpleDeclarator Declarator
| | `-'b'
| `-';'
|-DeclarationStatement Statement
| |-SimpleDeclaration
| | |-'typedef'
| | |-'int'
| | |-SimpleDeclarator Declarator
| | | |-'*'
| | | `-'ta'
| | |-','
| | `-SimpleDeclarator Declarator
| | `-'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'
| |-'*'
| `-')'
|-')'
|-SimpleDeclarator Declarator
| `-'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'
|-SimpleDeclarator Declarator
| |-'*'
| `-'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'
|-'{'
|-'}'
|-SimpleDeclarator Declarator
| |-'*'
| `-'y2'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'struct'
|-'{'
|-'}'
|-SimpleDeclarator Declarator
| |-'*'
| `-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-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
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'&'
| |-'operator'
| |-'='
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'X'
| | `-SimpleDeclarator Declarator
| | `-'&'
| `-')' 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'
|-SimpleDeclarator Declarator
| |-'operator'
| |-'+'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | `-'X'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'X'
| | `-SimpleDeclarator Declarator
| | `-'&'
| `-')' 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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
| |-SimpleDeclarator Declarator
| | |-'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'
| | |-SimpleDeclarator Declarator
| | | |-'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, ExplicitClassTemplateInstantation_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, ExplicitClassTemplateInstantation_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'
| |-SimpleDeclarator Declarator
| | `-'a'
| `-';'
`-LinkageSpecificationDeclaration
|-'extern'
|-'"C"'
|-'{'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | `-'b'
| `-';'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | `-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
`-SimpleDeclarator Declarator
|-'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'
`-SimpleDeclarator Declarator
`-UnknownExpression
|-'s0'
|-'{'
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-SimpleDeclarator Declarator
`-UnknownExpression
|-'s1'
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-SimpleDeclarator Declarator
`-UnknownExpression
|-'s2'
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
|-','
|-FloatingLiteralExpression
| `-'2.' LiteralToken
`-'}'
)txt"}));
}
TEST_P(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'
`-SimpleDeclarator Declarator
|-'s0'
|-'='
`-UnknownExpression
|-'{'
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-SimpleDeclarator Declarator
|-'s1'
|-'='
`-UnknownExpression
|-'{'
|-IntegerLiteralExpression
| `-'1' LiteralToken
`-'}'
)txt",
R"txt(
SimpleDeclaration
|-'S'
`-SimpleDeclarator Declarator
|-'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'
|-SimpleDeclarator Declarator
| `-UnknownExpression
| |-'s1'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-SimpleDeclarator Declarator
| `-UnknownExpression
| |-'s2'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-FloatingLiteralExpression
| | `-'2.' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(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'
|-SimpleDeclarator Declarator
| `-'s0'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-SimpleDeclarator Declarator
| `-UnknownExpression
| |-'s1'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'S'
|-SimpleDeclarator Declarator
| `-UnknownExpression
| |-'s2'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
| |-','
| |-FloatingLiteralExpression
| | `-'2.' LiteralToken
| `-')'
`-';'
)txt"}));
}
TEST_P(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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'f'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-SimpleDeclarator Declarator
| | |-'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'
|-SimpleDeclarator Declarator
| |-'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'
| |-SimpleDeclarator Declarator
| | |-'func1'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | |-'func2'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | |-'*'
| | | `-'ap'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'func3'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'float'
| | `-SimpleDeclarator Declarator
| | `-'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'
| |-SimpleDeclarator Declarator
| | |-'func1'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | `-'int'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | |-'func2'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'*'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'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'
`-SimpleDeclarator Declarator
|-'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'
| `-SimpleDeclarator Declarator
| |-'*'
| `-'ap'
|-',' ListDelimiter
|-SimpleDeclaration ListElement
| |-'int'
| `-SimpleDeclarator Declarator
| |-'a'
| |-'='
| `-IntegerLiteralExpression
| `-'1' LiteralToken
|-',' ListDelimiter
`-SimpleDeclaration ListElement
|-'char'
`-SimpleDeclarator Declarator
|-'c'
|-'='
`-CharacterLiteralExpression
`-''2'' LiteralToken
)txt"}));
}
TEST_P(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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'test'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'T'
| | | `-SimpleDeclarator Declarator
| | | `-'t'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'Args'
| | |-'...'
| | `-SimpleDeclarator Declarator
| | `-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'const'
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | |-',' ListDelimiter
| | |-SimpleDeclaration ListElement
| | | |-'volatile'
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'b'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'volatile'
| | |-'int'
| | `-SimpleDeclarator Declarator
| | `-'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'
|-SimpleDeclarator Declarator
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-SimpleDeclarator Declarator
| | |-'&'
| | `-'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'
|-SimpleDeclarator Declarator
| |-'func'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'int'
| | `-SimpleDeclarator Declarator
| | |-'&&'
| | `-'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'
| |-SimpleDeclarator Declarator
| | |-'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'
|-SimpleDeclarator Declarator
| |-'b'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'const'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'c'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| `-'volatile'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'a'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'b'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| |-'...'
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'c'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-')' CloseParen
| |-'throw'
| |-'('
| |-'MyException1'
| `-')'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'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'
| |-SimpleDeclarator Declarator
| | |-'a'
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-')' CloseParen
| | `-'noexcept'
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'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'
| |-SimpleDeclarator Declarator
| | `-ParenDeclarator
| | |-'(' OpenParen
| | |-'a'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | |-'*'
| | `-ParenDeclarator
| | |-'(' OpenParen
| | |-'b'
| | `-')' CloseParen
| `-';'
|-SimpleDeclaration
| |-'int'
| |-SimpleDeclarator Declarator
| | |-ParenDeclarator
| | | |-'(' OpenParen
| | | |-'*'
| | | |-'c'
| | | `-')' CloseParen
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | `-'int'
| | `-')' CloseParen
| `-';'
`-SimpleDeclaration
|-'int'
|-SimpleDeclarator Declarator
| |-'*'
| |-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'
| |-SimpleDeclarator Declarator
| | |-'west'
| | |-'='
| | `-PrefixUnaryOperatorExpression
| | |-'-' OperatorToken
| | `-IntegerLiteralExpression Operand
| | `-'1' LiteralToken
| `-';'
`-SimpleDeclaration
|-'int'
|-'const'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-'*'
| |-'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'
|-SimpleDeclarator Declarator
| |-'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'
|-SimpleDeclarator Declarator
| |-MemberPointer
| | |-'X'
| | |-'::'
| | `-'*'
| `-'a'
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'const'
|-'int'
|-SimpleDeclarator Declarator
| |-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'
|-SimpleDeclarator Declarator
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-MemberPointer
| | | |-'X'
| | | |-'::'
| | | `-'*'
| | |-'xp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| `-')' CloseParen
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'void'
|-SimpleDeclarator Declarator
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-MemberPointer
| | | |-'X'
| | | |-'::'
| | | `-'*'
| | |-'*'
| | |-'xpp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | `-SimpleDeclaration ListElement
| | |-'const'
| | |-'int'
| | `-SimpleDeclarator Declarator
| | `-'*'
| `-')' CloseParen
`-';'
)txt",
R"txt(
SimpleDeclaration
|-'void'
|-SimpleDeclarator Declarator
| |-ParenDeclarator
| | |-'(' OpenParen
| | |-'X'
| | |-'::'
| | |-MemberPointer
| | | |-'Y'
| | | |-'::'
| | | `-'*'
| | |-'xyp'
| | `-')' CloseParen
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'const'
| | | |-'int'
| | | `-SimpleDeclarator Declarator
| | | `-'*'
| | |-',' 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'
|-SimpleDeclarator Declarator
| |-'x'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'char'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'short'
| | `-SimpleDeclarator Declarator
| | |-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'
|-SimpleDeclarator Declarator
| |-'x'
| `-ParametersAndQualifiers
| |-'(' OpenParen
| |-ParameterDeclarationList Parameters
| | |-SimpleDeclaration ListElement
| | | |-'char'
| | | `-SimpleDeclarator Declarator
| | | `-'a'
| | |-',' ListDelimiter
| | |-SimpleDeclaration ListElement
| | | |-'short'
| | | `-SimpleDeclarator Declarator
| | | |-ParenDeclarator
| | | | |-'(' OpenParen
| | | | |-'*'
| | | | |-'b'
| | | | `-')' CloseParen
| | | `-ParametersAndQualifiers
| | | |-'(' OpenParen
| | | |-ParameterDeclarationList Parameters
| | | | `-SimpleDeclaration ListElement
| | | | `-'int'
| | | `-')' CloseParen
| | |-',' ListDelimiter
| | `-SimpleDeclaration ListElement
| | |-'long'
| | `-SimpleDeclarator Declarator
| | |-ParenDeclarator
| | | |-'(' OpenParen
| | | |-'*'
| | | |-'*'
| | | |-'c'
| | | `-')' CloseParen
| | `-ParametersAndQualifiers
| | |-'(' OpenParen
| | |-ParameterDeclarationList Parameters
| | | `-SimpleDeclaration ListElement
| | | |-'long'
| | | `-'long'
| | `-')' CloseParen
| `-')' CloseParen
`-';'
)txt"));
}
} // namespace