| //===- 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_SUITE_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 |