| //===- TreeTest.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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Tooling/Syntax/Tree.h" |
| #include "clang/AST/ASTConsumer.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/Stmt.h" |
| #include "clang/Basic/LLVM.h" |
| #include "clang/Basic/TokenKinds.h" |
| #include "clang/Frontend/CompilerInstance.h" |
| #include "clang/Frontend/CompilerInvocation.h" |
| #include "clang/Frontend/FrontendAction.h" |
| #include "clang/Frontend/TextDiagnosticPrinter.h" |
| #include "clang/Lex/PreprocessorOptions.h" |
| #include "clang/Testing/CommandLineArgs.h" |
| #include "clang/Testing/TestClangConfig.h" |
| #include "clang/Tooling/Core/Replacement.h" |
| #include "clang/Tooling/Syntax/BuildTree.h" |
| #include "clang/Tooling/Syntax/Mutations.h" |
| #include "clang/Tooling/Syntax/Nodes.h" |
| #include "clang/Tooling/Syntax/Tokens.h" |
| #include "clang/Tooling/Tooling.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Testing/Support/Annotations.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include <cstdlib> |
| |
| using namespace clang; |
| |
| namespace { |
| static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) { |
| assert(N->isOriginal() && "tokens of modified nodes are not well-defined"); |
| if (auto *L = dyn_cast<syntax::Leaf>(N)) |
| return llvm::makeArrayRef(L->token(), 1); |
| auto *T = cast<syntax::Tree>(N); |
| return llvm::makeArrayRef(T->firstLeaf()->token(), |
| T->lastLeaf()->token() + 1); |
| } |
| |
| class SyntaxTreeTest : public ::testing::Test, |
| public ::testing::WithParamInterface<TestClangConfig> { |
| protected: |
| // Build a syntax tree for the code. |
| syntax::TranslationUnit *buildTree(llvm::StringRef Code, |
| const TestClangConfig &ClangConfig) { |
| // FIXME: this code is almost the identical to the one in TokensTest. Share |
| // it. |
| class BuildSyntaxTree : public ASTConsumer { |
| public: |
| BuildSyntaxTree(syntax::TranslationUnit *&Root, |
| std::unique_ptr<syntax::Arena> &Arena, |
| std::unique_ptr<syntax::TokenCollector> Tokens) |
| : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) { |
| assert(this->Tokens); |
| } |
| |
| void HandleTranslationUnit(ASTContext &Ctx) override { |
| Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(), |
| Ctx.getLangOpts(), |
| std::move(*Tokens).consume()); |
| Tokens = nullptr; // make sure we fail if this gets called twice. |
| Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl()); |
| } |
| |
| private: |
| syntax::TranslationUnit *&Root; |
| std::unique_ptr<syntax::Arena> &Arena; |
| std::unique_ptr<syntax::TokenCollector> Tokens; |
| }; |
| |
| class BuildSyntaxTreeAction : public ASTFrontendAction { |
| public: |
| BuildSyntaxTreeAction(syntax::TranslationUnit *&Root, |
| std::unique_ptr<syntax::Arena> &Arena) |
| : Root(Root), Arena(Arena) {} |
| |
| std::unique_ptr<ASTConsumer> |
| CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { |
| // We start recording the tokens, ast consumer will take on the result. |
| auto Tokens = |
| std::make_unique<syntax::TokenCollector>(CI.getPreprocessor()); |
| return std::make_unique<BuildSyntaxTree>(Root, Arena, |
| std::move(Tokens)); |
| } |
| |
| private: |
| syntax::TranslationUnit *&Root; |
| std::unique_ptr<syntax::Arena> &Arena; |
| }; |
| |
| constexpr const char *FileName = "./input.cpp"; |
| FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy("")); |
| |
| if (!Diags->getClient()) |
| Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagOpts.get())); |
| Diags->setSeverityForGroup(diag::Flavor::WarningOrError, "unused-value", |
| diag::Severity::Ignored, SourceLocation()); |
| |
| // Prepare to run a compiler. |
| std::vector<std::string> Args = { |
| "syntax-test", |
| "-fsyntax-only", |
| }; |
| llvm::copy(ClangConfig.getCommandLineArgs(), std::back_inserter(Args)); |
| Args.push_back(FileName); |
| |
| std::vector<const char *> ArgsCStr; |
| for (const std::string &arg : Args) { |
| ArgsCStr.push_back(arg.c_str()); |
| } |
| |
| Invocation = createInvocationFromCommandLine(ArgsCStr, Diags, FS); |
| assert(Invocation); |
| Invocation->getFrontendOpts().DisableFree = false; |
| Invocation->getPreprocessorOpts().addRemappedFile( |
| FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release()); |
| CompilerInstance Compiler; |
| Compiler.setInvocation(Invocation); |
| Compiler.setDiagnostics(Diags.get()); |
| Compiler.setFileManager(FileMgr.get()); |
| Compiler.setSourceManager(SourceMgr.get()); |
| |
| syntax::TranslationUnit *Root = nullptr; |
| BuildSyntaxTreeAction Recorder(Root, this->Arena); |
| |
| // Action could not be executed but the frontend didn't identify any errors |
| // in the code ==> problem in setting up the action. |
| if (!Compiler.ExecuteAction(Recorder) && |
| Diags->getClient()->getNumErrors() == 0) { |
| ADD_FAILURE() << "failed to run the frontend"; |
| std::abort(); |
| } |
| return Root; |
| } |
| |
| ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) { |
| SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); |
| |
| auto *Root = buildTree(Code, GetParam()); |
| if (Diags->getClient()->getNumErrors() != 0) { |
| return ::testing::AssertionFailure() |
| << "Source file has syntax errors, they were printed to the test " |
| "log"; |
| } |
| std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim()); |
| // 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(); |
| } |
| |
| // Adds a file to the test VFS. |
| void addFile(llvm::StringRef Path, llvm::StringRef Contents) { |
| if (!FS->addFile(Path, time_t(), |
| llvm::MemoryBuffer::getMemBufferCopy(Contents))) { |
| ADD_FAILURE() << "could not add a file to VFS: " << Path; |
| } |
| } |
| |
| /// Finds the deepest node in the tree that covers exactly \p R. |
| /// FIXME: implement this efficiently and move to public syntax tree API. |
| syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) { |
| llvm::ArrayRef<syntax::Token> Toks = tokens(Root); |
| |
| if (Toks.front().location().isFileID() && |
| Toks.back().location().isFileID() && |
| syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) == |
| syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End)) |
| return Root; |
| |
| auto *T = dyn_cast<syntax::Tree>(Root); |
| if (!T) |
| return nullptr; |
| for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) { |
| if (auto *Result = nodeByRange(R, C)) |
| return Result; |
| } |
| return nullptr; |
| } |
| |
| // Data fields. |
| llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = |
| new DiagnosticOptions(); |
| llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = |
| new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get()); |
| IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = |
| new llvm::vfs::InMemoryFileSystem; |
| llvm::IntrusiveRefCntPtr<FileManager> FileMgr = |
| new FileManager(FileSystemOptions(), FS); |
| llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr = |
| new SourceManager(*Diags, *FileMgr); |
| std::shared_ptr<CompilerInvocation> Invocation; |
| // Set after calling buildTree(). |
| std::unique_ptr<syntax::Arena> Arena; |
| }; |
| |
| TEST_P(SyntaxTreeTest, Simple) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int main() {} |
| void foo() {} |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-main |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | `-) |
| | `-CompoundStatement |
| | |-{ |
| | `-} |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-foo |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, SimpleVariable) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int a; |
| int b = 42; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | `-a |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-b |
| | |-= |
| | `-IntegerLiteralExpression |
| | `-42 |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, SimpleFunction) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void foo(int a, int b) {} |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-foo |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-b |
| | `-) |
| `-CompoundStatement |
| |-{ |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, If) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int main() { |
| if (1) {} |
| if (1) {} else if (0) {} |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-main |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-IfStatement |
| | |-if |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-) |
| | `-CompoundStatement |
| | |-{ |
| | `-} |
| |-IfStatement |
| | |-if |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-) |
| | |-CompoundStatement |
| | | |-{ |
| | | `-} |
| | |-else |
| | `-IfStatement |
| | |-if |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-0 |
| | |-) |
| | `-CompoundStatement |
| | |-{ |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, For) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| for (;;) {} |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ForStatement |
| | |-for |
| | |-( |
| | |-; |
| | |-; |
| | |-) |
| | `-CompoundStatement |
| | |-{ |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, RangeBasedFor) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| int a[3]; |
| for (int x : a) |
| ; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-DeclarationStatement |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-a |
| | | `-ArraySubscript |
| | | |-[ |
| | | |-IntegerLiteralExpression |
| | | | `-3 |
| | | `-] |
| | `-; |
| |-RangeBasedForStatement |
| | |-for |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | |-SimpleDeclarator |
| | | | `-x |
| | | `-: |
| | |-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | |-) |
| | `-EmptyStatement |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, DeclarationStatement) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| int a = 10; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-DeclarationStatement |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-a |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-10 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, Switch) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| switch (1) { |
| case 0: |
| default:; |
| } |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-SwitchStatement |
| | |-switch |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-) |
| | `-CompoundStatement |
| | |-{ |
| | |-CaseStatement |
| | | |-case |
| | | |-IntegerLiteralExpression |
| | | | `-0 |
| | | |-: |
| | | `-DefaultStatement |
| | | |-default |
| | | |-: |
| | | `-EmptyStatement |
| | | `-; |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, While) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| while (1) { continue; break; } |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-WhileStatement |
| | |-while |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-) |
| | `-CompoundStatement |
| | |-{ |
| | |-ContinueStatement |
| | | |-continue |
| | | `-; |
| | |-BreakStatement |
| | | |-break |
| | | `-; |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, 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(treeDumpEqual( |
| R"cpp( |
| int main() { |
| foo: return 100; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-main |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-UnknownStatement |
| | |-foo |
| | |-: |
| | `-ReturnStatement |
| | |-return |
| | |-IntegerLiteralExpression |
| | | `-100 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, 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 |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-test |
| | | |-( |
| | | `-) |
| | `-; |
| |-IfStatement |
| | |-if |
| | |-( |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-) |
| | |-ExpressionStatement |
| | | |-UnknownExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-test |
| | | | |-( |
| | | | `-) |
| | | `-; |
| | |-else |
| | `-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-test |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UnqualifiedId) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct X { |
| // TODO: Expose `id-expression` from `Declarator` |
| friend X operator+(const X&, const X&); |
| operator int(); |
| }; |
| template<typename T> |
| void f(T&); |
| void test(X x) { |
| x; // identifier |
| operator+(x, x); // operator-function-id |
| f<X>(x); // template-id |
| // TODO: Expose `id-expression` from `MemberExpr` |
| x.operator int(); // conversion-funtion-id |
| x.~X(); // ~type-name |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-UnknownDeclaration |
| | | `-SimpleDeclaration |
| | | |-friend |
| | | |-X |
| | | |-SimpleDeclarator |
| | | | |-operator |
| | | | |-+ |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | |-, |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | `-) |
| | | `-; |
| | |-SimpleDeclaration |
| | | |-SimpleDeclarator |
| | | | |-operator |
| | | | |-int |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | `-) |
| | | `-; |
| | |-} |
| | `-; |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-typename |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-void |
| | |-SimpleDeclarator |
| | | |-f |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-T |
| | | | `-SimpleDeclarator |
| | | | `-& |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-X |
| | | `-SimpleDeclarator |
| | | `-x |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-IdExpression |
| | | `-UnqualifiedId |
| | | `-x |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | |-operator |
| | | | `-+ |
| | | |-( |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | |-, |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | |-f |
| | | | |-< |
| | | | |-X |
| | | | `-> |
| | | |-( |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-UnknownExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-x |
| | | | |-. |
| | | | |-operator |
| | | | `-int |
| | | |-( |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-UnknownExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-x |
| | | | |-. |
| | | | |-~ |
| | | | `-X |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UnqualifiedIdCxx11OrLater) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct X { }; |
| unsigned operator "" _w(long long unsigned); |
| void test(X x) { |
| operator "" _w(1llu); // literal-operator-id |
| // TODO: Expose `id-expression` from `MemberExpr` |
| x.~decltype(x)(); // ~decltype-specifier |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-} |
| | `-; |
| |-SimpleDeclaration |
| | |-unsigned |
| | |-SimpleDeclarator |
| | | |-operator |
| | | |-"" |
| | | |-_w |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-long |
| | | | |-long |
| | | | `-unsigned |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-X |
| | | `-SimpleDeclarator |
| | | `-x |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | |-operator |
| | | | |-"" |
| | | | `-_w |
| | | |-( |
| | | |-IntegerLiteralExpression |
| | | | `-1llu |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-UnknownExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-x |
| | | | |-. |
| | | | `-~ |
| | | |-decltype |
| | | |-( |
| | | |-x |
| | | |-) |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, QualifiedId) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| namespace a { |
| struct S { |
| template<typename T> |
| static T f(){} |
| }; |
| } |
| void test() { |
| :: // global-namespace-specifier |
| a:: // namespace-specifier |
| S:: // type-name-specifier |
| f<int>(); |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-NamespaceDefinition |
| | |-namespace |
| | |-a |
| | |-{ |
| | |-SimpleDeclaration |
| | | |-struct |
| | | |-S |
| | | |-{ |
| | | |-TemplateDeclaration |
| | | | |-template |
| | | | |-< |
| | | | |-UnknownDeclaration |
| | | | | |-typename |
| | | | | `-T |
| | | | |-> |
| | | | `-SimpleDeclaration |
| | | | |-static |
| | | | |-T |
| | | | |-SimpleDeclarator |
| | | | | |-f |
| | | | | `-ParametersAndQualifiers |
| | | | | |-( |
| | | | | `-) |
| | | | `-CompoundStatement |
| | | | |-{ |
| | | | `-} |
| | | |-} |
| | | `-; |
| | `-} |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | |-NestedNameSpecifier |
| | | | | |-NameSpecifier |
| | | | | | `-:: |
| | | | | |-NameSpecifier |
| | | | | | |-a |
| | | | | | `-:: |
| | | | | `-NameSpecifier |
| | | | | |-S |
| | | | | `-:: |
| | | | `-UnqualifiedId |
| | | | |-f |
| | | | |-< |
| | | | |-int |
| | | | `-> |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, QualifiedIdWithTemplateKeyword) { |
| 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(treeDumpEqual( |
| R"cpp( |
| struct X { |
| template<int> static void f(); |
| template<int> |
| struct Y { |
| static void f(); |
| }; |
| }; |
| template<typename T> void test() { |
| // TODO: Expose `id-expression` from `DependentScopeDeclRefExpr` |
| T::template f<0>(); // nested-name-specifier template unqualified-id |
| T::template Y<0>::f(); // nested-name-specifier template :: unqualified-id |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-TemplateDeclaration |
| | | |-template |
| | | |-< |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | |-> |
| | | `-SimpleDeclaration |
| | | |-static |
| | | |-void |
| | | |-SimpleDeclarator |
| | | | |-f |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | `-) |
| | | `-; |
| | |-TemplateDeclaration |
| | | |-template |
| | | |-< |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | |-> |
| | | `-SimpleDeclaration |
| | | |-struct |
| | | |-Y |
| | | |-{ |
| | | |-SimpleDeclaration |
| | | | |-static |
| | | | |-void |
| | | | |-SimpleDeclarator |
| | | | | |-f |
| | | | | `-ParametersAndQualifiers |
| | | | | |-( |
| | | | | `-) |
| | | | `-; |
| | | |-} |
| | | `-; |
| | |-} |
| | `-; |
| `-TemplateDeclaration |
| |-template |
| |-< |
| |-UnknownDeclaration |
| | |-typename |
| | `-T |
| |-> |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-UnknownExpression |
| | | | |-T |
| | | | |-:: |
| | | | |-template |
| | | | |-f |
| | | | |-< |
| | | | |-IntegerLiteralExpression |
| | | | | `-0 |
| | | | `-> |
| | | |-( |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-UnknownExpression |
| | | | |-T |
| | | | |-:: |
| | | | |-template |
| | | | |-Y |
| | | | |-< |
| | | | |-IntegerLiteralExpression |
| | | | | `-0 |
| | | | |-> |
| | | | |-:: |
| | | | `-f |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, QualifiedIdDecltype) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct S { |
| static void f(){} |
| }; |
| void test(S s) { |
| decltype(s):: // decltype-specifier |
| f(); |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-S |
| | |-{ |
| | |-SimpleDeclaration |
| | | |-static |
| | | |-void |
| | | |-SimpleDeclarator |
| | | | |-f |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | `-) |
| | | `-CompoundStatement |
| | | |-{ |
| | | `-} |
| | |-} |
| | `-; |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-S |
| | | `-SimpleDeclarator |
| | | `-s |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-UnknownExpression |
| | | |-IdExpression |
| | | | |-NestedNameSpecifier |
| | | | | `-NameSpecifier |
| | | | | |-decltype |
| | | | | |-( |
| | | | | |-IdExpression |
| | | | | | `-UnqualifiedId |
| | | | | | `-s |
| | | | | |-) |
| | | | | `-:: |
| | | | `-UnqualifiedId |
| | | | `-f |
| | | |-( |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ParenExpr) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| (1); |
| ((1)); |
| (1 + (2)); |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-ParenExpression |
| | | |-( |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-ParenExpression |
| | | |-( |
| | | |-ParenExpression |
| | | | |-( |
| | | | |-IntegerLiteralExpression |
| | | | | `-1 |
| | | | `-) |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-ParenExpression |
| | | |-( |
| | | |-BinaryOperatorExpression |
| | | | |-IntegerLiteralExpression |
| | | | | `-1 |
| | | | |-+ |
| | | | `-ParenExpression |
| | | | |-( |
| | | | |-IntegerLiteralExpression |
| | | | | `-2 |
| | | | `-) |
| | | `-) |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, IntegerLiteral) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 12; |
| 12u; |
| 12l; |
| 12ul; |
| 014; |
| 0XC; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12 |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12u |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12l |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12ul |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-014 |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-0XC |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 12ll; |
| 12ull; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12ll |
| | `-; |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-12ull |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, IntegerLiteralBinary) { |
| if (!GetParam().isCXX14OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 0b1100; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-0b1100 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) { |
| if (!GetParam().isCXX14OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 1'2'0ull; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-IntegerLiteralExpression |
| | | `-1'2'0ull |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, CharacterLiteral) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 'a'; |
| '\n'; |
| '\x20'; |
| '\0'; |
| L'a'; |
| L'α'; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-'a' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-'\n' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-'\x20' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-'\0' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-L'a' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-L'α' |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, CharacterLiteralUtf) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| u'a'; |
| u'構'; |
| U'a'; |
| U'🌲'; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-u'a' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-u'構' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-U'a' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-U'🌲' |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) { |
| if (!GetParam().isCXX17OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| u8'a'; |
| u8'\x7f'; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-u8'a' |
| | `-; |
| |-ExpressionStatement |
| | |-CharacterLiteralExpression |
| | | `-u8'\x7f' |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, FloatingLiteral) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 1e-2; |
| 2.; |
| .2; |
| 2.f; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-1e-2 |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-2. |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-.2 |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-2.f |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) { |
| if (!GetParam().isCXX17OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| 0xfp1; |
| 0xf.p1; |
| 0x.fp1; |
| 0xf.fp1f; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-0xfp1 |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-0xf.p1 |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-0x.fp1 |
| | `-; |
| |-ExpressionStatement |
| | |-FloatingLiteralExpression |
| | | `-0xf.fp1f |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, StringLiteral) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| "a\n\0\x20"; |
| L"αβ"; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-StringLiteralExpression |
| | | `-"a\n\0\x20" |
| | `-; |
| |-ExpressionStatement |
| | |-StringLiteralExpression |
| | | `-L"αβ" |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, StringLiteralUtf) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| u8"a\x1f\x05"; |
| u"C++抽象構文木"; |
| U"📖🌲\n"; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-StringLiteralExpression |
| | | `-u8"a\x1f\x05" |
| | `-; |
| |-ExpressionStatement |
| | |-StringLiteralExpression |
| | | `-u"C++抽象構文木" |
| | `-; |
| |-ExpressionStatement |
| | |-StringLiteralExpression |
| | | `-U"📖🌲\n" |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, StringLiteralRaw) { |
| 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\n" |
| "`-SimpleDeclaration\n" |
| " |-void\n" |
| " |-SimpleDeclarator\n" |
| " | |-test\n" |
| " | `-ParametersAndQualifiers\n" |
| " | |-(\n" |
| " | `-)\n" |
| " `-CompoundStatement\n" |
| " |-{\n" |
| " |-ExpressionStatement\n" |
| " | |-StringLiteralExpression\n" |
| " | | `-R\"SyntaxTree(\n" |
| " Hello \"Syntax\" \\\"\n" |
| " )SyntaxTree\"\n" |
| " | `-;\n" |
| " `-}\n")); |
| } |
| |
| TEST_P(SyntaxTreeTest, BoolLiteral) { |
| if (GetParam().isC()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| true; |
| false; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-BoolLiteralExpression |
| | | `-true |
| | `-; |
| |-ExpressionStatement |
| | |-BoolLiteralExpression |
| | | `-false |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test() { |
| nullptr; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-CxxNullPtrExpression |
| | | `-nullptr |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a) { |
| a++; |
| a--; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-PostfixUnaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | `-++ |
| | `-; |
| |-ExpressionStatement |
| | |-PostfixUnaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | `--- |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, PrefixUnaryOperator) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a, int *ap) { |
| --a; ++a; |
| ~a; |
| -a; |
| +a; |
| &a; |
| *ap; |
| !a; |
| __real a; __imag a; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-* |
| | | `-ap |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |--- |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-++ |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-~ |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-- |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-+ |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-& |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-* |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-ap |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-! |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-__real |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-__imag |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a, bool b) { |
| compl a; |
| not b; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-bool |
| | | `-SimpleDeclarator |
| | | `-b |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-compl |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-a |
| | `-; |
| |-ExpressionStatement |
| | |-PrefixUnaryOperatorExpression |
| | | |-not |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-b |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, BinaryOperator) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a) { |
| 1 - 2; |
| 1 == 2; |
| a = 1; |
| a <<= 1; |
| 1 || 0; |
| 1 & 2; |
| a ^= 3; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | |-- |
| | | `-IntegerLiteralExpression |
| | | `-2 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | |-== |
| | | `-IntegerLiteralExpression |
| | | `-2 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-1 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | |-<<= |
| | | `-IntegerLiteralExpression |
| | | `-1 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | |-|| |
| | | `-IntegerLiteralExpression |
| | | `-0 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | |-& |
| | | `-IntegerLiteralExpression |
| | | `-2 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | |-^= |
| | | `-IntegerLiteralExpression |
| | | `-3 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, BinaryOperatorCxx) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a) { |
| true || false; |
| true or false; |
| 1 bitand 2; |
| a xor_eq 3; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-BoolLiteralExpression |
| | | | `-true |
| | | |-|| |
| | | `-BoolLiteralExpression |
| | | `-false |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-BoolLiteralExpression |
| | | | `-true |
| | | |-or |
| | | `-BoolLiteralExpression |
| | | `-false |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | |-bitand |
| | | `-IntegerLiteralExpression |
| | | `-2 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | |-xor_eq |
| | | `-IntegerLiteralExpression |
| | | `-3 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, NestedBinaryOperator) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void test(int a, int b) { |
| (1 + 2) * (4 / 2); |
| a + b + 42; |
| a = b = 42; |
| a + b * 4 + 2; |
| a % 2 + b * 42; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | `-b |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-ParenExpression |
| | | | |-( |
| | | | |-BinaryOperatorExpression |
| | | | | |-IntegerLiteralExpression |
| | | | | | `-1 |
| | | | | |-+ |
| | | | | `-IntegerLiteralExpression |
| | | | | `-2 |
| | | | `-) |
| | | |-* |
| | | `-ParenExpression |
| | | |-( |
| | | |-BinaryOperatorExpression |
| | | | |-IntegerLiteralExpression |
| | | | | `-4 |
| | | | |-/ |
| | | | `-IntegerLiteralExpression |
| | | | `-2 |
| | | `-) |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-BinaryOperatorExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-a |
| | | | |-+ |
| | | | `-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-b |
| | | |-+ |
| | | `-IntegerLiteralExpression |
| | | `-42 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-a |
| | | |-= |
| | | `-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-b |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-42 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-BinaryOperatorExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-a |
| | | | |-+ |
| | | | `-BinaryOperatorExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-b |
| | | | |-* |
| | | | `-IntegerLiteralExpression |
| | | | `-4 |
| | | |-+ |
| | | `-IntegerLiteralExpression |
| | | `-2 |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-BinaryOperatorExpression |
| | | | |-IdExpression |
| | | | | `-UnqualifiedId |
| | | | | `-a |
| | | | |-% |
| | | | `-IntegerLiteralExpression |
| | | | `-2 |
| | | |-+ |
| | | `-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-b |
| | | |-* |
| | | `-IntegerLiteralExpression |
| | | `-42 |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct X { |
| X& operator=(const X&); |
| friend X operator+(X, const X&); |
| friend bool operator<(const X&, const X&); |
| }; |
| void test(X x, X y) { |
| x = y; |
| x + y; |
| x < y; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-SimpleDeclaration |
| | | |-X |
| | | |-SimpleDeclarator |
| | | | |-& |
| | | | |-operator |
| | | | |-= |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | `-) |
| | | `-; |
| | |-UnknownDeclaration |
| | | `-SimpleDeclaration |
| | | |-friend |
| | | |-X |
| | | |-SimpleDeclarator |
| | | | |-operator |
| | | | |-+ |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | |-SimpleDeclaration |
| | | | | `-X |
| | | | |-, |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | `-) |
| | | `-; |
| | |-UnknownDeclaration |
| | | `-SimpleDeclaration |
| | | |-friend |
| | | |-bool |
| | | |-SimpleDeclarator |
| | | | |-operator |
| | | | |-< |
| | | | `-ParametersAndQualifiers |
| | | | |-( |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | |-, |
| | | | |-SimpleDeclaration |
| | | | | |-const |
| | | | | |-X |
| | | | | `-SimpleDeclarator |
| | | | | `-& |
| | | | `-) |
| | | `-; |
| | |-} |
| | `-; |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-X |
| | | `-SimpleDeclarator |
| | | `-x |
| | |-, |
| | |-SimpleDeclaration |
| | | |-X |
| | | `-SimpleDeclarator |
| | | `-y |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-= |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-y |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-UnknownExpression |
| | | | `-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-+ |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-y |
| | `-; |
| |-ExpressionStatement |
| | |-BinaryOperatorExpression |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-x |
| | | |-IdExpression |
| | | | `-UnqualifiedId |
| | | | `-< |
| | | `-IdExpression |
| | | `-UnqualifiedId |
| | | `-y |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int *a, b; |
| int *c, d; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-* |
| | | `-a |
| | |-, |
| | |-SimpleDeclarator |
| | | `-b |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-* |
| | `-c |
| |-, |
| |-SimpleDeclarator |
| | `-d |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| typedef int *a, b; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-typedef |
| |-int |
| |-SimpleDeclarator |
| | |-* |
| | `-a |
| |-, |
| |-SimpleDeclarator |
| | `-b |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void foo() { |
| int *a, b; |
| typedef int *ta, tb; |
| } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-foo |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-DeclarationStatement |
| | |-SimpleDeclaration |
| | | |-int |
| | | |-SimpleDeclarator |
| | | | |-* |
| | | | `-a |
| | | |-, |
| | | `-SimpleDeclarator |
| | | `-b |
| | `-; |
| |-DeclarationStatement |
| | |-SimpleDeclaration |
| | | |-typedef |
| | | |-int |
| | | |-SimpleDeclarator |
| | | | |-* |
| | | | `-ta |
| | | |-, |
| | | `-SimpleDeclarator |
| | | `-tb |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, Namespaces) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| namespace a { namespace b {} } |
| namespace a::b {} |
| namespace {} |
| |
| namespace foo = a; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-NamespaceDefinition |
| | |-namespace |
| | |-a |
| | |-{ |
| | |-NamespaceDefinition |
| | | |-namespace |
| | | |-b |
| | | |-{ |
| | | `-} |
| | `-} |
| |-NamespaceDefinition |
| | |-namespace |
| | |-a |
| | |-:: |
| | |-b |
| | |-{ |
| | `-} |
| |-NamespaceDefinition |
| | |-namespace |
| | |-{ |
| | `-} |
| `-NamespaceAliasDefinition |
| |-namespace |
| |-foo |
| |-= |
| |-a |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UsingDirective) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| namespace ns {} |
| using namespace ::ns; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-NamespaceDefinition |
| | |-namespace |
| | |-ns |
| | |-{ |
| | `-} |
| `-UsingNamespaceDirective |
| |-using |
| |-namespace |
| |-:: |
| |-ns |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UsingDeclaration) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| namespace ns { int a; } |
| using ns::a; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-NamespaceDefinition |
| | |-namespace |
| | |-ns |
| | |-{ |
| | |-SimpleDeclaration |
| | | |-int |
| | | |-SimpleDeclarator |
| | | | `-a |
| | | `-; |
| | `-} |
| `-UsingDeclaration |
| |-using |
| |-ns |
| |-:: |
| |-a |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, FreeStandingClasses) { |
| // Free-standing classes, must live inside a SimpleDeclaration. |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct X; |
| struct X {}; |
| |
| struct Y *y1; |
| struct Y {} *y2; |
| |
| struct {} *a1; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | `-; |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-} |
| | `-; |
| |-SimpleDeclaration |
| | |-struct |
| | |-Y |
| | |-SimpleDeclarator |
| | | |-* |
| | | `-y1 |
| | `-; |
| |-SimpleDeclaration |
| | |-struct |
| | |-Y |
| | |-{ |
| | |-} |
| | |-SimpleDeclarator |
| | | |-* |
| | | `-y2 |
| | `-; |
| `-SimpleDeclaration |
| |-struct |
| |-{ |
| |-} |
| |-SimpleDeclarator |
| | |-* |
| | `-a1 |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, Templates) { |
| 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(treeDumpEqual( |
| R"cpp( |
| template <class T> struct cls {}; |
| template <class T> int var = 10; |
| template <class T> int fun() {} |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-struct |
| | |-cls |
| | |-{ |
| | |-} |
| | `-; |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-var |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-10 |
| | `-; |
| `-TemplateDeclaration |
| |-template |
| |-< |
| |-UnknownDeclaration |
| | |-class |
| | `-T |
| |-> |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-fun |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, NestedTemplates) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| template <class T> |
| struct X { |
| template <class U> |
| U foo(); |
| }; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-TemplateDeclaration |
| |-template |
| |-< |
| |-UnknownDeclaration |
| | |-class |
| | `-T |
| |-> |
| `-SimpleDeclaration |
| |-struct |
| |-X |
| |-{ |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-U |
| | |-> |
| | `-SimpleDeclaration |
| | |-U |
| | |-SimpleDeclarator |
| | | |-foo |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | `-) |
| | `-; |
| |-} |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, Templates2) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| template <class T> struct X { struct Y; }; |
| template <class T> struct X<T>::Y {}; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-SimpleDeclaration |
| | | |-struct |
| | | |-Y |
| | | `-; |
| | |-} |
| | `-; |
| `-TemplateDeclaration |
| |-template |
| |-< |
| |-UnknownDeclaration |
| | |-class |
| | `-T |
| |-> |
| `-SimpleDeclaration |
| |-struct |
| |-X |
| |-< |
| |-T |
| |-> |
| |-:: |
| |-Y |
| |-{ |
| |-} |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| template <class T> struct X { |
| using T::foo; |
| using typename T::bar; |
| }; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-TemplateDeclaration |
| |-template |
| |-< |
| |-UnknownDeclaration |
| | |-class |
| | `-T |
| |-> |
| `-SimpleDeclaration |
| |-struct |
| |-X |
| |-{ |
| |-UsingDeclaration |
| | |-using |
| | |-T |
| | |-:: |
| | |-foo |
| | `-; |
| |-UsingDeclaration |
| | |-using |
| | |-typename |
| | |-T |
| | |-:: |
| | |-bar |
| | `-; |
| |-} |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| template <class T> struct X {}; |
| template <class T> struct X<T*> {}; |
| template <> struct X<int> {}; |
| |
| template struct X<double>; |
| extern template struct X<float>; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-} |
| | `-; |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-UnknownDeclaration |
| | | |-class |
| | | `-T |
| | |-> |
| | `-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-< |
| | |-T |
| | |-* |
| | |-> |
| | |-{ |
| | |-} |
| | `-; |
| |-TemplateDeclaration |
| | |-template |
| | |-< |
| | |-> |
| | `-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-< |
| | |-int |
| | |-> |
| | |-{ |
| | |-} |
| | `-; |
| |-ExplicitTemplateInstantiation |
| | |-template |
| | `-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-< |
| | |-double |
| | |-> |
| | `-; |
| `-ExplicitTemplateInstantiation |
| |-extern |
| |-template |
| `-SimpleDeclaration |
| |-struct |
| |-X |
| |-< |
| |-float |
| |-> |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, UsingType) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| using type = int; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-TypeAliasDeclaration |
| |-using |
| |-type |
| |-= |
| |-int |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, EmptyDeclaration) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| ; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-EmptyDeclaration |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, StaticAssert) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| static_assert(true, "message"); |
| static_assert(true); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-StaticAssertDeclaration |
| | |-static_assert |
| | |-( |
| | |-BoolLiteralExpression |
| | | `-true |
| | |-, |
| | |-StringLiteralExpression |
| | | `-"message" |
| | |-) |
| | `-; |
| `-StaticAssertDeclaration |
| |-static_assert |
| |-( |
| |-BoolLiteralExpression |
| | `-true |
| |-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ExternC) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| extern "C" int a; |
| extern "C" { int b; int c; } |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-LinkageSpecificationDeclaration |
| | |-extern |
| | |-"C" |
| | `-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | `-a |
| | `-; |
| `-LinkageSpecificationDeclaration |
| |-extern |
| |-"C" |
| |-{ |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | `-b |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | `-c |
| | `-; |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, NonModifiableNodes) { |
| // Some nodes are non-modifiable, they are marked with 'I:'. |
| 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 |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-IfStatement |
| | |-I: if |
| | |-I: ( |
| | |-I: BinaryOperatorExpression |
| | | |-I: IntegerLiteralExpression |
| | | | `-I: 1 |
| | | |-I: + |
| | | `-I: IntegerLiteralExpression |
| | | `-I: 1 |
| | |-I: ) |
| | |-I: CompoundStatement |
| | | |-I: { |
| | | `-I: } |
| | |-else |
| | `-CompoundStatement |
| | |-{ |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ModifiableNodes) { |
| // 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 |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-test |
| | `-ParametersAndQualifiers |
| | |-( |
| | `-) |
| `-CompoundStatement |
| |-{ |
| |-CompoundStatement |
| | |-{ |
| | |-ExpressionStatement |
| | | |-IntegerLiteralExpression |
| | | | `-1 |
| | | `-; |
| | `-} |
| |-CompoundStatement |
| | |-{ |
| | |-ExpressionStatement |
| | | |-IntegerLiteralExpression |
| | | | `-2 |
| | | `-; |
| | `-} |
| `-} |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int a[10]; |
| int b[1][2][3]; |
| int c[] = {1,2,3}; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-a |
| | | `-ArraySubscript |
| | | |-[ |
| | | |-IntegerLiteralExpression |
| | | | `-10 |
| | | `-] |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-b |
| | | |-ArraySubscript |
| | | | |-[ |
| | | | |-IntegerLiteralExpression |
| | | | | `-1 |
| | | | `-] |
| | | |-ArraySubscript |
| | | | |-[ |
| | | | |-IntegerLiteralExpression |
| | | | | `-2 |
| | | | `-] |
| | | `-ArraySubscript |
| | | |-[ |
| | | |-IntegerLiteralExpression |
| | | | `-3 |
| | | `-] |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-c |
| | |-ArraySubscript |
| | | |-[ |
| | | `-] |
| | |-= |
| | `-UnknownExpression |
| | `-UnknownExpression |
| | |-{ |
| | |-IntegerLiteralExpression |
| | | `-1 |
| | |-, |
| | |-IntegerLiteralExpression |
| | | `-2 |
| | |-, |
| | |-IntegerLiteralExpression |
| | | `-3 |
| | `-} |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { |
| if (!GetParam().isC99OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void f(int xs[static 10]); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-f |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-xs |
| | | `-ArraySubscript |
| | | |-[ |
| | | |-static |
| | | |-IntegerLiteralExpression |
| | | | `-10 |
| | | `-] |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int func1(); |
| int func2a(int a); |
| int func2b(int); |
| int func3a(int *ap); |
| int func3b(int *); |
| int func4a(int a, float b); |
| int func4b(int, float); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func1 |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func2a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-a |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func2b |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func3a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | |-* |
| | | | `-ap |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func3b |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-* |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func4a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-a |
| | | |-, |
| | | |-SimpleDeclaration |
| | | | |-float |
| | | | `-SimpleDeclarator |
| | | | `-b |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-func4b |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | `-int |
| | |-, |
| | |-SimpleDeclaration |
| | | `-float |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int func1(const int a, volatile int b, const volatile int c); |
| int func2(int& a); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-func1 |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-const |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-a |
| | | |-, |
| | | |-SimpleDeclaration |
| | | | |-volatile |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-b |
| | | |-, |
| | | |-SimpleDeclaration |
| | | | |-const |
| | | | |-volatile |
| | | | |-int |
| | | | `-SimpleDeclarator |
| | | | `-c |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-func2 |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-& |
| | | `-a |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int func1(int&& a); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-func1 |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-int |
| | | `-SimpleDeclarator |
| | | |-&& |
| | | `-a |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct Test { |
| int a(); |
| int b() const; |
| int c() volatile; |
| int d() const volatile; |
| int e() &; |
| int f() &&; |
| }; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-struct |
| |-Test |
| |-{ |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-b |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | `-const |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-c |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | `-volatile |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-d |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | |-const |
| | | `-volatile |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-e |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | `-& |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-f |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | `-&& |
| | `-; |
| |-} |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, TrailingReturn) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| auto foo() -> int; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-auto |
| |-SimpleDeclarator |
| | |-foo |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-) |
| | `-TrailingReturnType |
| | |--> |
| | `-int |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { |
| if (!GetParam().supportsCXXDynamicExceptionSpecification()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct MyException1 {}; |
| struct MyException2 {}; |
| int a() throw(); |
| int b() throw(...); |
| int c() throw(MyException1); |
| int d() throw(MyException1, MyException2); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-MyException1 |
| | |-{ |
| | |-} |
| | `-; |
| |-SimpleDeclaration |
| | |-struct |
| | |-MyException2 |
| | |-{ |
| | |-} |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | |-throw |
| | | |-( |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-b |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | |-throw |
| | | |-( |
| | | |-... |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-c |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | |-throw |
| | | |-( |
| | | |-MyException1 |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-d |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-) |
| | |-throw |
| | |-( |
| | |-MyException1 |
| | |-, |
| | |-MyException2 |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int a() noexcept; |
| int b() noexcept(true); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-a |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-) |
| | | `-noexcept |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-b |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-) |
| | |-noexcept |
| | |-( |
| | |-BoolLiteralExpression |
| | | `-true |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| int (a); |
| int *(b); |
| int (*c)(int); |
| int *(d)(int); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | `-ParenDeclarator |
| | | |-( |
| | | |-a |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-* |
| | | `-ParenDeclarator |
| | | |-( |
| | | |-b |
| | | `-) |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-ParenDeclarator |
| | | | |-( |
| | | | |-* |
| | | | |-c |
| | | | `-) |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | `-) |
| | `-; |
| `-SimpleDeclaration |
| |-int |
| |-SimpleDeclarator |
| | |-* |
| | |-ParenDeclarator |
| | | |-( |
| | | |-d |
| | | `-) |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | `-int |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| const int west = -1; |
| int const east = 1; |
| const int const universal = 0; |
| const int const *const *volatile b; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-const |
| | |-int |
| | |-SimpleDeclarator |
| | | |-west |
| | | |-= |
| | | `-PrefixUnaryOperatorExpression |
| | | |-- |
| | | `-IntegerLiteralExpression |
| | | `-1 |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-const |
| | |-SimpleDeclarator |
| | | |-east |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-1 |
| | `-; |
| |-SimpleDeclaration |
| | |-const |
| | |-int |
| | |-const |
| | |-SimpleDeclarator |
| | | |-universal |
| | | |-= |
| | | `-IntegerLiteralExpression |
| | | `-0 |
| | `-; |
| `-SimpleDeclaration |
| |-const |
| |-int |
| |-const |
| |-SimpleDeclarator |
| | |-* |
| | |-const |
| | |-* |
| | |-volatile |
| | `-b |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| auto foo() -> auto(*)(int) -> double*; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-auto |
| |-SimpleDeclarator |
| | |-foo |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-) |
| | `-TrailingReturnType |
| | |--> |
| | |-auto |
| | `-SimpleDeclarator |
| | |-ParenDeclarator |
| | | |-( |
| | | |-* |
| | | `-) |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | `-int |
| | |-) |
| | `-TrailingReturnType |
| | |--> |
| | |-double |
| | `-SimpleDeclarator |
| | `-* |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, MemberPointers) { |
| if (!GetParam().isCXX()) { |
| return; |
| } |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| struct X {}; |
| int X::* a; |
| const int X::* b; |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| |-SimpleDeclaration |
| | |-struct |
| | |-X |
| | |-{ |
| | |-} |
| | `-; |
| |-SimpleDeclaration |
| | |-int |
| | |-SimpleDeclarator |
| | | |-MemberPointer |
| | | | |-X |
| | | | |-:: |
| | | | `-* |
| | | `-a |
| | `-; |
| `-SimpleDeclaration |
| |-const |
| |-int |
| |-SimpleDeclarator |
| | |-MemberPointer |
| | | |-X |
| | | |-:: |
| | | `-* |
| | `-b |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ComplexDeclarator) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void x(char a, short (*b)(int)); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-x |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-char |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-short |
| | | `-SimpleDeclarator |
| | | |-ParenDeclarator |
| | | | |-( |
| | | | |-* |
| | | | |-b |
| | | | `-) |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | `-) |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, ComplexDeclarator2) { |
| EXPECT_TRUE(treeDumpEqual( |
| R"cpp( |
| void x(char a, short (*b)(int), long (**c)(long long)); |
| )cpp", |
| R"txt( |
| *: TranslationUnit |
| `-SimpleDeclaration |
| |-void |
| |-SimpleDeclarator |
| | |-x |
| | `-ParametersAndQualifiers |
| | |-( |
| | |-SimpleDeclaration |
| | | |-char |
| | | `-SimpleDeclarator |
| | | `-a |
| | |-, |
| | |-SimpleDeclaration |
| | | |-short |
| | | `-SimpleDeclarator |
| | | |-ParenDeclarator |
| | | | |-( |
| | | | |-* |
| | | | |-b |
| | | | `-) |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | `-int |
| | | `-) |
| | |-, |
| | |-SimpleDeclaration |
| | | |-long |
| | | `-SimpleDeclarator |
| | | |-ParenDeclarator |
| | | | |-( |
| | | | |-* |
| | | | |-* |
| | | | |-c |
| | | | `-) |
| | | `-ParametersAndQualifiers |
| | | |-( |
| | | |-SimpleDeclaration |
| | | | |-long |
| | | | `-long |
| | | `-) |
| | `-) |
| `-; |
| )txt")); |
| } |
| |
| TEST_P(SyntaxTreeTest, Mutations) { |
| if (!GetParam().isCXX11OrLater()) { |
| return; |
| } |
| |
| using Transformation = std::function<void( |
| const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; |
| auto CheckTransformation = [this](std::string Input, std::string Expected, |
| Transformation Transform) -> void { |
| llvm::Annotations Source(Input); |
| auto *Root = buildTree(Source.code(), GetParam()); |
| |
| Transform(Source, Root); |
| |
| auto Replacements = syntax::computeReplacements(*Arena, *Root); |
| auto Output = tooling::applyAllReplacements(Source.code(), Replacements); |
| if (!Output) { |
| ADD_FAILURE() << "could not apply replacements: " |
| << llvm::toString(Output.takeError()); |
| return; |
| } |
| |
| EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; |
| }; |
| |
| // Removes the selected statement. Input should have exactly one selected |
| // range and it should correspond to a single statement. |
| auto RemoveStatement = [this](const llvm::Annotations &Input, |
| syntax::TranslationUnit *TU) { |
| auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); |
| ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; |
| syntax::removeStatement(*Arena, S); |
| EXPECT_TRUE(S->isDetached()); |
| EXPECT_FALSE(S->isOriginal()) |
| << "node removed from tree cannot be marked as original"; |
| }; |
| |
| std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> |
| Cases = { |
| {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, |
| {"void test() { if (true) [[{}]] else {} }", |
| "void test() { if (true) ; else {} }"}, |
| {"void test() { [[;]] }", "void test() { }"}}; |
| for (const auto &C : Cases) |
| CheckTransformation(C.first, C.second, RemoveStatement); |
| } |
| |
| TEST_P(SyntaxTreeTest, SynthesizedNodes) { |
| buildTree("", GetParam()); |
| |
| auto *C = syntax::createPunctuation(*Arena, tok::comma); |
| ASSERT_NE(C, nullptr); |
| EXPECT_EQ(C->token()->kind(), tok::comma); |
| EXPECT_TRUE(C->canModify()); |
| EXPECT_FALSE(C->isOriginal()); |
| EXPECT_TRUE(C->isDetached()); |
| |
| auto *S = syntax::createEmptyStatement(*Arena); |
| ASSERT_NE(S, nullptr); |
| EXPECT_TRUE(S->canModify()); |
| EXPECT_FALSE(S->isOriginal()); |
| EXPECT_TRUE(S->isDetached()); |
| } |
| |
| static std::vector<TestClangConfig> allTestClangConfigs() { |
| std::vector<TestClangConfig> all_configs; |
| for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, |
| Lang_CXX14, Lang_CXX17, Lang_CXX20}) { |
| TestClangConfig config; |
| config.Language = lang; |
| config.Target = "x86_64-pc-linux-gnu"; |
| all_configs.push_back(config); |
| |
| // Windows target is interesting to test because it enables |
| // `-fdelayed-template-parsing`. |
| config.Target = "x86_64-pc-win32-msvc"; |
| all_configs.push_back(config); |
| } |
| return all_configs; |
| } |
| |
| INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, |
| testing::ValuesIn(allTestClangConfigs()), ); |
| |
| } // namespace |