4243 lines
77 KiB
C++
4243 lines
77 KiB
C++
//===- 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, UserDefinedLiteral) {
|
||
if (!GetParam().isCXX11OrLater()) {
|
||
return;
|
||
}
|
||
EXPECT_TRUE(treeDumpEqual(
|
||
R"cpp(
|
||
typedef decltype(sizeof(void *)) size_t;
|
||
|
||
unsigned operator "" _i(unsigned long long);
|
||
unsigned operator "" _f(long double);
|
||
unsigned operator "" _c(char);
|
||
unsigned operator "" _s(const char*, size_t);
|
||
unsigned operator "" _r(const char*);
|
||
template <char...>
|
||
unsigned operator "" _t();
|
||
|
||
void test() {
|
||
12_i; // call: operator "" _i(12uLL) | kind: integer
|
||
1.2_f; // call: operator "" _f(1.2L) | kind: float
|
||
'2'_c; // call: operator "" _c('2') | kind: char
|
||
"12"_s; // call: operator "" _s("12") | kind: string
|
||
|
||
12_r; // call: operator "" _r("12") | kind: integer
|
||
1.2_r; // call: operator "" _i("1.2") | kind: float
|
||
12_t; // call: operator<'1', '2'> "" _x() | kind: integer
|
||
1.2_t; // call: operator<'1', '2'> "" _x() | kind: float
|
||
}
|
||
)cpp",
|
||
R"txt(
|
||
*: TranslationUnit
|
||
|-SimpleDeclaration
|
||
| |-typedef
|
||
| |-decltype
|
||
| |-(
|
||
| |-UnknownExpression
|
||
| | |-sizeof
|
||
| | |-(
|
||
| | |-void
|
||
| | |-*
|
||
| | `-)
|
||
| |-)
|
||
| |-SimpleDeclarator
|
||
| | `-size_t
|
||
| `-;
|
||
|-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_i
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | |-SimpleDeclaration
|
||
| | | |-unsigned
|
||
| | | |-long
|
||
| | | `-long
|
||
| | `-)
|
||
| `-;
|
||
|-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_f
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | |-SimpleDeclaration
|
||
| | | |-long
|
||
| | | `-double
|
||
| | `-)
|
||
| `-;
|
||
|-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_c
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | |-SimpleDeclaration
|
||
| | | `-char
|
||
| | `-)
|
||
| `-;
|
||
|-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_s
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | |-SimpleDeclaration
|
||
| | | |-const
|
||
| | | |-char
|
||
| | | `-SimpleDeclarator
|
||
| | | `-*
|
||
| | |-,
|
||
| | |-SimpleDeclaration
|
||
| | | `-size_t
|
||
| | `-)
|
||
| `-;
|
||
|-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_r
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | |-SimpleDeclaration
|
||
| | | |-const
|
||
| | | |-char
|
||
| | | `-SimpleDeclarator
|
||
| | | `-*
|
||
| | `-)
|
||
| `-;
|
||
|-TemplateDeclaration
|
||
| |-template
|
||
| |-<
|
||
| |-SimpleDeclaration
|
||
| | `-char
|
||
| |-...
|
||
| |->
|
||
| `-SimpleDeclaration
|
||
| |-unsigned
|
||
| |-SimpleDeclarator
|
||
| | |-operator
|
||
| | |-""
|
||
| | |-_t
|
||
| | `-ParametersAndQualifiers
|
||
| | |-(
|
||
| | `-)
|
||
| `-;
|
||
`-SimpleDeclaration
|
||
|-void
|
||
|-SimpleDeclarator
|
||
| |-test
|
||
| `-ParametersAndQualifiers
|
||
| |-(
|
||
| `-)
|
||
`-CompoundStatement
|
||
|-{
|
||
|-ExpressionStatement
|
||
| |-IntegerUserDefinedLiteralExpression
|
||
| | `-12_i
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-FloatUserDefinedLiteralExpression
|
||
| | `-1.2_f
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-CharUserDefinedLiteralExpression
|
||
| | `-'2'_c
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-StringUserDefinedLiteralExpression
|
||
| | `-"12"_s
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-IntegerUserDefinedLiteralExpression
|
||
| | `-12_r
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-FloatUserDefinedLiteralExpression
|
||
| | `-1.2_r
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-IntegerUserDefinedLiteralExpression
|
||
| | `-12_t
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-FloatUserDefinedLiteralExpression
|
||
| | `-1.2_t
|
||
| `-;
|
||
`-}
|
||
)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&);
|
||
friend X operator<<(X&, const X&);
|
||
X operator,(X&);
|
||
// TODO: Fix crash on member function pointer and add a test for `->*`
|
||
// TODO: Unbox operators in syntax tree.
|
||
// Represent operators by `+` instead of `IdExpression-UnqualifiedId-+`
|
||
};
|
||
void test(X x, X y) {
|
||
x = y;
|
||
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
|
||
| | | | `-&
|
||
| | | `-)
|
||
| | `-;
|
||
| |-UnknownDeclaration
|
||
| | `-SimpleDeclaration
|
||
| | |-friend
|
||
| | |-X
|
||
| | |-SimpleDeclarator
|
||
| | | |-operator
|
||
| | | |-<<
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | |-SimpleDeclaration
|
||
| | | | |-X
|
||
| | | | `-SimpleDeclarator
|
||
| | | | `-&
|
||
| | | |-,
|
||
| | | |-SimpleDeclaration
|
||
| | | | |-const
|
||
| | | | |-X
|
||
| | | | `-SimpleDeclarator
|
||
| | | | `-&
|
||
| | | `-)
|
||
| | `-;
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | |-SimpleDeclarator
|
||
| | | |-operator
|
||
| | | |-,
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | |-SimpleDeclaration
|
||
| | | | |-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
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-BinaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-x
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-<<
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-y
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-BinaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-x
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-,
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-y
|
||
| `-;
|
||
`-}
|
||
)txt"));
|
||
}
|
||
|
||
TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
|
||
if (!GetParam().isCXX()) {
|
||
return;
|
||
}
|
||
EXPECT_TRUE(treeDumpEqual(
|
||
R"cpp(
|
||
struct X {
|
||
X operator++();
|
||
bool operator!();
|
||
X* operator&();
|
||
};
|
||
void test(X x) {
|
||
++x;
|
||
!x;
|
||
&x;
|
||
}
|
||
)cpp",
|
||
R"txt(
|
||
*: TranslationUnit
|
||
|-SimpleDeclaration
|
||
| |-struct
|
||
| |-X
|
||
| |-{
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | |-SimpleDeclarator
|
||
| | | |-operator
|
||
| | | |-++
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | `-)
|
||
| | `-;
|
||
| |-SimpleDeclaration
|
||
| | |-bool
|
||
| | |-SimpleDeclarator
|
||
| | | |-operator
|
||
| | | |-!
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | `-)
|
||
| | `-;
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | |-SimpleDeclarator
|
||
| | | |-*
|
||
| | | |-operator
|
||
| | | |-&
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | `-)
|
||
| | `-;
|
||
| |-}
|
||
| `-;
|
||
`-SimpleDeclaration
|
||
|-void
|
||
|-SimpleDeclarator
|
||
| |-test
|
||
| `-ParametersAndQualifiers
|
||
| |-(
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | `-SimpleDeclarator
|
||
| | `-x
|
||
| `-)
|
||
`-CompoundStatement
|
||
|-{
|
||
|-ExpressionStatement
|
||
| |-PrefixUnaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-++
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-x
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-PrefixUnaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-!
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-x
|
||
| `-;
|
||
|-ExpressionStatement
|
||
| |-PrefixUnaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-&
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-x
|
||
| `-;
|
||
`-}
|
||
)txt"));
|
||
}
|
||
|
||
TEST_P(SyntaxTreeTest, UserDefinedUnaryPostfixOperator) {
|
||
if (!GetParam().isCXX()) {
|
||
return;
|
||
}
|
||
EXPECT_TRUE(treeDumpEqual(
|
||
R"cpp(
|
||
struct X {
|
||
X operator++(int);
|
||
};
|
||
void test(X x) {
|
||
x++;
|
||
}
|
||
)cpp",
|
||
R"txt(
|
||
*: TranslationUnit
|
||
|-SimpleDeclaration
|
||
| |-struct
|
||
| |-X
|
||
| |-{
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | |-SimpleDeclarator
|
||
| | | |-operator
|
||
| | | |-++
|
||
| | | `-ParametersAndQualifiers
|
||
| | | |-(
|
||
| | | |-SimpleDeclaration
|
||
| | | | `-int
|
||
| | | `-)
|
||
| | `-;
|
||
| |-}
|
||
| `-;
|
||
`-SimpleDeclaration
|
||
|-void
|
||
|-SimpleDeclarator
|
||
| |-test
|
||
| `-ParametersAndQualifiers
|
||
| |-(
|
||
| |-SimpleDeclaration
|
||
| | |-X
|
||
| | `-SimpleDeclarator
|
||
| | `-x
|
||
| `-)
|
||
`-CompoundStatement
|
||
|-{
|
||
|-ExpressionStatement
|
||
| |-PostfixUnaryOperatorExpression
|
||
| | |-IdExpression
|
||
| | | `-UnqualifiedId
|
||
| | | `-x
|
||
| | `-IdExpression
|
||
| | `-UnqualifiedId
|
||
| | `-++
|
||
| `-;
|
||
`-}
|
||
)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
|