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