1 //===- TreeTest.cpp -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "clang/Tooling/Syntax/Tree.h"
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/AST/Stmt.h"
13 #include "clang/Basic/LLVM.h"
14 #include "clang/Basic/TokenKinds.h"
15 #include "clang/Frontend/CompilerInstance.h"
16 #include "clang/Frontend/CompilerInvocation.h"
17 #include "clang/Frontend/FrontendAction.h"
18 #include "clang/Frontend/TextDiagnosticPrinter.h"
19 #include "clang/Lex/PreprocessorOptions.h"
20 #include "clang/Testing/CommandLineArgs.h"
21 #include "clang/Testing/TestClangConfig.h"
22 #include "clang/Tooling/Core/Replacement.h"
23 #include "clang/Tooling/Syntax/BuildTree.h"
24 #include "clang/Tooling/Syntax/Mutations.h"
25 #include "clang/Tooling/Syntax/Nodes.h"
26 #include "clang/Tooling/Syntax/Tokens.h"
27 #include "clang/Tooling/Tooling.h"
28 #include "llvm/ADT/ArrayRef.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/Error.h"
34 #include "llvm/Testing/Support/Annotations.h"
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 #include <cstdlib>
38
39 using namespace clang;
40
41 namespace {
tokens(syntax::Node * N)42 static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) {
43 assert(N->isOriginal() && "tokens of modified nodes are not well-defined");
44 if (auto *L = dyn_cast<syntax::Leaf>(N))
45 return llvm::makeArrayRef(L->token(), 1);
46 auto *T = cast<syntax::Tree>(N);
47 return llvm::makeArrayRef(T->firstLeaf()->token(),
48 T->lastLeaf()->token() + 1);
49 }
50
51 class SyntaxTreeTest : public ::testing::Test,
52 public ::testing::WithParamInterface<TestClangConfig> {
53 protected:
54 // Build a syntax tree for the code.
buildTree(llvm::StringRef Code,const TestClangConfig & ClangConfig)55 syntax::TranslationUnit *buildTree(llvm::StringRef Code,
56 const TestClangConfig &ClangConfig) {
57 // FIXME: this code is almost the identical to the one in TokensTest. Share
58 // it.
59 class BuildSyntaxTree : public ASTConsumer {
60 public:
61 BuildSyntaxTree(syntax::TranslationUnit *&Root,
62 std::unique_ptr<syntax::Arena> &Arena,
63 std::unique_ptr<syntax::TokenCollector> Tokens)
64 : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) {
65 assert(this->Tokens);
66 }
67
68 void HandleTranslationUnit(ASTContext &Ctx) override {
69 Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
70 Ctx.getLangOpts(),
71 std::move(*Tokens).consume());
72 Tokens = nullptr; // make sure we fail if this gets called twice.
73 Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl());
74 }
75
76 private:
77 syntax::TranslationUnit *&Root;
78 std::unique_ptr<syntax::Arena> &Arena;
79 std::unique_ptr<syntax::TokenCollector> Tokens;
80 };
81
82 class BuildSyntaxTreeAction : public ASTFrontendAction {
83 public:
84 BuildSyntaxTreeAction(syntax::TranslationUnit *&Root,
85 std::unique_ptr<syntax::Arena> &Arena)
86 : Root(Root), Arena(Arena) {}
87
88 std::unique_ptr<ASTConsumer>
89 CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
90 // We start recording the tokens, ast consumer will take on the result.
91 auto Tokens =
92 std::make_unique<syntax::TokenCollector>(CI.getPreprocessor());
93 return std::make_unique<BuildSyntaxTree>(Root, Arena,
94 std::move(Tokens));
95 }
96
97 private:
98 syntax::TranslationUnit *&Root;
99 std::unique_ptr<syntax::Arena> &Arena;
100 };
101
102 constexpr const char *FileName = "./input.cpp";
103 FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy(""));
104
105 if (!Diags->getClient())
106 Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagOpts.get()));
107 Diags->setSeverityForGroup(diag::Flavor::WarningOrError, "unused-value",
108 diag::Severity::Ignored, SourceLocation());
109
110 // Prepare to run a compiler.
111 std::vector<std::string> Args = {
112 "syntax-test",
113 "-fsyntax-only",
114 };
115 llvm::copy(ClangConfig.getCommandLineArgs(), std::back_inserter(Args));
116 Args.push_back(FileName);
117
118 std::vector<const char *> ArgsCStr;
119 for (const std::string &arg : Args) {
120 ArgsCStr.push_back(arg.c_str());
121 }
122
123 Invocation = createInvocationFromCommandLine(ArgsCStr, Diags, FS);
124 assert(Invocation);
125 Invocation->getFrontendOpts().DisableFree = false;
126 Invocation->getPreprocessorOpts().addRemappedFile(
127 FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release());
128 CompilerInstance Compiler;
129 Compiler.setInvocation(Invocation);
130 Compiler.setDiagnostics(Diags.get());
131 Compiler.setFileManager(FileMgr.get());
132 Compiler.setSourceManager(SourceMgr.get());
133
134 syntax::TranslationUnit *Root = nullptr;
135 BuildSyntaxTreeAction Recorder(Root, this->Arena);
136
137 // Action could not be executed but the frontend didn't identify any errors
138 // in the code ==> problem in setting up the action.
139 if (!Compiler.ExecuteAction(Recorder) &&
140 Diags->getClient()->getNumErrors() == 0) {
141 ADD_FAILURE() << "failed to run the frontend";
142 std::abort();
143 }
144 return Root;
145 }
146
treeDumpEqual(StringRef Code,StringRef Tree)147 ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
148 SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
149
150 auto *Root = buildTree(Code, GetParam());
151 if (Diags->getClient()->getNumErrors() != 0) {
152 return ::testing::AssertionFailure()
153 << "Source file has syntax errors, they were printed to the test "
154 "log";
155 }
156 std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim());
157 // EXPECT_EQ shows the diff between the two strings if they are different.
158 EXPECT_EQ(Tree.trim().str(), Actual);
159 if (Actual != Tree.trim().str()) {
160 return ::testing::AssertionFailure();
161 }
162 return ::testing::AssertionSuccess();
163 }
164
165 // Adds a file to the test VFS.
addFile(llvm::StringRef Path,llvm::StringRef Contents)166 void addFile(llvm::StringRef Path, llvm::StringRef Contents) {
167 if (!FS->addFile(Path, time_t(),
168 llvm::MemoryBuffer::getMemBufferCopy(Contents))) {
169 ADD_FAILURE() << "could not add a file to VFS: " << Path;
170 }
171 }
172
173 /// Finds the deepest node in the tree that covers exactly \p R.
174 /// FIXME: implement this efficiently and move to public syntax tree API.
nodeByRange(llvm::Annotations::Range R,syntax::Node * Root)175 syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) {
176 llvm::ArrayRef<syntax::Token> Toks = tokens(Root);
177
178 if (Toks.front().location().isFileID() &&
179 Toks.back().location().isFileID() &&
180 syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) ==
181 syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End))
182 return Root;
183
184 auto *T = dyn_cast<syntax::Tree>(Root);
185 if (!T)
186 return nullptr;
187 for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) {
188 if (auto *Result = nodeByRange(R, C))
189 return Result;
190 }
191 return nullptr;
192 }
193
194 // Data fields.
195 llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
196 new DiagnosticOptions();
197 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
198 new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get());
199 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
200 new llvm::vfs::InMemoryFileSystem;
201 llvm::IntrusiveRefCntPtr<FileManager> FileMgr =
202 new FileManager(FileSystemOptions(), FS);
203 llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr =
204 new SourceManager(*Diags, *FileMgr);
205 std::shared_ptr<CompilerInvocation> Invocation;
206 // Set after calling buildTree().
207 std::unique_ptr<syntax::Arena> Arena;
208 };
209
TEST_P(SyntaxTreeTest,Simple)210 TEST_P(SyntaxTreeTest, Simple) {
211 EXPECT_TRUE(treeDumpEqual(
212 R"cpp(
213 int main() {}
214 void foo() {}
215 )cpp",
216 R"txt(
217 *: TranslationUnit
218 |-SimpleDeclaration
219 | |-int
220 | |-SimpleDeclarator
221 | | |-main
222 | | `-ParametersAndQualifiers
223 | | |-(
224 | | `-)
225 | `-CompoundStatement
226 | |-{
227 | `-}
228 `-SimpleDeclaration
229 |-void
230 |-SimpleDeclarator
231 | |-foo
232 | `-ParametersAndQualifiers
233 | |-(
234 | `-)
235 `-CompoundStatement
236 |-{
237 `-}
238 )txt"));
239 }
240
TEST_P(SyntaxTreeTest,SimpleVariable)241 TEST_P(SyntaxTreeTest, SimpleVariable) {
242 EXPECT_TRUE(treeDumpEqual(
243 R"cpp(
244 int a;
245 int b = 42;
246 )cpp",
247 R"txt(
248 *: TranslationUnit
249 |-SimpleDeclaration
250 | |-int
251 | |-SimpleDeclarator
252 | | `-a
253 | `-;
254 `-SimpleDeclaration
255 |-int
256 |-SimpleDeclarator
257 | |-b
258 | |-=
259 | `-IntegerLiteralExpression
260 | `-42
261 `-;
262 )txt"));
263 }
264
TEST_P(SyntaxTreeTest,SimpleFunction)265 TEST_P(SyntaxTreeTest, SimpleFunction) {
266 EXPECT_TRUE(treeDumpEqual(
267 R"cpp(
268 void foo(int a, int b) {}
269 )cpp",
270 R"txt(
271 *: TranslationUnit
272 `-SimpleDeclaration
273 |-void
274 |-SimpleDeclarator
275 | |-foo
276 | `-ParametersAndQualifiers
277 | |-(
278 | |-SimpleDeclaration
279 | | |-int
280 | | `-SimpleDeclarator
281 | | `-a
282 | |-,
283 | |-SimpleDeclaration
284 | | |-int
285 | | `-SimpleDeclarator
286 | | `-b
287 | `-)
288 `-CompoundStatement
289 |-{
290 `-}
291 )txt"));
292 }
293
TEST_P(SyntaxTreeTest,If)294 TEST_P(SyntaxTreeTest, If) {
295 EXPECT_TRUE(treeDumpEqual(
296 R"cpp(
297 int main() {
298 if (1) {}
299 if (1) {} else if (0) {}
300 }
301 )cpp",
302 R"txt(
303 *: TranslationUnit
304 `-SimpleDeclaration
305 |-int
306 |-SimpleDeclarator
307 | |-main
308 | `-ParametersAndQualifiers
309 | |-(
310 | `-)
311 `-CompoundStatement
312 |-{
313 |-IfStatement
314 | |-if
315 | |-(
316 | |-IntegerLiteralExpression
317 | | `-1
318 | |-)
319 | `-CompoundStatement
320 | |-{
321 | `-}
322 |-IfStatement
323 | |-if
324 | |-(
325 | |-IntegerLiteralExpression
326 | | `-1
327 | |-)
328 | |-CompoundStatement
329 | | |-{
330 | | `-}
331 | |-else
332 | `-IfStatement
333 | |-if
334 | |-(
335 | |-IntegerLiteralExpression
336 | | `-0
337 | |-)
338 | `-CompoundStatement
339 | |-{
340 | `-}
341 `-}
342 )txt"));
343 }
344
TEST_P(SyntaxTreeTest,For)345 TEST_P(SyntaxTreeTest, For) {
346 EXPECT_TRUE(treeDumpEqual(
347 R"cpp(
348 void test() {
349 for (;;) {}
350 }
351 )cpp",
352 R"txt(
353 *: TranslationUnit
354 `-SimpleDeclaration
355 |-void
356 |-SimpleDeclarator
357 | |-test
358 | `-ParametersAndQualifiers
359 | |-(
360 | `-)
361 `-CompoundStatement
362 |-{
363 |-ForStatement
364 | |-for
365 | |-(
366 | |-;
367 | |-;
368 | |-)
369 | `-CompoundStatement
370 | |-{
371 | `-}
372 `-}
373 )txt"));
374 }
375
TEST_P(SyntaxTreeTest,RangeBasedFor)376 TEST_P(SyntaxTreeTest, RangeBasedFor) {
377 if (!GetParam().isCXX11OrLater()) {
378 return;
379 }
380 EXPECT_TRUE(treeDumpEqual(
381 R"cpp(
382 void test() {
383 int a[3];
384 for (int x : a)
385 ;
386 }
387 )cpp",
388 R"txt(
389 *: TranslationUnit
390 `-SimpleDeclaration
391 |-void
392 |-SimpleDeclarator
393 | |-test
394 | `-ParametersAndQualifiers
395 | |-(
396 | `-)
397 `-CompoundStatement
398 |-{
399 |-DeclarationStatement
400 | |-SimpleDeclaration
401 | | |-int
402 | | `-SimpleDeclarator
403 | | |-a
404 | | `-ArraySubscript
405 | | |-[
406 | | |-IntegerLiteralExpression
407 | | | `-3
408 | | `-]
409 | `-;
410 |-RangeBasedForStatement
411 | |-for
412 | |-(
413 | |-SimpleDeclaration
414 | | |-int
415 | | |-SimpleDeclarator
416 | | | `-x
417 | | `-:
418 | |-IdExpression
419 | | `-UnqualifiedId
420 | | `-a
421 | |-)
422 | `-EmptyStatement
423 | `-;
424 `-}
425 )txt"));
426 }
427
TEST_P(SyntaxTreeTest,DeclarationStatement)428 TEST_P(SyntaxTreeTest, DeclarationStatement) {
429 EXPECT_TRUE(treeDumpEqual(
430 R"cpp(
431 void test() {
432 int a = 10;
433 }
434 )cpp",
435 R"txt(
436 *: TranslationUnit
437 `-SimpleDeclaration
438 |-void
439 |-SimpleDeclarator
440 | |-test
441 | `-ParametersAndQualifiers
442 | |-(
443 | `-)
444 `-CompoundStatement
445 |-{
446 |-DeclarationStatement
447 | |-SimpleDeclaration
448 | | |-int
449 | | `-SimpleDeclarator
450 | | |-a
451 | | |-=
452 | | `-IntegerLiteralExpression
453 | | `-10
454 | `-;
455 `-}
456 )txt"));
457 }
458
TEST_P(SyntaxTreeTest,Switch)459 TEST_P(SyntaxTreeTest, Switch) {
460 EXPECT_TRUE(treeDumpEqual(
461 R"cpp(
462 void test() {
463 switch (1) {
464 case 0:
465 default:;
466 }
467 }
468 )cpp",
469 R"txt(
470 *: TranslationUnit
471 `-SimpleDeclaration
472 |-void
473 |-SimpleDeclarator
474 | |-test
475 | `-ParametersAndQualifiers
476 | |-(
477 | `-)
478 `-CompoundStatement
479 |-{
480 |-SwitchStatement
481 | |-switch
482 | |-(
483 | |-IntegerLiteralExpression
484 | | `-1
485 | |-)
486 | `-CompoundStatement
487 | |-{
488 | |-CaseStatement
489 | | |-case
490 | | |-IntegerLiteralExpression
491 | | | `-0
492 | | |-:
493 | | `-DefaultStatement
494 | | |-default
495 | | |-:
496 | | `-EmptyStatement
497 | | `-;
498 | `-}
499 `-}
500 )txt"));
501 }
502
TEST_P(SyntaxTreeTest,While)503 TEST_P(SyntaxTreeTest, While) {
504 EXPECT_TRUE(treeDumpEqual(
505 R"cpp(
506 void test() {
507 while (1) { continue; break; }
508 }
509 )cpp",
510 R"txt(
511 *: TranslationUnit
512 `-SimpleDeclaration
513 |-void
514 |-SimpleDeclarator
515 | |-test
516 | `-ParametersAndQualifiers
517 | |-(
518 | `-)
519 `-CompoundStatement
520 |-{
521 |-WhileStatement
522 | |-while
523 | |-(
524 | |-IntegerLiteralExpression
525 | | `-1
526 | |-)
527 | `-CompoundStatement
528 | |-{
529 | |-ContinueStatement
530 | | |-continue
531 | | `-;
532 | |-BreakStatement
533 | | |-break
534 | | `-;
535 | `-}
536 `-}
537 )txt"));
538 }
539
TEST_P(SyntaxTreeTest,UnhandledStatement)540 TEST_P(SyntaxTreeTest, UnhandledStatement) {
541 // Unhandled statements should end up as 'unknown statement'.
542 // This example uses a 'label statement', which does not yet have a syntax
543 // counterpart.
544 EXPECT_TRUE(treeDumpEqual(
545 R"cpp(
546 int main() {
547 foo: return 100;
548 }
549 )cpp",
550 R"txt(
551 *: TranslationUnit
552 `-SimpleDeclaration
553 |-int
554 |-SimpleDeclarator
555 | |-main
556 | `-ParametersAndQualifiers
557 | |-(
558 | `-)
559 `-CompoundStatement
560 |-{
561 |-UnknownStatement
562 | |-foo
563 | |-:
564 | `-ReturnStatement
565 | |-return
566 | |-IntegerLiteralExpression
567 | | `-100
568 | `-;
569 `-}
570 )txt"));
571 }
572
TEST_P(SyntaxTreeTest,Expressions)573 TEST_P(SyntaxTreeTest, Expressions) {
574 // expressions should be wrapped in 'ExpressionStatement' when they appear
575 // in a statement position.
576 EXPECT_TRUE(treeDumpEqual(
577 R"cpp(
578 void test() {
579 test();
580 if (1) test(); else test();
581 }
582 )cpp",
583 R"txt(
584 *: TranslationUnit
585 `-SimpleDeclaration
586 |-void
587 |-SimpleDeclarator
588 | |-test
589 | `-ParametersAndQualifiers
590 | |-(
591 | `-)
592 `-CompoundStatement
593 |-{
594 |-ExpressionStatement
595 | |-UnknownExpression
596 | | |-IdExpression
597 | | | `-UnqualifiedId
598 | | | `-test
599 | | |-(
600 | | `-)
601 | `-;
602 |-IfStatement
603 | |-if
604 | |-(
605 | |-IntegerLiteralExpression
606 | | `-1
607 | |-)
608 | |-ExpressionStatement
609 | | |-UnknownExpression
610 | | | |-IdExpression
611 | | | | `-UnqualifiedId
612 | | | | `-test
613 | | | |-(
614 | | | `-)
615 | | `-;
616 | |-else
617 | `-ExpressionStatement
618 | |-UnknownExpression
619 | | |-IdExpression
620 | | | `-UnqualifiedId
621 | | | `-test
622 | | |-(
623 | | `-)
624 | `-;
625 `-}
626 )txt"));
627 }
628
TEST_P(SyntaxTreeTest,UnqualifiedId)629 TEST_P(SyntaxTreeTest, UnqualifiedId) {
630 if (!GetParam().isCXX()) {
631 return;
632 }
633 EXPECT_TRUE(treeDumpEqual(
634 R"cpp(
635 struct X {
636 // TODO: Expose `id-expression` from `Declarator`
637 friend X operator+(const X&, const X&);
638 operator int();
639 };
640 template<typename T>
641 void f(T&);
642 void test(X x) {
643 x; // identifier
644 operator+(x, x); // operator-function-id
645 f<X>(x); // template-id
646 // TODO: Expose `id-expression` from `MemberExpr`
647 x.operator int(); // conversion-funtion-id
648 x.~X(); // ~type-name
649 }
650 )cpp",
651 R"txt(
652 *: TranslationUnit
653 |-SimpleDeclaration
654 | |-struct
655 | |-X
656 | |-{
657 | |-UnknownDeclaration
658 | | `-SimpleDeclaration
659 | | |-friend
660 | | |-X
661 | | |-SimpleDeclarator
662 | | | |-operator
663 | | | |-+
664 | | | `-ParametersAndQualifiers
665 | | | |-(
666 | | | |-SimpleDeclaration
667 | | | | |-const
668 | | | | |-X
669 | | | | `-SimpleDeclarator
670 | | | | `-&
671 | | | |-,
672 | | | |-SimpleDeclaration
673 | | | | |-const
674 | | | | |-X
675 | | | | `-SimpleDeclarator
676 | | | | `-&
677 | | | `-)
678 | | `-;
679 | |-SimpleDeclaration
680 | | |-SimpleDeclarator
681 | | | |-operator
682 | | | |-int
683 | | | `-ParametersAndQualifiers
684 | | | |-(
685 | | | `-)
686 | | `-;
687 | |-}
688 | `-;
689 |-TemplateDeclaration
690 | |-template
691 | |-<
692 | |-UnknownDeclaration
693 | | |-typename
694 | | `-T
695 | |->
696 | `-SimpleDeclaration
697 | |-void
698 | |-SimpleDeclarator
699 | | |-f
700 | | `-ParametersAndQualifiers
701 | | |-(
702 | | |-SimpleDeclaration
703 | | | |-T
704 | | | `-SimpleDeclarator
705 | | | `-&
706 | | `-)
707 | `-;
708 `-SimpleDeclaration
709 |-void
710 |-SimpleDeclarator
711 | |-test
712 | `-ParametersAndQualifiers
713 | |-(
714 | |-SimpleDeclaration
715 | | |-X
716 | | `-SimpleDeclarator
717 | | `-x
718 | `-)
719 `-CompoundStatement
720 |-{
721 |-ExpressionStatement
722 | |-IdExpression
723 | | `-UnqualifiedId
724 | | `-x
725 | `-;
726 |-ExpressionStatement
727 | |-UnknownExpression
728 | | |-IdExpression
729 | | | `-UnqualifiedId
730 | | | |-operator
731 | | | `-+
732 | | |-(
733 | | |-IdExpression
734 | | | `-UnqualifiedId
735 | | | `-x
736 | | |-,
737 | | |-IdExpression
738 | | | `-UnqualifiedId
739 | | | `-x
740 | | `-)
741 | `-;
742 |-ExpressionStatement
743 | |-UnknownExpression
744 | | |-IdExpression
745 | | | `-UnqualifiedId
746 | | | |-f
747 | | | |-<
748 | | | |-X
749 | | | `->
750 | | |-(
751 | | |-IdExpression
752 | | | `-UnqualifiedId
753 | | | `-x
754 | | `-)
755 | `-;
756 |-ExpressionStatement
757 | |-UnknownExpression
758 | | |-UnknownExpression
759 | | | |-IdExpression
760 | | | | `-UnqualifiedId
761 | | | | `-x
762 | | | |-.
763 | | | |-operator
764 | | | `-int
765 | | |-(
766 | | `-)
767 | `-;
768 |-ExpressionStatement
769 | |-UnknownExpression
770 | | |-UnknownExpression
771 | | | |-IdExpression
772 | | | | `-UnqualifiedId
773 | | | | `-x
774 | | | |-.
775 | | | |-~
776 | | | `-X
777 | | |-(
778 | | `-)
779 | `-;
780 `-}
781 )txt"));
782 }
783
TEST_P(SyntaxTreeTest,UnqualifiedIdCxx11OrLater)784 TEST_P(SyntaxTreeTest, UnqualifiedIdCxx11OrLater) {
785 if (!GetParam().isCXX11OrLater()) {
786 return;
787 }
788 EXPECT_TRUE(treeDumpEqual(
789 R"cpp(
790 struct X { };
791 unsigned operator "" _w(long long unsigned);
792 void test(X x) {
793 operator "" _w(1llu); // literal-operator-id
794 // TODO: Expose `id-expression` from `MemberExpr`
795 x.~decltype(x)(); // ~decltype-specifier
796 }
797 )cpp",
798 R"txt(
799 *: TranslationUnit
800 |-SimpleDeclaration
801 | |-struct
802 | |-X
803 | |-{
804 | |-}
805 | `-;
806 |-SimpleDeclaration
807 | |-unsigned
808 | |-SimpleDeclarator
809 | | |-operator
810 | | |-""
811 | | |-_w
812 | | `-ParametersAndQualifiers
813 | | |-(
814 | | |-SimpleDeclaration
815 | | | |-long
816 | | | |-long
817 | | | `-unsigned
818 | | `-)
819 | `-;
820 `-SimpleDeclaration
821 |-void
822 |-SimpleDeclarator
823 | |-test
824 | `-ParametersAndQualifiers
825 | |-(
826 | |-SimpleDeclaration
827 | | |-X
828 | | `-SimpleDeclarator
829 | | `-x
830 | `-)
831 `-CompoundStatement
832 |-{
833 |-ExpressionStatement
834 | |-UnknownExpression
835 | | |-IdExpression
836 | | | `-UnqualifiedId
837 | | | |-operator
838 | | | |-""
839 | | | `-_w
840 | | |-(
841 | | |-IntegerLiteralExpression
842 | | | `-1llu
843 | | `-)
844 | `-;
845 |-ExpressionStatement
846 | |-UnknownExpression
847 | | |-UnknownExpression
848 | | | |-IdExpression
849 | | | | `-UnqualifiedId
850 | | | | `-x
851 | | | |-.
852 | | | `-~
853 | | |-decltype
854 | | |-(
855 | | |-x
856 | | |-)
857 | | |-(
858 | | `-)
859 | `-;
860 `-}
861 )txt"));
862 }
863
TEST_P(SyntaxTreeTest,QualifiedId)864 TEST_P(SyntaxTreeTest, QualifiedId) {
865 if (!GetParam().isCXX()) {
866 return;
867 }
868 EXPECT_TRUE(treeDumpEqual(
869 R"cpp(
870 namespace a {
871 struct S {
872 template<typename T>
873 static T f(){}
874 };
875 }
876 void test() {
877 :: // global-namespace-specifier
878 a:: // namespace-specifier
879 S:: // type-name-specifier
880 f<int>();
881 }
882 )cpp",
883 R"txt(
884 *: TranslationUnit
885 |-NamespaceDefinition
886 | |-namespace
887 | |-a
888 | |-{
889 | |-SimpleDeclaration
890 | | |-struct
891 | | |-S
892 | | |-{
893 | | |-TemplateDeclaration
894 | | | |-template
895 | | | |-<
896 | | | |-UnknownDeclaration
897 | | | | |-typename
898 | | | | `-T
899 | | | |->
900 | | | `-SimpleDeclaration
901 | | | |-static
902 | | | |-T
903 | | | |-SimpleDeclarator
904 | | | | |-f
905 | | | | `-ParametersAndQualifiers
906 | | | | |-(
907 | | | | `-)
908 | | | `-CompoundStatement
909 | | | |-{
910 | | | `-}
911 | | |-}
912 | | `-;
913 | `-}
914 `-SimpleDeclaration
915 |-void
916 |-SimpleDeclarator
917 | |-test
918 | `-ParametersAndQualifiers
919 | |-(
920 | `-)
921 `-CompoundStatement
922 |-{
923 |-ExpressionStatement
924 | |-UnknownExpression
925 | | |-IdExpression
926 | | | |-NestedNameSpecifier
927 | | | | |-NameSpecifier
928 | | | | | `-::
929 | | | | |-NameSpecifier
930 | | | | | |-a
931 | | | | | `-::
932 | | | | `-NameSpecifier
933 | | | | |-S
934 | | | | `-::
935 | | | `-UnqualifiedId
936 | | | |-f
937 | | | |-<
938 | | | |-int
939 | | | `->
940 | | |-(
941 | | `-)
942 | `-;
943 `-}
944 )txt"));
945 }
946
TEST_P(SyntaxTreeTest,QualifiedIdWithTemplateKeyword)947 TEST_P(SyntaxTreeTest, QualifiedIdWithTemplateKeyword) {
948 if (!GetParam().isCXX()) {
949 return;
950 }
951 if (GetParam().hasDelayedTemplateParsing()) {
952 // FIXME: Make this test work on Windows by generating the expected syntax
953 // tree when `-fdelayed-template-parsing` is active.
954 return;
955 }
956 EXPECT_TRUE(treeDumpEqual(
957 R"cpp(
958 struct X {
959 template<int> static void f();
960 template<int>
961 struct Y {
962 static void f();
963 };
964 };
965 template<typename T> void test() {
966 // TODO: Expose `id-expression` from `DependentScopeDeclRefExpr`
967 T::template f<0>(); // nested-name-specifier template unqualified-id
968 T::template Y<0>::f(); // nested-name-specifier template :: unqualified-id
969 }
970 )cpp",
971 R"txt(
972 *: TranslationUnit
973 |-SimpleDeclaration
974 | |-struct
975 | |-X
976 | |-{
977 | |-TemplateDeclaration
978 | | |-template
979 | | |-<
980 | | |-SimpleDeclaration
981 | | | `-int
982 | | |->
983 | | `-SimpleDeclaration
984 | | |-static
985 | | |-void
986 | | |-SimpleDeclarator
987 | | | |-f
988 | | | `-ParametersAndQualifiers
989 | | | |-(
990 | | | `-)
991 | | `-;
992 | |-TemplateDeclaration
993 | | |-template
994 | | |-<
995 | | |-SimpleDeclaration
996 | | | `-int
997 | | |->
998 | | `-SimpleDeclaration
999 | | |-struct
1000 | | |-Y
1001 | | |-{
1002 | | |-SimpleDeclaration
1003 | | | |-static
1004 | | | |-void
1005 | | | |-SimpleDeclarator
1006 | | | | |-f
1007 | | | | `-ParametersAndQualifiers
1008 | | | | |-(
1009 | | | | `-)
1010 | | | `-;
1011 | | |-}
1012 | | `-;
1013 | |-}
1014 | `-;
1015 `-TemplateDeclaration
1016 |-template
1017 |-<
1018 |-UnknownDeclaration
1019 | |-typename
1020 | `-T
1021 |->
1022 `-SimpleDeclaration
1023 |-void
1024 |-SimpleDeclarator
1025 | |-test
1026 | `-ParametersAndQualifiers
1027 | |-(
1028 | `-)
1029 `-CompoundStatement
1030 |-{
1031 |-ExpressionStatement
1032 | |-UnknownExpression
1033 | | |-UnknownExpression
1034 | | | |-T
1035 | | | |-::
1036 | | | |-template
1037 | | | |-f
1038 | | | |-<
1039 | | | |-IntegerLiteralExpression
1040 | | | | `-0
1041 | | | `->
1042 | | |-(
1043 | | `-)
1044 | `-;
1045 |-ExpressionStatement
1046 | |-UnknownExpression
1047 | | |-UnknownExpression
1048 | | | |-T
1049 | | | |-::
1050 | | | |-template
1051 | | | |-Y
1052 | | | |-<
1053 | | | |-IntegerLiteralExpression
1054 | | | | `-0
1055 | | | |->
1056 | | | |-::
1057 | | | `-f
1058 | | |-(
1059 | | `-)
1060 | `-;
1061 `-}
1062 )txt"));
1063 }
1064
TEST_P(SyntaxTreeTest,QualifiedIdDecltype)1065 TEST_P(SyntaxTreeTest, QualifiedIdDecltype) {
1066 if (!GetParam().isCXX11OrLater()) {
1067 return;
1068 }
1069 EXPECT_TRUE(treeDumpEqual(
1070 R"cpp(
1071 struct S {
1072 static void f(){}
1073 };
1074 void test(S s) {
1075 decltype(s):: // decltype-specifier
1076 f();
1077 }
1078 )cpp",
1079 R"txt(
1080 *: TranslationUnit
1081 |-SimpleDeclaration
1082 | |-struct
1083 | |-S
1084 | |-{
1085 | |-SimpleDeclaration
1086 | | |-static
1087 | | |-void
1088 | | |-SimpleDeclarator
1089 | | | |-f
1090 | | | `-ParametersAndQualifiers
1091 | | | |-(
1092 | | | `-)
1093 | | `-CompoundStatement
1094 | | |-{
1095 | | `-}
1096 | |-}
1097 | `-;
1098 `-SimpleDeclaration
1099 |-void
1100 |-SimpleDeclarator
1101 | |-test
1102 | `-ParametersAndQualifiers
1103 | |-(
1104 | |-SimpleDeclaration
1105 | | |-S
1106 | | `-SimpleDeclarator
1107 | | `-s
1108 | `-)
1109 `-CompoundStatement
1110 |-{
1111 |-ExpressionStatement
1112 | |-UnknownExpression
1113 | | |-IdExpression
1114 | | | |-NestedNameSpecifier
1115 | | | | `-NameSpecifier
1116 | | | | |-decltype
1117 | | | | |-(
1118 | | | | |-IdExpression
1119 | | | | | `-UnqualifiedId
1120 | | | | | `-s
1121 | | | | |-)
1122 | | | | `-::
1123 | | | `-UnqualifiedId
1124 | | | `-f
1125 | | |-(
1126 | | `-)
1127 | `-;
1128 `-}
1129 )txt"));
1130 }
1131
TEST_P(SyntaxTreeTest,ParenExpr)1132 TEST_P(SyntaxTreeTest, ParenExpr) {
1133 EXPECT_TRUE(treeDumpEqual(
1134 R"cpp(
1135 void test() {
1136 (1);
1137 ((1));
1138 (1 + (2));
1139 }
1140 )cpp",
1141 R"txt(
1142 *: TranslationUnit
1143 `-SimpleDeclaration
1144 |-void
1145 |-SimpleDeclarator
1146 | |-test
1147 | `-ParametersAndQualifiers
1148 | |-(
1149 | `-)
1150 `-CompoundStatement
1151 |-{
1152 |-ExpressionStatement
1153 | |-ParenExpression
1154 | | |-(
1155 | | |-IntegerLiteralExpression
1156 | | | `-1
1157 | | `-)
1158 | `-;
1159 |-ExpressionStatement
1160 | |-ParenExpression
1161 | | |-(
1162 | | |-ParenExpression
1163 | | | |-(
1164 | | | |-IntegerLiteralExpression
1165 | | | | `-1
1166 | | | `-)
1167 | | `-)
1168 | `-;
1169 |-ExpressionStatement
1170 | |-ParenExpression
1171 | | |-(
1172 | | |-BinaryOperatorExpression
1173 | | | |-IntegerLiteralExpression
1174 | | | | `-1
1175 | | | |-+
1176 | | | `-ParenExpression
1177 | | | |-(
1178 | | | |-IntegerLiteralExpression
1179 | | | | `-2
1180 | | | `-)
1181 | | `-)
1182 | `-;
1183 `-}
1184 )txt"));
1185 }
1186
TEST_P(SyntaxTreeTest,UserDefinedLiteral)1187 TEST_P(SyntaxTreeTest, UserDefinedLiteral) {
1188 if (!GetParam().isCXX11OrLater()) {
1189 return;
1190 }
1191 EXPECT_TRUE(treeDumpEqual(
1192 R"cpp(
1193 typedef decltype(sizeof(void *)) size_t;
1194
1195 unsigned operator "" _i(unsigned long long);
1196 unsigned operator "" _f(long double);
1197 unsigned operator "" _c(char);
1198 unsigned operator "" _s(const char*, size_t);
1199 unsigned operator "" _r(const char*);
1200 template <char...>
1201 unsigned operator "" _t();
1202
1203 void test() {
1204 12_i; // call: operator "" _i(12uLL) | kind: integer
1205 1.2_f; // call: operator "" _f(1.2L) | kind: float
1206 '2'_c; // call: operator "" _c('2') | kind: char
1207 "12"_s; // call: operator "" _s("12") | kind: string
1208
1209 12_r; // call: operator "" _r("12") | kind: integer
1210 1.2_r; // call: operator "" _i("1.2") | kind: float
1211 12_t; // call: operator<'1', '2'> "" _x() | kind: integer
1212 1.2_t; // call: operator<'1', '2'> "" _x() | kind: float
1213 }
1214 )cpp",
1215 R"txt(
1216 *: TranslationUnit
1217 |-SimpleDeclaration
1218 | |-typedef
1219 | |-decltype
1220 | |-(
1221 | |-UnknownExpression
1222 | | |-sizeof
1223 | | |-(
1224 | | |-void
1225 | | |-*
1226 | | `-)
1227 | |-)
1228 | |-SimpleDeclarator
1229 | | `-size_t
1230 | `-;
1231 |-SimpleDeclaration
1232 | |-unsigned
1233 | |-SimpleDeclarator
1234 | | |-operator
1235 | | |-""
1236 | | |-_i
1237 | | `-ParametersAndQualifiers
1238 | | |-(
1239 | | |-SimpleDeclaration
1240 | | | |-unsigned
1241 | | | |-long
1242 | | | `-long
1243 | | `-)
1244 | `-;
1245 |-SimpleDeclaration
1246 | |-unsigned
1247 | |-SimpleDeclarator
1248 | | |-operator
1249 | | |-""
1250 | | |-_f
1251 | | `-ParametersAndQualifiers
1252 | | |-(
1253 | | |-SimpleDeclaration
1254 | | | |-long
1255 | | | `-double
1256 | | `-)
1257 | `-;
1258 |-SimpleDeclaration
1259 | |-unsigned
1260 | |-SimpleDeclarator
1261 | | |-operator
1262 | | |-""
1263 | | |-_c
1264 | | `-ParametersAndQualifiers
1265 | | |-(
1266 | | |-SimpleDeclaration
1267 | | | `-char
1268 | | `-)
1269 | `-;
1270 |-SimpleDeclaration
1271 | |-unsigned
1272 | |-SimpleDeclarator
1273 | | |-operator
1274 | | |-""
1275 | | |-_s
1276 | | `-ParametersAndQualifiers
1277 | | |-(
1278 | | |-SimpleDeclaration
1279 | | | |-const
1280 | | | |-char
1281 | | | `-SimpleDeclarator
1282 | | | `-*
1283 | | |-,
1284 | | |-SimpleDeclaration
1285 | | | `-size_t
1286 | | `-)
1287 | `-;
1288 |-SimpleDeclaration
1289 | |-unsigned
1290 | |-SimpleDeclarator
1291 | | |-operator
1292 | | |-""
1293 | | |-_r
1294 | | `-ParametersAndQualifiers
1295 | | |-(
1296 | | |-SimpleDeclaration
1297 | | | |-const
1298 | | | |-char
1299 | | | `-SimpleDeclarator
1300 | | | `-*
1301 | | `-)
1302 | `-;
1303 |-TemplateDeclaration
1304 | |-template
1305 | |-<
1306 | |-SimpleDeclaration
1307 | | `-char
1308 | |-...
1309 | |->
1310 | `-SimpleDeclaration
1311 | |-unsigned
1312 | |-SimpleDeclarator
1313 | | |-operator
1314 | | |-""
1315 | | |-_t
1316 | | `-ParametersAndQualifiers
1317 | | |-(
1318 | | `-)
1319 | `-;
1320 `-SimpleDeclaration
1321 |-void
1322 |-SimpleDeclarator
1323 | |-test
1324 | `-ParametersAndQualifiers
1325 | |-(
1326 | `-)
1327 `-CompoundStatement
1328 |-{
1329 |-ExpressionStatement
1330 | |-IntegerUserDefinedLiteralExpression
1331 | | `-12_i
1332 | `-;
1333 |-ExpressionStatement
1334 | |-FloatUserDefinedLiteralExpression
1335 | | `-1.2_f
1336 | `-;
1337 |-ExpressionStatement
1338 | |-CharUserDefinedLiteralExpression
1339 | | `-'2'_c
1340 | `-;
1341 |-ExpressionStatement
1342 | |-StringUserDefinedLiteralExpression
1343 | | `-"12"_s
1344 | `-;
1345 |-ExpressionStatement
1346 | |-IntegerUserDefinedLiteralExpression
1347 | | `-12_r
1348 | `-;
1349 |-ExpressionStatement
1350 | |-FloatUserDefinedLiteralExpression
1351 | | `-1.2_r
1352 | `-;
1353 |-ExpressionStatement
1354 | |-IntegerUserDefinedLiteralExpression
1355 | | `-12_t
1356 | `-;
1357 |-ExpressionStatement
1358 | |-FloatUserDefinedLiteralExpression
1359 | | `-1.2_t
1360 | `-;
1361 `-}
1362 )txt"));
1363 }
1364
TEST_P(SyntaxTreeTest,IntegerLiteralLongLong)1365 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) {
1366 if (!GetParam().isCXX11OrLater()) {
1367 return;
1368 }
1369 EXPECT_TRUE(treeDumpEqual(
1370 R"cpp(
1371 void test() {
1372 12ll;
1373 12ull;
1374 }
1375 )cpp",
1376 R"txt(
1377 *: TranslationUnit
1378 `-SimpleDeclaration
1379 |-void
1380 |-SimpleDeclarator
1381 | |-test
1382 | `-ParametersAndQualifiers
1383 | |-(
1384 | `-)
1385 `-CompoundStatement
1386 |-{
1387 |-ExpressionStatement
1388 | |-IntegerLiteralExpression
1389 | | `-12ll
1390 | `-;
1391 |-ExpressionStatement
1392 | |-IntegerLiteralExpression
1393 | | `-12ull
1394 | `-;
1395 `-}
1396 )txt"));
1397 }
1398
TEST_P(SyntaxTreeTest,IntegerLiteralBinary)1399 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) {
1400 if (!GetParam().isCXX14OrLater()) {
1401 return;
1402 }
1403 EXPECT_TRUE(treeDumpEqual(
1404 R"cpp(
1405 void test() {
1406 0b1100;
1407 }
1408 )cpp",
1409 R"txt(
1410 *: TranslationUnit
1411 `-SimpleDeclaration
1412 |-void
1413 |-SimpleDeclarator
1414 | |-test
1415 | `-ParametersAndQualifiers
1416 | |-(
1417 | `-)
1418 `-CompoundStatement
1419 |-{
1420 |-ExpressionStatement
1421 | |-IntegerLiteralExpression
1422 | | `-0b1100
1423 | `-;
1424 `-}
1425 )txt"));
1426 }
1427
TEST_P(SyntaxTreeTest,IntegerLiteralWithDigitSeparators)1428 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) {
1429 if (!GetParam().isCXX14OrLater()) {
1430 return;
1431 }
1432 EXPECT_TRUE(treeDumpEqual(
1433 R"cpp(
1434 void test() {
1435 1'2'0ull;
1436 }
1437 )cpp",
1438 R"txt(
1439 *: TranslationUnit
1440 `-SimpleDeclaration
1441 |-void
1442 |-SimpleDeclarator
1443 | |-test
1444 | `-ParametersAndQualifiers
1445 | |-(
1446 | `-)
1447 `-CompoundStatement
1448 |-{
1449 |-ExpressionStatement
1450 | |-IntegerLiteralExpression
1451 | | `-1'2'0ull
1452 | `-;
1453 `-}
1454 )txt"));
1455 }
1456
TEST_P(SyntaxTreeTest,CharacterLiteral)1457 TEST_P(SyntaxTreeTest, CharacterLiteral) {
1458 EXPECT_TRUE(treeDumpEqual(
1459 R"cpp(
1460 void test() {
1461 'a';
1462 '\n';
1463 '\x20';
1464 '\0';
1465 L'a';
1466 L'α';
1467 }
1468 )cpp",
1469 R"txt(
1470 *: TranslationUnit
1471 `-SimpleDeclaration
1472 |-void
1473 |-SimpleDeclarator
1474 | |-test
1475 | `-ParametersAndQualifiers
1476 | |-(
1477 | `-)
1478 `-CompoundStatement
1479 |-{
1480 |-ExpressionStatement
1481 | |-CharacterLiteralExpression
1482 | | `-'a'
1483 | `-;
1484 |-ExpressionStatement
1485 | |-CharacterLiteralExpression
1486 | | `-'\n'
1487 | `-;
1488 |-ExpressionStatement
1489 | |-CharacterLiteralExpression
1490 | | `-'\x20'
1491 | `-;
1492 |-ExpressionStatement
1493 | |-CharacterLiteralExpression
1494 | | `-'\0'
1495 | `-;
1496 |-ExpressionStatement
1497 | |-CharacterLiteralExpression
1498 | | `-L'a'
1499 | `-;
1500 |-ExpressionStatement
1501 | |-CharacterLiteralExpression
1502 | | `-L'α'
1503 | `-;
1504 `-}
1505 )txt"));
1506 }
1507
TEST_P(SyntaxTreeTest,CharacterLiteralUtf)1508 TEST_P(SyntaxTreeTest, CharacterLiteralUtf) {
1509 if (!GetParam().isCXX11OrLater()) {
1510 return;
1511 }
1512 EXPECT_TRUE(treeDumpEqual(
1513 R"cpp(
1514 void test() {
1515 u'a';
1516 u'構';
1517 U'a';
1518 U'';
1519 }
1520 )cpp",
1521 R"txt(
1522 *: TranslationUnit
1523 `-SimpleDeclaration
1524 |-void
1525 |-SimpleDeclarator
1526 | |-test
1527 | `-ParametersAndQualifiers
1528 | |-(
1529 | `-)
1530 `-CompoundStatement
1531 |-{
1532 |-ExpressionStatement
1533 | |-CharacterLiteralExpression
1534 | | `-u'a'
1535 | `-;
1536 |-ExpressionStatement
1537 | |-CharacterLiteralExpression
1538 | | `-u'構'
1539 | `-;
1540 |-ExpressionStatement
1541 | |-CharacterLiteralExpression
1542 | | `-U'a'
1543 | `-;
1544 |-ExpressionStatement
1545 | |-CharacterLiteralExpression
1546 | | `-U''
1547 | `-;
1548 `-}
1549 )txt"));
1550 }
1551
TEST_P(SyntaxTreeTest,CharacterLiteralUtf8)1552 TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) {
1553 if (!GetParam().isCXX17OrLater()) {
1554 return;
1555 }
1556 EXPECT_TRUE(treeDumpEqual(
1557 R"cpp(
1558 void test() {
1559 u8'a';
1560 u8'\x7f';
1561 }
1562 )cpp",
1563 R"txt(
1564 *: TranslationUnit
1565 `-SimpleDeclaration
1566 |-void
1567 |-SimpleDeclarator
1568 | |-test
1569 | `-ParametersAndQualifiers
1570 | |-(
1571 | `-)
1572 `-CompoundStatement
1573 |-{
1574 |-ExpressionStatement
1575 | |-CharacterLiteralExpression
1576 | | `-u8'a'
1577 | `-;
1578 |-ExpressionStatement
1579 | |-CharacterLiteralExpression
1580 | | `-u8'\x7f'
1581 | `-;
1582 `-}
1583 )txt"));
1584 }
1585
TEST_P(SyntaxTreeTest,FloatingLiteral)1586 TEST_P(SyntaxTreeTest, FloatingLiteral) {
1587 EXPECT_TRUE(treeDumpEqual(
1588 R"cpp(
1589 void test() {
1590 1e-2;
1591 2.;
1592 .2;
1593 2.f;
1594 }
1595 )cpp",
1596 R"txt(
1597 *: TranslationUnit
1598 `-SimpleDeclaration
1599 |-void
1600 |-SimpleDeclarator
1601 | |-test
1602 | `-ParametersAndQualifiers
1603 | |-(
1604 | `-)
1605 `-CompoundStatement
1606 |-{
1607 |-ExpressionStatement
1608 | |-FloatingLiteralExpression
1609 | | `-1e-2
1610 | `-;
1611 |-ExpressionStatement
1612 | |-FloatingLiteralExpression
1613 | | `-2.
1614 | `-;
1615 |-ExpressionStatement
1616 | |-FloatingLiteralExpression
1617 | | `-.2
1618 | `-;
1619 |-ExpressionStatement
1620 | |-FloatingLiteralExpression
1621 | | `-2.f
1622 | `-;
1623 `-}
1624 )txt"));
1625 }
1626
TEST_P(SyntaxTreeTest,FloatingLiteralHexadecimal)1627 TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) {
1628 if (!GetParam().isCXX17OrLater()) {
1629 return;
1630 }
1631 EXPECT_TRUE(treeDumpEqual(
1632 R"cpp(
1633 void test() {
1634 0xfp1;
1635 0xf.p1;
1636 0x.fp1;
1637 0xf.fp1f;
1638 }
1639 )cpp",
1640 R"txt(
1641 *: TranslationUnit
1642 `-SimpleDeclaration
1643 |-void
1644 |-SimpleDeclarator
1645 | |-test
1646 | `-ParametersAndQualifiers
1647 | |-(
1648 | `-)
1649 `-CompoundStatement
1650 |-{
1651 |-ExpressionStatement
1652 | |-FloatingLiteralExpression
1653 | | `-0xfp1
1654 | `-;
1655 |-ExpressionStatement
1656 | |-FloatingLiteralExpression
1657 | | `-0xf.p1
1658 | `-;
1659 |-ExpressionStatement
1660 | |-FloatingLiteralExpression
1661 | | `-0x.fp1
1662 | `-;
1663 |-ExpressionStatement
1664 | |-FloatingLiteralExpression
1665 | | `-0xf.fp1f
1666 | `-;
1667 `-}
1668 )txt"));
1669 }
1670
TEST_P(SyntaxTreeTest,StringLiteral)1671 TEST_P(SyntaxTreeTest, StringLiteral) {
1672 EXPECT_TRUE(treeDumpEqual(
1673 R"cpp(
1674 void test() {
1675 "a\n\0\x20";
1676 L"αβ";
1677 }
1678 )cpp",
1679 R"txt(
1680 *: TranslationUnit
1681 `-SimpleDeclaration
1682 |-void
1683 |-SimpleDeclarator
1684 | |-test
1685 | `-ParametersAndQualifiers
1686 | |-(
1687 | `-)
1688 `-CompoundStatement
1689 |-{
1690 |-ExpressionStatement
1691 | |-StringLiteralExpression
1692 | | `-"a\n\0\x20"
1693 | `-;
1694 |-ExpressionStatement
1695 | |-StringLiteralExpression
1696 | | `-L"αβ"
1697 | `-;
1698 `-}
1699 )txt"));
1700 }
1701
TEST_P(SyntaxTreeTest,StringLiteralUtf)1702 TEST_P(SyntaxTreeTest, StringLiteralUtf) {
1703 if (!GetParam().isCXX11OrLater()) {
1704 return;
1705 }
1706 EXPECT_TRUE(treeDumpEqual(
1707 R"cpp(
1708 void test() {
1709 u8"a\x1f\x05";
1710 u"C++抽象構文木";
1711 U"\n";
1712 }
1713 )cpp",
1714 R"txt(
1715 *: TranslationUnit
1716 `-SimpleDeclaration
1717 |-void
1718 |-SimpleDeclarator
1719 | |-test
1720 | `-ParametersAndQualifiers
1721 | |-(
1722 | `-)
1723 `-CompoundStatement
1724 |-{
1725 |-ExpressionStatement
1726 | |-StringLiteralExpression
1727 | | `-u8"a\x1f\x05"
1728 | `-;
1729 |-ExpressionStatement
1730 | |-StringLiteralExpression
1731 | | `-u"C++抽象構文木"
1732 | `-;
1733 |-ExpressionStatement
1734 | |-StringLiteralExpression
1735 | | `-U"\n"
1736 | `-;
1737 `-}
1738 )txt"));
1739 }
1740
TEST_P(SyntaxTreeTest,StringLiteralRaw)1741 TEST_P(SyntaxTreeTest, StringLiteralRaw) {
1742 if (!GetParam().isCXX11OrLater()) {
1743 return;
1744 }
1745 // This test uses regular string literals instead of raw string literals to
1746 // hold source code and expected output because of a bug in MSVC up to MSVC
1747 // 2019 16.2:
1748 // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html
1749 EXPECT_TRUE(treeDumpEqual( //
1750 "void test() {\n"
1751 " R\"SyntaxTree(\n"
1752 " Hello \"Syntax\" \\\"\n"
1753 " )SyntaxTree\";\n"
1754 "}\n",
1755 "*: TranslationUnit\n"
1756 "`-SimpleDeclaration\n"
1757 " |-void\n"
1758 " |-SimpleDeclarator\n"
1759 " | |-test\n"
1760 " | `-ParametersAndQualifiers\n"
1761 " | |-(\n"
1762 " | `-)\n"
1763 " `-CompoundStatement\n"
1764 " |-{\n"
1765 " |-ExpressionStatement\n"
1766 " | |-StringLiteralExpression\n"
1767 " | | `-R\"SyntaxTree(\n"
1768 " Hello \"Syntax\" \\\"\n"
1769 " )SyntaxTree\"\n"
1770 " | `-;\n"
1771 " `-}\n"));
1772 }
1773
TEST_P(SyntaxTreeTest,BoolLiteral)1774 TEST_P(SyntaxTreeTest, BoolLiteral) {
1775 if (GetParam().isC()) {
1776 return;
1777 }
1778 EXPECT_TRUE(treeDumpEqual(
1779 R"cpp(
1780 void test() {
1781 true;
1782 false;
1783 }
1784 )cpp",
1785 R"txt(
1786 *: TranslationUnit
1787 `-SimpleDeclaration
1788 |-void
1789 |-SimpleDeclarator
1790 | |-test
1791 | `-ParametersAndQualifiers
1792 | |-(
1793 | `-)
1794 `-CompoundStatement
1795 |-{
1796 |-ExpressionStatement
1797 | |-BoolLiteralExpression
1798 | | `-true
1799 | `-;
1800 |-ExpressionStatement
1801 | |-BoolLiteralExpression
1802 | | `-false
1803 | `-;
1804 `-}
1805 )txt"));
1806 }
1807
TEST_P(SyntaxTreeTest,CxxNullPtrLiteral)1808 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) {
1809 if (!GetParam().isCXX11OrLater()) {
1810 return;
1811 }
1812 EXPECT_TRUE(treeDumpEqual(
1813 R"cpp(
1814 void test() {
1815 nullptr;
1816 }
1817 )cpp",
1818 R"txt(
1819 *: TranslationUnit
1820 `-SimpleDeclaration
1821 |-void
1822 |-SimpleDeclarator
1823 | |-test
1824 | `-ParametersAndQualifiers
1825 | |-(
1826 | `-)
1827 `-CompoundStatement
1828 |-{
1829 |-ExpressionStatement
1830 | |-CxxNullPtrExpression
1831 | | `-nullptr
1832 | `-;
1833 `-}
1834 )txt"));
1835 }
1836
TEST_P(SyntaxTreeTest,PostfixUnaryOperator)1837 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) {
1838 EXPECT_TRUE(treeDumpEqual(
1839 R"cpp(
1840 void test(int a) {
1841 a++;
1842 a--;
1843 }
1844 )cpp",
1845 R"txt(
1846 *: TranslationUnit
1847 `-SimpleDeclaration
1848 |-void
1849 |-SimpleDeclarator
1850 | |-test
1851 | `-ParametersAndQualifiers
1852 | |-(
1853 | |-SimpleDeclaration
1854 | | |-int
1855 | | `-SimpleDeclarator
1856 | | `-a
1857 | `-)
1858 `-CompoundStatement
1859 |-{
1860 |-ExpressionStatement
1861 | |-PostfixUnaryOperatorExpression
1862 | | |-IdExpression
1863 | | | `-UnqualifiedId
1864 | | | `-a
1865 | | `-++
1866 | `-;
1867 |-ExpressionStatement
1868 | |-PostfixUnaryOperatorExpression
1869 | | |-IdExpression
1870 | | | `-UnqualifiedId
1871 | | | `-a
1872 | | `---
1873 | `-;
1874 `-}
1875 )txt"));
1876 }
1877
TEST_P(SyntaxTreeTest,PrefixUnaryOperator)1878 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) {
1879 EXPECT_TRUE(treeDumpEqual(
1880 R"cpp(
1881 void test(int a, int *ap) {
1882 --a; ++a;
1883 ~a;
1884 -a;
1885 +a;
1886 &a;
1887 *ap;
1888 !a;
1889 __real a; __imag a;
1890 }
1891 )cpp",
1892 R"txt(
1893 *: TranslationUnit
1894 `-SimpleDeclaration
1895 |-void
1896 |-SimpleDeclarator
1897 | |-test
1898 | `-ParametersAndQualifiers
1899 | |-(
1900 | |-SimpleDeclaration
1901 | | |-int
1902 | | `-SimpleDeclarator
1903 | | `-a
1904 | |-,
1905 | |-SimpleDeclaration
1906 | | |-int
1907 | | `-SimpleDeclarator
1908 | | |-*
1909 | | `-ap
1910 | `-)
1911 `-CompoundStatement
1912 |-{
1913 |-ExpressionStatement
1914 | |-PrefixUnaryOperatorExpression
1915 | | |---
1916 | | `-IdExpression
1917 | | `-UnqualifiedId
1918 | | `-a
1919 | `-;
1920 |-ExpressionStatement
1921 | |-PrefixUnaryOperatorExpression
1922 | | |-++
1923 | | `-IdExpression
1924 | | `-UnqualifiedId
1925 | | `-a
1926 | `-;
1927 |-ExpressionStatement
1928 | |-PrefixUnaryOperatorExpression
1929 | | |-~
1930 | | `-IdExpression
1931 | | `-UnqualifiedId
1932 | | `-a
1933 | `-;
1934 |-ExpressionStatement
1935 | |-PrefixUnaryOperatorExpression
1936 | | |--
1937 | | `-IdExpression
1938 | | `-UnqualifiedId
1939 | | `-a
1940 | `-;
1941 |-ExpressionStatement
1942 | |-PrefixUnaryOperatorExpression
1943 | | |-+
1944 | | `-IdExpression
1945 | | `-UnqualifiedId
1946 | | `-a
1947 | `-;
1948 |-ExpressionStatement
1949 | |-PrefixUnaryOperatorExpression
1950 | | |-&
1951 | | `-IdExpression
1952 | | `-UnqualifiedId
1953 | | `-a
1954 | `-;
1955 |-ExpressionStatement
1956 | |-PrefixUnaryOperatorExpression
1957 | | |-*
1958 | | `-IdExpression
1959 | | `-UnqualifiedId
1960 | | `-ap
1961 | `-;
1962 |-ExpressionStatement
1963 | |-PrefixUnaryOperatorExpression
1964 | | |-!
1965 | | `-IdExpression
1966 | | `-UnqualifiedId
1967 | | `-a
1968 | `-;
1969 |-ExpressionStatement
1970 | |-PrefixUnaryOperatorExpression
1971 | | |-__real
1972 | | `-IdExpression
1973 | | `-UnqualifiedId
1974 | | `-a
1975 | `-;
1976 |-ExpressionStatement
1977 | |-PrefixUnaryOperatorExpression
1978 | | |-__imag
1979 | | `-IdExpression
1980 | | `-UnqualifiedId
1981 | | `-a
1982 | `-;
1983 `-}
1984 )txt"));
1985 }
1986
TEST_P(SyntaxTreeTest,PrefixUnaryOperatorCxx)1987 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) {
1988 if (!GetParam().isCXX()) {
1989 return;
1990 }
1991 EXPECT_TRUE(treeDumpEqual(
1992 R"cpp(
1993 void test(int a, bool b) {
1994 compl a;
1995 not b;
1996 }
1997 )cpp",
1998 R"txt(
1999 *: TranslationUnit
2000 `-SimpleDeclaration
2001 |-void
2002 |-SimpleDeclarator
2003 | |-test
2004 | `-ParametersAndQualifiers
2005 | |-(
2006 | |-SimpleDeclaration
2007 | | |-int
2008 | | `-SimpleDeclarator
2009 | | `-a
2010 | |-,
2011 | |-SimpleDeclaration
2012 | | |-bool
2013 | | `-SimpleDeclarator
2014 | | `-b
2015 | `-)
2016 `-CompoundStatement
2017 |-{
2018 |-ExpressionStatement
2019 | |-PrefixUnaryOperatorExpression
2020 | | |-compl
2021 | | `-IdExpression
2022 | | `-UnqualifiedId
2023 | | `-a
2024 | `-;
2025 |-ExpressionStatement
2026 | |-PrefixUnaryOperatorExpression
2027 | | |-not
2028 | | `-IdExpression
2029 | | `-UnqualifiedId
2030 | | `-b
2031 | `-;
2032 `-}
2033 )txt"));
2034 }
2035
TEST_P(SyntaxTreeTest,BinaryOperator)2036 TEST_P(SyntaxTreeTest, BinaryOperator) {
2037 EXPECT_TRUE(treeDumpEqual(
2038 R"cpp(
2039 void test(int a) {
2040 1 - 2;
2041 1 == 2;
2042 a = 1;
2043 a <<= 1;
2044 1 || 0;
2045 1 & 2;
2046 a ^= 3;
2047 }
2048 )cpp",
2049 R"txt(
2050 *: TranslationUnit
2051 `-SimpleDeclaration
2052 |-void
2053 |-SimpleDeclarator
2054 | |-test
2055 | `-ParametersAndQualifiers
2056 | |-(
2057 | |-SimpleDeclaration
2058 | | |-int
2059 | | `-SimpleDeclarator
2060 | | `-a
2061 | `-)
2062 `-CompoundStatement
2063 |-{
2064 |-ExpressionStatement
2065 | |-BinaryOperatorExpression
2066 | | |-IntegerLiteralExpression
2067 | | | `-1
2068 | | |--
2069 | | `-IntegerLiteralExpression
2070 | | `-2
2071 | `-;
2072 |-ExpressionStatement
2073 | |-BinaryOperatorExpression
2074 | | |-IntegerLiteralExpression
2075 | | | `-1
2076 | | |-==
2077 | | `-IntegerLiteralExpression
2078 | | `-2
2079 | `-;
2080 |-ExpressionStatement
2081 | |-BinaryOperatorExpression
2082 | | |-IdExpression
2083 | | | `-UnqualifiedId
2084 | | | `-a
2085 | | |-=
2086 | | `-IntegerLiteralExpression
2087 | | `-1
2088 | `-;
2089 |-ExpressionStatement
2090 | |-BinaryOperatorExpression
2091 | | |-IdExpression
2092 | | | `-UnqualifiedId
2093 | | | `-a
2094 | | |-<<=
2095 | | `-IntegerLiteralExpression
2096 | | `-1
2097 | `-;
2098 |-ExpressionStatement
2099 | |-BinaryOperatorExpression
2100 | | |-IntegerLiteralExpression
2101 | | | `-1
2102 | | |-||
2103 | | `-IntegerLiteralExpression
2104 | | `-0
2105 | `-;
2106 |-ExpressionStatement
2107 | |-BinaryOperatorExpression
2108 | | |-IntegerLiteralExpression
2109 | | | `-1
2110 | | |-&
2111 | | `-IntegerLiteralExpression
2112 | | `-2
2113 | `-;
2114 |-ExpressionStatement
2115 | |-BinaryOperatorExpression
2116 | | |-IdExpression
2117 | | | `-UnqualifiedId
2118 | | | `-a
2119 | | |-^=
2120 | | `-IntegerLiteralExpression
2121 | | `-3
2122 | `-;
2123 `-}
2124 )txt"));
2125 }
2126
TEST_P(SyntaxTreeTest,BinaryOperatorCxx)2127 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) {
2128 if (!GetParam().isCXX()) {
2129 return;
2130 }
2131 EXPECT_TRUE(treeDumpEqual(
2132 R"cpp(
2133 void test(int a) {
2134 true || false;
2135 true or false;
2136 1 bitand 2;
2137 a xor_eq 3;
2138 }
2139 )cpp",
2140 R"txt(
2141 *: TranslationUnit
2142 `-SimpleDeclaration
2143 |-void
2144 |-SimpleDeclarator
2145 | |-test
2146 | `-ParametersAndQualifiers
2147 | |-(
2148 | |-SimpleDeclaration
2149 | | |-int
2150 | | `-SimpleDeclarator
2151 | | `-a
2152 | `-)
2153 `-CompoundStatement
2154 |-{
2155 |-ExpressionStatement
2156 | |-BinaryOperatorExpression
2157 | | |-BoolLiteralExpression
2158 | | | `-true
2159 | | |-||
2160 | | `-BoolLiteralExpression
2161 | | `-false
2162 | `-;
2163 |-ExpressionStatement
2164 | |-BinaryOperatorExpression
2165 | | |-BoolLiteralExpression
2166 | | | `-true
2167 | | |-or
2168 | | `-BoolLiteralExpression
2169 | | `-false
2170 | `-;
2171 |-ExpressionStatement
2172 | |-BinaryOperatorExpression
2173 | | |-IntegerLiteralExpression
2174 | | | `-1
2175 | | |-bitand
2176 | | `-IntegerLiteralExpression
2177 | | `-2
2178 | `-;
2179 |-ExpressionStatement
2180 | |-BinaryOperatorExpression
2181 | | |-IdExpression
2182 | | | `-UnqualifiedId
2183 | | | `-a
2184 | | |-xor_eq
2185 | | `-IntegerLiteralExpression
2186 | | `-3
2187 | `-;
2188 `-}
2189 )txt"));
2190 }
2191
TEST_P(SyntaxTreeTest,NestedBinaryOperator)2192 TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
2193 EXPECT_TRUE(treeDumpEqual(
2194 R"cpp(
2195 void test(int a, int b) {
2196 (1 + 2) * (4 / 2);
2197 a + b + 42;
2198 a = b = 42;
2199 a + b * 4 + 2;
2200 a % 2 + b * 42;
2201 }
2202 )cpp",
2203 R"txt(
2204 *: TranslationUnit
2205 `-SimpleDeclaration
2206 |-void
2207 |-SimpleDeclarator
2208 | |-test
2209 | `-ParametersAndQualifiers
2210 | |-(
2211 | |-SimpleDeclaration
2212 | | |-int
2213 | | `-SimpleDeclarator
2214 | | `-a
2215 | |-,
2216 | |-SimpleDeclaration
2217 | | |-int
2218 | | `-SimpleDeclarator
2219 | | `-b
2220 | `-)
2221 `-CompoundStatement
2222 |-{
2223 |-ExpressionStatement
2224 | |-BinaryOperatorExpression
2225 | | |-ParenExpression
2226 | | | |-(
2227 | | | |-BinaryOperatorExpression
2228 | | | | |-IntegerLiteralExpression
2229 | | | | | `-1
2230 | | | | |-+
2231 | | | | `-IntegerLiteralExpression
2232 | | | | `-2
2233 | | | `-)
2234 | | |-*
2235 | | `-ParenExpression
2236 | | |-(
2237 | | |-BinaryOperatorExpression
2238 | | | |-IntegerLiteralExpression
2239 | | | | `-4
2240 | | | |-/
2241 | | | `-IntegerLiteralExpression
2242 | | | `-2
2243 | | `-)
2244 | `-;
2245 |-ExpressionStatement
2246 | |-BinaryOperatorExpression
2247 | | |-BinaryOperatorExpression
2248 | | | |-IdExpression
2249 | | | | `-UnqualifiedId
2250 | | | | `-a
2251 | | | |-+
2252 | | | `-IdExpression
2253 | | | `-UnqualifiedId
2254 | | | `-b
2255 | | |-+
2256 | | `-IntegerLiteralExpression
2257 | | `-42
2258 | `-;
2259 |-ExpressionStatement
2260 | |-BinaryOperatorExpression
2261 | | |-IdExpression
2262 | | | `-UnqualifiedId
2263 | | | `-a
2264 | | |-=
2265 | | `-BinaryOperatorExpression
2266 | | |-IdExpression
2267 | | | `-UnqualifiedId
2268 | | | `-b
2269 | | |-=
2270 | | `-IntegerLiteralExpression
2271 | | `-42
2272 | `-;
2273 |-ExpressionStatement
2274 | |-BinaryOperatorExpression
2275 | | |-BinaryOperatorExpression
2276 | | | |-IdExpression
2277 | | | | `-UnqualifiedId
2278 | | | | `-a
2279 | | | |-+
2280 | | | `-BinaryOperatorExpression
2281 | | | |-IdExpression
2282 | | | | `-UnqualifiedId
2283 | | | | `-b
2284 | | | |-*
2285 | | | `-IntegerLiteralExpression
2286 | | | `-4
2287 | | |-+
2288 | | `-IntegerLiteralExpression
2289 | | `-2
2290 | `-;
2291 |-ExpressionStatement
2292 | |-BinaryOperatorExpression
2293 | | |-BinaryOperatorExpression
2294 | | | |-IdExpression
2295 | | | | `-UnqualifiedId
2296 | | | | `-a
2297 | | | |-%
2298 | | | `-IntegerLiteralExpression
2299 | | | `-2
2300 | | |-+
2301 | | `-BinaryOperatorExpression
2302 | | |-IdExpression
2303 | | | `-UnqualifiedId
2304 | | | `-b
2305 | | |-*
2306 | | `-IntegerLiteralExpression
2307 | | `-42
2308 | `-;
2309 `-}
2310 )txt"));
2311 }
2312
TEST_P(SyntaxTreeTest,UserDefinedBinaryOperator)2313 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
2314 if (!GetParam().isCXX()) {
2315 return;
2316 }
2317 EXPECT_TRUE(treeDumpEqual(
2318 R"cpp(
2319 struct X {
2320 X& operator=(const X&);
2321 friend X operator+(X, const X&);
2322 friend bool operator<(const X&, const X&);
2323 friend X operator<<(X&, const X&);
2324 X operator,(X&);
2325 // TODO: Fix crash on member function pointer and add a test for `->*`
2326 // TODO: Unbox operators in syntax tree.
2327 // Represent operators by `+` instead of `IdExpression-UnqualifiedId-+`
2328 };
2329 void test(X x, X y) {
2330 x = y;
2331 x + y;
2332 x < y;
2333 x << y;
2334 x, y;
2335 }
2336 )cpp",
2337 R"txt(
2338 *: TranslationUnit
2339 |-SimpleDeclaration
2340 | |-struct
2341 | |-X
2342 | |-{
2343 | |-SimpleDeclaration
2344 | | |-X
2345 | | |-SimpleDeclarator
2346 | | | |-&
2347 | | | |-operator
2348 | | | |-=
2349 | | | `-ParametersAndQualifiers
2350 | | | |-(
2351 | | | |-SimpleDeclaration
2352 | | | | |-const
2353 | | | | |-X
2354 | | | | `-SimpleDeclarator
2355 | | | | `-&
2356 | | | `-)
2357 | | `-;
2358 | |-UnknownDeclaration
2359 | | `-SimpleDeclaration
2360 | | |-friend
2361 | | |-X
2362 | | |-SimpleDeclarator
2363 | | | |-operator
2364 | | | |-+
2365 | | | `-ParametersAndQualifiers
2366 | | | |-(
2367 | | | |-SimpleDeclaration
2368 | | | | `-X
2369 | | | |-,
2370 | | | |-SimpleDeclaration
2371 | | | | |-const
2372 | | | | |-X
2373 | | | | `-SimpleDeclarator
2374 | | | | `-&
2375 | | | `-)
2376 | | `-;
2377 | |-UnknownDeclaration
2378 | | `-SimpleDeclaration
2379 | | |-friend
2380 | | |-bool
2381 | | |-SimpleDeclarator
2382 | | | |-operator
2383 | | | |-<
2384 | | | `-ParametersAndQualifiers
2385 | | | |-(
2386 | | | |-SimpleDeclaration
2387 | | | | |-const
2388 | | | | |-X
2389 | | | | `-SimpleDeclarator
2390 | | | | `-&
2391 | | | |-,
2392 | | | |-SimpleDeclaration
2393 | | | | |-const
2394 | | | | |-X
2395 | | | | `-SimpleDeclarator
2396 | | | | `-&
2397 | | | `-)
2398 | | `-;
2399 | |-UnknownDeclaration
2400 | | `-SimpleDeclaration
2401 | | |-friend
2402 | | |-X
2403 | | |-SimpleDeclarator
2404 | | | |-operator
2405 | | | |-<<
2406 | | | `-ParametersAndQualifiers
2407 | | | |-(
2408 | | | |-SimpleDeclaration
2409 | | | | |-X
2410 | | | | `-SimpleDeclarator
2411 | | | | `-&
2412 | | | |-,
2413 | | | |-SimpleDeclaration
2414 | | | | |-const
2415 | | | | |-X
2416 | | | | `-SimpleDeclarator
2417 | | | | `-&
2418 | | | `-)
2419 | | `-;
2420 | |-SimpleDeclaration
2421 | | |-X
2422 | | |-SimpleDeclarator
2423 | | | |-operator
2424 | | | |-,
2425 | | | `-ParametersAndQualifiers
2426 | | | |-(
2427 | | | |-SimpleDeclaration
2428 | | | | |-X
2429 | | | | `-SimpleDeclarator
2430 | | | | `-&
2431 | | | `-)
2432 | | `-;
2433 | |-}
2434 | `-;
2435 `-SimpleDeclaration
2436 |-void
2437 |-SimpleDeclarator
2438 | |-test
2439 | `-ParametersAndQualifiers
2440 | |-(
2441 | |-SimpleDeclaration
2442 | | |-X
2443 | | `-SimpleDeclarator
2444 | | `-x
2445 | |-,
2446 | |-SimpleDeclaration
2447 | | |-X
2448 | | `-SimpleDeclarator
2449 | | `-y
2450 | `-)
2451 `-CompoundStatement
2452 |-{
2453 |-ExpressionStatement
2454 | |-BinaryOperatorExpression
2455 | | |-IdExpression
2456 | | | `-UnqualifiedId
2457 | | | `-x
2458 | | |-IdExpression
2459 | | | `-UnqualifiedId
2460 | | | `-=
2461 | | `-IdExpression
2462 | | `-UnqualifiedId
2463 | | `-y
2464 | `-;
2465 |-ExpressionStatement
2466 | |-BinaryOperatorExpression
2467 | | |-UnknownExpression
2468 | | | `-IdExpression
2469 | | | `-UnqualifiedId
2470 | | | `-x
2471 | | |-IdExpression
2472 | | | `-UnqualifiedId
2473 | | | `-+
2474 | | `-IdExpression
2475 | | `-UnqualifiedId
2476 | | `-y
2477 | `-;
2478 |-ExpressionStatement
2479 | |-BinaryOperatorExpression
2480 | | |-IdExpression
2481 | | | `-UnqualifiedId
2482 | | | `-x
2483 | | |-IdExpression
2484 | | | `-UnqualifiedId
2485 | | | `-<
2486 | | `-IdExpression
2487 | | `-UnqualifiedId
2488 | | `-y
2489 | `-;
2490 |-ExpressionStatement
2491 | |-BinaryOperatorExpression
2492 | | |-IdExpression
2493 | | | `-UnqualifiedId
2494 | | | `-x
2495 | | |-IdExpression
2496 | | | `-UnqualifiedId
2497 | | | `-<<
2498 | | `-IdExpression
2499 | | `-UnqualifiedId
2500 | | `-y
2501 | `-;
2502 |-ExpressionStatement
2503 | |-BinaryOperatorExpression
2504 | | |-IdExpression
2505 | | | `-UnqualifiedId
2506 | | | `-x
2507 | | |-IdExpression
2508 | | | `-UnqualifiedId
2509 | | | `-,
2510 | | `-IdExpression
2511 | | `-UnqualifiedId
2512 | | `-y
2513 | `-;
2514 `-}
2515 )txt"));
2516 }
2517
TEST_P(SyntaxTreeTest,UserDefinedUnaryPrefixOperator)2518 TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
2519 if (!GetParam().isCXX()) {
2520 return;
2521 }
2522 EXPECT_TRUE(treeDumpEqual(
2523 R"cpp(
2524 struct X {
2525 X operator++();
2526 bool operator!();
2527 X* operator&();
2528 };
2529 void test(X x) {
2530 ++x;
2531 !x;
2532 &x;
2533 }
2534 )cpp",
2535 R"txt(
2536 *: TranslationUnit
2537 |-SimpleDeclaration
2538 | |-struct
2539 | |-X
2540 | |-{
2541 | |-SimpleDeclaration
2542 | | |-X
2543 | | |-SimpleDeclarator
2544 | | | |-operator
2545 | | | |-++
2546 | | | `-ParametersAndQualifiers
2547 | | | |-(
2548 | | | `-)
2549 | | `-;
2550 | |-SimpleDeclaration
2551 | | |-bool
2552 | | |-SimpleDeclarator
2553 | | | |-operator
2554 | | | |-!
2555 | | | `-ParametersAndQualifiers
2556 | | | |-(
2557 | | | `-)
2558 | | `-;
2559 | |-SimpleDeclaration
2560 | | |-X
2561 | | |-SimpleDeclarator
2562 | | | |-*
2563 | | | |-operator
2564 | | | |-&
2565 | | | `-ParametersAndQualifiers
2566 | | | |-(
2567 | | | `-)
2568 | | `-;
2569 | |-}
2570 | `-;
2571 `-SimpleDeclaration
2572 |-void
2573 |-SimpleDeclarator
2574 | |-test
2575 | `-ParametersAndQualifiers
2576 | |-(
2577 | |-SimpleDeclaration
2578 | | |-X
2579 | | `-SimpleDeclarator
2580 | | `-x
2581 | `-)
2582 `-CompoundStatement
2583 |-{
2584 |-ExpressionStatement
2585 | |-PrefixUnaryOperatorExpression
2586 | | |-IdExpression
2587 | | | `-UnqualifiedId
2588 | | | `-++
2589 | | `-IdExpression
2590 | | `-UnqualifiedId
2591 | | `-x
2592 | `-;
2593 |-ExpressionStatement
2594 | |-PrefixUnaryOperatorExpression
2595 | | |-IdExpression
2596 | | | `-UnqualifiedId
2597 | | | `-!
2598 | | `-IdExpression
2599 | | `-UnqualifiedId
2600 | | `-x
2601 | `-;
2602 |-ExpressionStatement
2603 | |-PrefixUnaryOperatorExpression
2604 | | |-IdExpression
2605 | | | `-UnqualifiedId
2606 | | | `-&
2607 | | `-IdExpression
2608 | | `-UnqualifiedId
2609 | | `-x
2610 | `-;
2611 `-}
2612 )txt"));
2613 }
2614
TEST_P(SyntaxTreeTest,UserDefinedUnaryPostfixOperator)2615 TEST_P(SyntaxTreeTest, UserDefinedUnaryPostfixOperator) {
2616 if (!GetParam().isCXX()) {
2617 return;
2618 }
2619 EXPECT_TRUE(treeDumpEqual(
2620 R"cpp(
2621 struct X {
2622 X operator++(int);
2623 };
2624 void test(X x) {
2625 x++;
2626 }
2627 )cpp",
2628 R"txt(
2629 *: TranslationUnit
2630 |-SimpleDeclaration
2631 | |-struct
2632 | |-X
2633 | |-{
2634 | |-SimpleDeclaration
2635 | | |-X
2636 | | |-SimpleDeclarator
2637 | | | |-operator
2638 | | | |-++
2639 | | | `-ParametersAndQualifiers
2640 | | | |-(
2641 | | | |-SimpleDeclaration
2642 | | | | `-int
2643 | | | `-)
2644 | | `-;
2645 | |-}
2646 | `-;
2647 `-SimpleDeclaration
2648 |-void
2649 |-SimpleDeclarator
2650 | |-test
2651 | `-ParametersAndQualifiers
2652 | |-(
2653 | |-SimpleDeclaration
2654 | | |-X
2655 | | `-SimpleDeclarator
2656 | | `-x
2657 | `-)
2658 `-CompoundStatement
2659 |-{
2660 |-ExpressionStatement
2661 | |-PostfixUnaryOperatorExpression
2662 | | |-IdExpression
2663 | | | `-UnqualifiedId
2664 | | | `-x
2665 | | `-IdExpression
2666 | | `-UnqualifiedId
2667 | | `-++
2668 | `-;
2669 `-}
2670 )txt"));
2671 }
2672
TEST_P(SyntaxTreeTest,MultipleDeclaratorsGrouping)2673 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
2674 EXPECT_TRUE(treeDumpEqual(
2675 R"cpp(
2676 int *a, b;
2677 int *c, d;
2678 )cpp",
2679 R"txt(
2680 *: TranslationUnit
2681 |-SimpleDeclaration
2682 | |-int
2683 | |-SimpleDeclarator
2684 | | |-*
2685 | | `-a
2686 | |-,
2687 | |-SimpleDeclarator
2688 | | `-b
2689 | `-;
2690 `-SimpleDeclaration
2691 |-int
2692 |-SimpleDeclarator
2693 | |-*
2694 | `-c
2695 |-,
2696 |-SimpleDeclarator
2697 | `-d
2698 `-;
2699 )txt"));
2700 }
2701
TEST_P(SyntaxTreeTest,MultipleDeclaratorsGroupingTypedef)2702 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2703 EXPECT_TRUE(treeDumpEqual(
2704 R"cpp(
2705 typedef int *a, b;
2706 )cpp",
2707 R"txt(
2708 *: TranslationUnit
2709 `-SimpleDeclaration
2710 |-typedef
2711 |-int
2712 |-SimpleDeclarator
2713 | |-*
2714 | `-a
2715 |-,
2716 |-SimpleDeclarator
2717 | `-b
2718 `-;
2719 )txt"));
2720 }
2721
TEST_P(SyntaxTreeTest,MultipleDeclaratorsInsideStatement)2722 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2723 EXPECT_TRUE(treeDumpEqual(
2724 R"cpp(
2725 void foo() {
2726 int *a, b;
2727 typedef int *ta, tb;
2728 }
2729 )cpp",
2730 R"txt(
2731 *: TranslationUnit
2732 `-SimpleDeclaration
2733 |-void
2734 |-SimpleDeclarator
2735 | |-foo
2736 | `-ParametersAndQualifiers
2737 | |-(
2738 | `-)
2739 `-CompoundStatement
2740 |-{
2741 |-DeclarationStatement
2742 | |-SimpleDeclaration
2743 | | |-int
2744 | | |-SimpleDeclarator
2745 | | | |-*
2746 | | | `-a
2747 | | |-,
2748 | | `-SimpleDeclarator
2749 | | `-b
2750 | `-;
2751 |-DeclarationStatement
2752 | |-SimpleDeclaration
2753 | | |-typedef
2754 | | |-int
2755 | | |-SimpleDeclarator
2756 | | | |-*
2757 | | | `-ta
2758 | | |-,
2759 | | `-SimpleDeclarator
2760 | | `-tb
2761 | `-;
2762 `-}
2763 )txt"));
2764 }
2765
TEST_P(SyntaxTreeTest,Namespaces)2766 TEST_P(SyntaxTreeTest, Namespaces) {
2767 if (!GetParam().isCXX()) {
2768 return;
2769 }
2770 EXPECT_TRUE(treeDumpEqual(
2771 R"cpp(
2772 namespace a { namespace b {} }
2773 namespace a::b {}
2774 namespace {}
2775
2776 namespace foo = a;
2777 )cpp",
2778 R"txt(
2779 *: TranslationUnit
2780 |-NamespaceDefinition
2781 | |-namespace
2782 | |-a
2783 | |-{
2784 | |-NamespaceDefinition
2785 | | |-namespace
2786 | | |-b
2787 | | |-{
2788 | | `-}
2789 | `-}
2790 |-NamespaceDefinition
2791 | |-namespace
2792 | |-a
2793 | |-::
2794 | |-b
2795 | |-{
2796 | `-}
2797 |-NamespaceDefinition
2798 | |-namespace
2799 | |-{
2800 | `-}
2801 `-NamespaceAliasDefinition
2802 |-namespace
2803 |-foo
2804 |-=
2805 |-a
2806 `-;
2807 )txt"));
2808 }
2809
TEST_P(SyntaxTreeTest,UsingDirective)2810 TEST_P(SyntaxTreeTest, UsingDirective) {
2811 if (!GetParam().isCXX()) {
2812 return;
2813 }
2814 EXPECT_TRUE(treeDumpEqual(
2815 R"cpp(
2816 namespace ns {}
2817 using namespace ::ns;
2818 )cpp",
2819 R"txt(
2820 *: TranslationUnit
2821 |-NamespaceDefinition
2822 | |-namespace
2823 | |-ns
2824 | |-{
2825 | `-}
2826 `-UsingNamespaceDirective
2827 |-using
2828 |-namespace
2829 |-::
2830 |-ns
2831 `-;
2832 )txt"));
2833 }
2834
TEST_P(SyntaxTreeTest,UsingDeclaration)2835 TEST_P(SyntaxTreeTest, UsingDeclaration) {
2836 if (!GetParam().isCXX()) {
2837 return;
2838 }
2839 EXPECT_TRUE(treeDumpEqual(
2840 R"cpp(
2841 namespace ns { int a; }
2842 using ns::a;
2843 )cpp",
2844 R"txt(
2845 *: TranslationUnit
2846 |-NamespaceDefinition
2847 | |-namespace
2848 | |-ns
2849 | |-{
2850 | |-SimpleDeclaration
2851 | | |-int
2852 | | |-SimpleDeclarator
2853 | | | `-a
2854 | | `-;
2855 | `-}
2856 `-UsingDeclaration
2857 |-using
2858 |-ns
2859 |-::
2860 |-a
2861 `-;
2862 )txt"));
2863 }
2864
TEST_P(SyntaxTreeTest,FreeStandingClasses)2865 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
2866 // Free-standing classes, must live inside a SimpleDeclaration.
2867 EXPECT_TRUE(treeDumpEqual(
2868 R"cpp(
2869 struct X;
2870 struct X {};
2871
2872 struct Y *y1;
2873 struct Y {} *y2;
2874
2875 struct {} *a1;
2876 )cpp",
2877 R"txt(
2878 *: TranslationUnit
2879 |-SimpleDeclaration
2880 | |-struct
2881 | |-X
2882 | `-;
2883 |-SimpleDeclaration
2884 | |-struct
2885 | |-X
2886 | |-{
2887 | |-}
2888 | `-;
2889 |-SimpleDeclaration
2890 | |-struct
2891 | |-Y
2892 | |-SimpleDeclarator
2893 | | |-*
2894 | | `-y1
2895 | `-;
2896 |-SimpleDeclaration
2897 | |-struct
2898 | |-Y
2899 | |-{
2900 | |-}
2901 | |-SimpleDeclarator
2902 | | |-*
2903 | | `-y2
2904 | `-;
2905 `-SimpleDeclaration
2906 |-struct
2907 |-{
2908 |-}
2909 |-SimpleDeclarator
2910 | |-*
2911 | `-a1
2912 `-;
2913 )txt"));
2914 }
2915
TEST_P(SyntaxTreeTest,Templates)2916 TEST_P(SyntaxTreeTest, Templates) {
2917 if (!GetParam().isCXX()) {
2918 return;
2919 }
2920 if (GetParam().hasDelayedTemplateParsing()) {
2921 // FIXME: Make this test work on Windows by generating the expected syntax
2922 // tree when `-fdelayed-template-parsing` is active.
2923 return;
2924 }
2925 EXPECT_TRUE(treeDumpEqual(
2926 R"cpp(
2927 template <class T> struct cls {};
2928 template <class T> int var = 10;
2929 template <class T> int fun() {}
2930 )cpp",
2931 R"txt(
2932 *: TranslationUnit
2933 |-TemplateDeclaration
2934 | |-template
2935 | |-<
2936 | |-UnknownDeclaration
2937 | | |-class
2938 | | `-T
2939 | |->
2940 | `-SimpleDeclaration
2941 | |-struct
2942 | |-cls
2943 | |-{
2944 | |-}
2945 | `-;
2946 |-TemplateDeclaration
2947 | |-template
2948 | |-<
2949 | |-UnknownDeclaration
2950 | | |-class
2951 | | `-T
2952 | |->
2953 | `-SimpleDeclaration
2954 | |-int
2955 | |-SimpleDeclarator
2956 | | |-var
2957 | | |-=
2958 | | `-IntegerLiteralExpression
2959 | | `-10
2960 | `-;
2961 `-TemplateDeclaration
2962 |-template
2963 |-<
2964 |-UnknownDeclaration
2965 | |-class
2966 | `-T
2967 |->
2968 `-SimpleDeclaration
2969 |-int
2970 |-SimpleDeclarator
2971 | |-fun
2972 | `-ParametersAndQualifiers
2973 | |-(
2974 | `-)
2975 `-CompoundStatement
2976 |-{
2977 `-}
2978 )txt"));
2979 }
2980
TEST_P(SyntaxTreeTest,NestedTemplates)2981 TEST_P(SyntaxTreeTest, NestedTemplates) {
2982 if (!GetParam().isCXX()) {
2983 return;
2984 }
2985 EXPECT_TRUE(treeDumpEqual(
2986 R"cpp(
2987 template <class T>
2988 struct X {
2989 template <class U>
2990 U foo();
2991 };
2992 )cpp",
2993 R"txt(
2994 *: TranslationUnit
2995 `-TemplateDeclaration
2996 |-template
2997 |-<
2998 |-UnknownDeclaration
2999 | |-class
3000 | `-T
3001 |->
3002 `-SimpleDeclaration
3003 |-struct
3004 |-X
3005 |-{
3006 |-TemplateDeclaration
3007 | |-template
3008 | |-<
3009 | |-UnknownDeclaration
3010 | | |-class
3011 | | `-U
3012 | |->
3013 | `-SimpleDeclaration
3014 | |-U
3015 | |-SimpleDeclarator
3016 | | |-foo
3017 | | `-ParametersAndQualifiers
3018 | | |-(
3019 | | `-)
3020 | `-;
3021 |-}
3022 `-;
3023 )txt"));
3024 }
3025
TEST_P(SyntaxTreeTest,Templates2)3026 TEST_P(SyntaxTreeTest, Templates2) {
3027 if (!GetParam().isCXX()) {
3028 return;
3029 }
3030 EXPECT_TRUE(treeDumpEqual(
3031 R"cpp(
3032 template <class T> struct X { struct Y; };
3033 template <class T> struct X<T>::Y {};
3034 )cpp",
3035 R"txt(
3036 *: TranslationUnit
3037 |-TemplateDeclaration
3038 | |-template
3039 | |-<
3040 | |-UnknownDeclaration
3041 | | |-class
3042 | | `-T
3043 | |->
3044 | `-SimpleDeclaration
3045 | |-struct
3046 | |-X
3047 | |-{
3048 | |-SimpleDeclaration
3049 | | |-struct
3050 | | |-Y
3051 | | `-;
3052 | |-}
3053 | `-;
3054 `-TemplateDeclaration
3055 |-template
3056 |-<
3057 |-UnknownDeclaration
3058 | |-class
3059 | `-T
3060 |->
3061 `-SimpleDeclaration
3062 |-struct
3063 |-X
3064 |-<
3065 |-T
3066 |->
3067 |-::
3068 |-Y
3069 |-{
3070 |-}
3071 `-;
3072 )txt"));
3073 }
3074
TEST_P(SyntaxTreeTest,TemplatesUsingUsing)3075 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
3076 if (!GetParam().isCXX()) {
3077 return;
3078 }
3079 EXPECT_TRUE(treeDumpEqual(
3080 R"cpp(
3081 template <class T> struct X {
3082 using T::foo;
3083 using typename T::bar;
3084 };
3085 )cpp",
3086 R"txt(
3087 *: TranslationUnit
3088 `-TemplateDeclaration
3089 |-template
3090 |-<
3091 |-UnknownDeclaration
3092 | |-class
3093 | `-T
3094 |->
3095 `-SimpleDeclaration
3096 |-struct
3097 |-X
3098 |-{
3099 |-UsingDeclaration
3100 | |-using
3101 | |-T
3102 | |-::
3103 | |-foo
3104 | `-;
3105 |-UsingDeclaration
3106 | |-using
3107 | |-typename
3108 | |-T
3109 | |-::
3110 | |-bar
3111 | `-;
3112 |-}
3113 `-;
3114 )txt"));
3115 }
3116
TEST_P(SyntaxTreeTest,ExplicitTemplateInstantations)3117 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
3118 if (!GetParam().isCXX()) {
3119 return;
3120 }
3121 EXPECT_TRUE(treeDumpEqual(
3122 R"cpp(
3123 template <class T> struct X {};
3124 template <class T> struct X<T*> {};
3125 template <> struct X<int> {};
3126
3127 template struct X<double>;
3128 extern template struct X<float>;
3129 )cpp",
3130 R"txt(
3131 *: TranslationUnit
3132 |-TemplateDeclaration
3133 | |-template
3134 | |-<
3135 | |-UnknownDeclaration
3136 | | |-class
3137 | | `-T
3138 | |->
3139 | `-SimpleDeclaration
3140 | |-struct
3141 | |-X
3142 | |-{
3143 | |-}
3144 | `-;
3145 |-TemplateDeclaration
3146 | |-template
3147 | |-<
3148 | |-UnknownDeclaration
3149 | | |-class
3150 | | `-T
3151 | |->
3152 | `-SimpleDeclaration
3153 | |-struct
3154 | |-X
3155 | |-<
3156 | |-T
3157 | |-*
3158 | |->
3159 | |-{
3160 | |-}
3161 | `-;
3162 |-TemplateDeclaration
3163 | |-template
3164 | |-<
3165 | |->
3166 | `-SimpleDeclaration
3167 | |-struct
3168 | |-X
3169 | |-<
3170 | |-int
3171 | |->
3172 | |-{
3173 | |-}
3174 | `-;
3175 |-ExplicitTemplateInstantiation
3176 | |-template
3177 | `-SimpleDeclaration
3178 | |-struct
3179 | |-X
3180 | |-<
3181 | |-double
3182 | |->
3183 | `-;
3184 `-ExplicitTemplateInstantiation
3185 |-extern
3186 |-template
3187 `-SimpleDeclaration
3188 |-struct
3189 |-X
3190 |-<
3191 |-float
3192 |->
3193 `-;
3194 )txt"));
3195 }
3196
TEST_P(SyntaxTreeTest,UsingType)3197 TEST_P(SyntaxTreeTest, UsingType) {
3198 if (!GetParam().isCXX()) {
3199 return;
3200 }
3201 EXPECT_TRUE(treeDumpEqual(
3202 R"cpp(
3203 using type = int;
3204 )cpp",
3205 R"txt(
3206 *: TranslationUnit
3207 `-TypeAliasDeclaration
3208 |-using
3209 |-type
3210 |-=
3211 |-int
3212 `-;
3213 )txt"));
3214 }
3215
TEST_P(SyntaxTreeTest,EmptyDeclaration)3216 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3217 EXPECT_TRUE(treeDumpEqual(
3218 R"cpp(
3219 ;
3220 )cpp",
3221 R"txt(
3222 *: TranslationUnit
3223 `-EmptyDeclaration
3224 `-;
3225 )txt"));
3226 }
3227
TEST_P(SyntaxTreeTest,StaticAssert)3228 TEST_P(SyntaxTreeTest, StaticAssert) {
3229 if (!GetParam().isCXX11OrLater()) {
3230 return;
3231 }
3232 EXPECT_TRUE(treeDumpEqual(
3233 R"cpp(
3234 static_assert(true, "message");
3235 static_assert(true);
3236 )cpp",
3237 R"txt(
3238 *: TranslationUnit
3239 |-StaticAssertDeclaration
3240 | |-static_assert
3241 | |-(
3242 | |-BoolLiteralExpression
3243 | | `-true
3244 | |-,
3245 | |-StringLiteralExpression
3246 | | `-"message"
3247 | |-)
3248 | `-;
3249 `-StaticAssertDeclaration
3250 |-static_assert
3251 |-(
3252 |-BoolLiteralExpression
3253 | `-true
3254 |-)
3255 `-;
3256 )txt"));
3257 }
3258
TEST_P(SyntaxTreeTest,ExternC)3259 TEST_P(SyntaxTreeTest, ExternC) {
3260 if (!GetParam().isCXX()) {
3261 return;
3262 }
3263 EXPECT_TRUE(treeDumpEqual(
3264 R"cpp(
3265 extern "C" int a;
3266 extern "C" { int b; int c; }
3267 )cpp",
3268 R"txt(
3269 *: TranslationUnit
3270 |-LinkageSpecificationDeclaration
3271 | |-extern
3272 | |-"C"
3273 | `-SimpleDeclaration
3274 | |-int
3275 | |-SimpleDeclarator
3276 | | `-a
3277 | `-;
3278 `-LinkageSpecificationDeclaration
3279 |-extern
3280 |-"C"
3281 |-{
3282 |-SimpleDeclaration
3283 | |-int
3284 | |-SimpleDeclarator
3285 | | `-b
3286 | `-;
3287 |-SimpleDeclaration
3288 | |-int
3289 | |-SimpleDeclarator
3290 | | `-c
3291 | `-;
3292 `-}
3293 )txt"));
3294 }
3295
TEST_P(SyntaxTreeTest,NonModifiableNodes)3296 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3297 // Some nodes are non-modifiable, they are marked with 'I:'.
3298 EXPECT_TRUE(treeDumpEqual(
3299 R"cpp(
3300 #define HALF_IF if (1+
3301 #define HALF_IF_2 1) {}
3302 void test() {
3303 HALF_IF HALF_IF_2 else {}
3304 })cpp",
3305 R"txt(
3306 *: TranslationUnit
3307 `-SimpleDeclaration
3308 |-void
3309 |-SimpleDeclarator
3310 | |-test
3311 | `-ParametersAndQualifiers
3312 | |-(
3313 | `-)
3314 `-CompoundStatement
3315 |-{
3316 |-IfStatement
3317 | |-I: if
3318 | |-I: (
3319 | |-I: BinaryOperatorExpression
3320 | | |-I: IntegerLiteralExpression
3321 | | | `-I: 1
3322 | | |-I: +
3323 | | `-I: IntegerLiteralExpression
3324 | | `-I: 1
3325 | |-I: )
3326 | |-I: CompoundStatement
3327 | | |-I: {
3328 | | `-I: }
3329 | |-else
3330 | `-CompoundStatement
3331 | |-{
3332 | `-}
3333 `-}
3334 )txt"));
3335 }
3336
TEST_P(SyntaxTreeTest,ModifiableNodes)3337 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3338 // All nodes can be mutated.
3339 EXPECT_TRUE(treeDumpEqual(
3340 R"cpp(
3341 #define OPEN {
3342 #define CLOSE }
3343
3344 void test() {
3345 OPEN
3346 1;
3347 CLOSE
3348
3349 OPEN
3350 2;
3351 }
3352 }
3353 )cpp",
3354 R"txt(
3355 *: TranslationUnit
3356 `-SimpleDeclaration
3357 |-void
3358 |-SimpleDeclarator
3359 | |-test
3360 | `-ParametersAndQualifiers
3361 | |-(
3362 | `-)
3363 `-CompoundStatement
3364 |-{
3365 |-CompoundStatement
3366 | |-{
3367 | |-ExpressionStatement
3368 | | |-IntegerLiteralExpression
3369 | | | `-1
3370 | | `-;
3371 | `-}
3372 |-CompoundStatement
3373 | |-{
3374 | |-ExpressionStatement
3375 | | |-IntegerLiteralExpression
3376 | | | `-2
3377 | | `-;
3378 | `-}
3379 `-}
3380 )txt"));
3381 }
3382
TEST_P(SyntaxTreeTest,ArraySubscriptsInDeclarators)3383 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
3384 EXPECT_TRUE(treeDumpEqual(
3385 R"cpp(
3386 int a[10];
3387 int b[1][2][3];
3388 int c[] = {1,2,3};
3389 )cpp",
3390 R"txt(
3391 *: TranslationUnit
3392 |-SimpleDeclaration
3393 | |-int
3394 | |-SimpleDeclarator
3395 | | |-a
3396 | | `-ArraySubscript
3397 | | |-[
3398 | | |-IntegerLiteralExpression
3399 | | | `-10
3400 | | `-]
3401 | `-;
3402 |-SimpleDeclaration
3403 | |-int
3404 | |-SimpleDeclarator
3405 | | |-b
3406 | | |-ArraySubscript
3407 | | | |-[
3408 | | | |-IntegerLiteralExpression
3409 | | | | `-1
3410 | | | `-]
3411 | | |-ArraySubscript
3412 | | | |-[
3413 | | | |-IntegerLiteralExpression
3414 | | | | `-2
3415 | | | `-]
3416 | | `-ArraySubscript
3417 | | |-[
3418 | | |-IntegerLiteralExpression
3419 | | | `-3
3420 | | `-]
3421 | `-;
3422 `-SimpleDeclaration
3423 |-int
3424 |-SimpleDeclarator
3425 | |-c
3426 | |-ArraySubscript
3427 | | |-[
3428 | | `-]
3429 | |-=
3430 | `-UnknownExpression
3431 | `-UnknownExpression
3432 | |-{
3433 | |-IntegerLiteralExpression
3434 | | `-1
3435 | |-,
3436 | |-IntegerLiteralExpression
3437 | | `-2
3438 | |-,
3439 | |-IntegerLiteralExpression
3440 | | `-3
3441 | `-}
3442 `-;
3443 )txt"));
3444 }
3445
TEST_P(SyntaxTreeTest,StaticArraySubscriptsInDeclarators)3446 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
3447 if (!GetParam().isC99OrLater()) {
3448 return;
3449 }
3450 EXPECT_TRUE(treeDumpEqual(
3451 R"cpp(
3452 void f(int xs[static 10]);
3453 )cpp",
3454 R"txt(
3455 *: TranslationUnit
3456 `-SimpleDeclaration
3457 |-void
3458 |-SimpleDeclarator
3459 | |-f
3460 | `-ParametersAndQualifiers
3461 | |-(
3462 | |-SimpleDeclaration
3463 | | |-int
3464 | | `-SimpleDeclarator
3465 | | |-xs
3466 | | `-ArraySubscript
3467 | | |-[
3468 | | |-static
3469 | | |-IntegerLiteralExpression
3470 | | | `-10
3471 | | `-]
3472 | `-)
3473 `-;
3474 )txt"));
3475 }
3476
TEST_P(SyntaxTreeTest,ParametersAndQualifiersInFreeFunctions)3477 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
3478 if (!GetParam().isCXX()) {
3479 return;
3480 }
3481 EXPECT_TRUE(treeDumpEqual(
3482 R"cpp(
3483 int func1();
3484 int func2a(int a);
3485 int func2b(int);
3486 int func3a(int *ap);
3487 int func3b(int *);
3488 int func4a(int a, float b);
3489 int func4b(int, float);
3490 )cpp",
3491 R"txt(
3492 *: TranslationUnit
3493 |-SimpleDeclaration
3494 | |-int
3495 | |-SimpleDeclarator
3496 | | |-func1
3497 | | `-ParametersAndQualifiers
3498 | | |-(
3499 | | `-)
3500 | `-;
3501 |-SimpleDeclaration
3502 | |-int
3503 | |-SimpleDeclarator
3504 | | |-func2a
3505 | | `-ParametersAndQualifiers
3506 | | |-(
3507 | | |-SimpleDeclaration
3508 | | | |-int
3509 | | | `-SimpleDeclarator
3510 | | | `-a
3511 | | `-)
3512 | `-;
3513 |-SimpleDeclaration
3514 | |-int
3515 | |-SimpleDeclarator
3516 | | |-func2b
3517 | | `-ParametersAndQualifiers
3518 | | |-(
3519 | | |-SimpleDeclaration
3520 | | | `-int
3521 | | `-)
3522 | `-;
3523 |-SimpleDeclaration
3524 | |-int
3525 | |-SimpleDeclarator
3526 | | |-func3a
3527 | | `-ParametersAndQualifiers
3528 | | |-(
3529 | | |-SimpleDeclaration
3530 | | | |-int
3531 | | | `-SimpleDeclarator
3532 | | | |-*
3533 | | | `-ap
3534 | | `-)
3535 | `-;
3536 |-SimpleDeclaration
3537 | |-int
3538 | |-SimpleDeclarator
3539 | | |-func3b
3540 | | `-ParametersAndQualifiers
3541 | | |-(
3542 | | |-SimpleDeclaration
3543 | | | |-int
3544 | | | `-SimpleDeclarator
3545 | | | `-*
3546 | | `-)
3547 | `-;
3548 |-SimpleDeclaration
3549 | |-int
3550 | |-SimpleDeclarator
3551 | | |-func4a
3552 | | `-ParametersAndQualifiers
3553 | | |-(
3554 | | |-SimpleDeclaration
3555 | | | |-int
3556 | | | `-SimpleDeclarator
3557 | | | `-a
3558 | | |-,
3559 | | |-SimpleDeclaration
3560 | | | |-float
3561 | | | `-SimpleDeclarator
3562 | | | `-b
3563 | | `-)
3564 | `-;
3565 `-SimpleDeclaration
3566 |-int
3567 |-SimpleDeclarator
3568 | |-func4b
3569 | `-ParametersAndQualifiers
3570 | |-(
3571 | |-SimpleDeclaration
3572 | | `-int
3573 | |-,
3574 | |-SimpleDeclaration
3575 | | `-float
3576 | `-)
3577 `-;
3578 )txt"));
3579 }
3580
TEST_P(SyntaxTreeTest,ParametersAndQualifiersInFreeFunctionsCxx)3581 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
3582 if (!GetParam().isCXX()) {
3583 return;
3584 }
3585 EXPECT_TRUE(treeDumpEqual(
3586 R"cpp(
3587 int func1(const int a, volatile int b, const volatile int c);
3588 int func2(int& a);
3589 )cpp",
3590 R"txt(
3591 *: TranslationUnit
3592 |-SimpleDeclaration
3593 | |-int
3594 | |-SimpleDeclarator
3595 | | |-func1
3596 | | `-ParametersAndQualifiers
3597 | | |-(
3598 | | |-SimpleDeclaration
3599 | | | |-const
3600 | | | |-int
3601 | | | `-SimpleDeclarator
3602 | | | `-a
3603 | | |-,
3604 | | |-SimpleDeclaration
3605 | | | |-volatile
3606 | | | |-int
3607 | | | `-SimpleDeclarator
3608 | | | `-b
3609 | | |-,
3610 | | |-SimpleDeclaration
3611 | | | |-const
3612 | | | |-volatile
3613 | | | |-int
3614 | | | `-SimpleDeclarator
3615 | | | `-c
3616 | | `-)
3617 | `-;
3618 `-SimpleDeclaration
3619 |-int
3620 |-SimpleDeclarator
3621 | |-func2
3622 | `-ParametersAndQualifiers
3623 | |-(
3624 | |-SimpleDeclaration
3625 | | |-int
3626 | | `-SimpleDeclarator
3627 | | |-&
3628 | | `-a
3629 | `-)
3630 `-;
3631 )txt"));
3632 }
3633
TEST_P(SyntaxTreeTest,ParametersAndQualifiersInFreeFunctionsCxx11)3634 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
3635 if (!GetParam().isCXX11OrLater()) {
3636 return;
3637 }
3638 EXPECT_TRUE(treeDumpEqual(
3639 R"cpp(
3640 int func1(int&& a);
3641 )cpp",
3642 R"txt(
3643 *: TranslationUnit
3644 `-SimpleDeclaration
3645 |-int
3646 |-SimpleDeclarator
3647 | |-func1
3648 | `-ParametersAndQualifiers
3649 | |-(
3650 | |-SimpleDeclaration
3651 | | |-int
3652 | | `-SimpleDeclarator
3653 | | |-&&
3654 | | `-a
3655 | `-)
3656 `-;
3657 )txt"));
3658 }
3659
TEST_P(SyntaxTreeTest,ParametersAndQualifiersInMemberFunctions)3660 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
3661 if (!GetParam().isCXX()) {
3662 return;
3663 }
3664 EXPECT_TRUE(treeDumpEqual(
3665 R"cpp(
3666 struct Test {
3667 int a();
3668 int b() const;
3669 int c() volatile;
3670 int d() const volatile;
3671 int e() &;
3672 int f() &&;
3673 };
3674 )cpp",
3675 R"txt(
3676 *: TranslationUnit
3677 `-SimpleDeclaration
3678 |-struct
3679 |-Test
3680 |-{
3681 |-SimpleDeclaration
3682 | |-int
3683 | |-SimpleDeclarator
3684 | | |-a
3685 | | `-ParametersAndQualifiers
3686 | | |-(
3687 | | `-)
3688 | `-;
3689 |-SimpleDeclaration
3690 | |-int
3691 | |-SimpleDeclarator
3692 | | |-b
3693 | | `-ParametersAndQualifiers
3694 | | |-(
3695 | | |-)
3696 | | `-const
3697 | `-;
3698 |-SimpleDeclaration
3699 | |-int
3700 | |-SimpleDeclarator
3701 | | |-c
3702 | | `-ParametersAndQualifiers
3703 | | |-(
3704 | | |-)
3705 | | `-volatile
3706 | `-;
3707 |-SimpleDeclaration
3708 | |-int
3709 | |-SimpleDeclarator
3710 | | |-d
3711 | | `-ParametersAndQualifiers
3712 | | |-(
3713 | | |-)
3714 | | |-const
3715 | | `-volatile
3716 | `-;
3717 |-SimpleDeclaration
3718 | |-int
3719 | |-SimpleDeclarator
3720 | | |-e
3721 | | `-ParametersAndQualifiers
3722 | | |-(
3723 | | |-)
3724 | | `-&
3725 | `-;
3726 |-SimpleDeclaration
3727 | |-int
3728 | |-SimpleDeclarator
3729 | | |-f
3730 | | `-ParametersAndQualifiers
3731 | | |-(
3732 | | |-)
3733 | | `-&&
3734 | `-;
3735 |-}
3736 `-;
3737 )txt"));
3738 }
3739
TEST_P(SyntaxTreeTest,TrailingReturn)3740 TEST_P(SyntaxTreeTest, TrailingReturn) {
3741 if (!GetParam().isCXX11OrLater()) {
3742 return;
3743 }
3744 EXPECT_TRUE(treeDumpEqual(
3745 R"cpp(
3746 auto foo() -> int;
3747 )cpp",
3748 R"txt(
3749 *: TranslationUnit
3750 `-SimpleDeclaration
3751 |-auto
3752 |-SimpleDeclarator
3753 | |-foo
3754 | `-ParametersAndQualifiers
3755 | |-(
3756 | |-)
3757 | `-TrailingReturnType
3758 | |-->
3759 | `-int
3760 `-;
3761 )txt"));
3762 }
3763
TEST_P(SyntaxTreeTest,DynamicExceptionSpecification)3764 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
3765 if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
3766 return;
3767 }
3768 EXPECT_TRUE(treeDumpEqual(
3769 R"cpp(
3770 struct MyException1 {};
3771 struct MyException2 {};
3772 int a() throw();
3773 int b() throw(...);
3774 int c() throw(MyException1);
3775 int d() throw(MyException1, MyException2);
3776 )cpp",
3777 R"txt(
3778 *: TranslationUnit
3779 |-SimpleDeclaration
3780 | |-struct
3781 | |-MyException1
3782 | |-{
3783 | |-}
3784 | `-;
3785 |-SimpleDeclaration
3786 | |-struct
3787 | |-MyException2
3788 | |-{
3789 | |-}
3790 | `-;
3791 |-SimpleDeclaration
3792 | |-int
3793 | |-SimpleDeclarator
3794 | | |-a
3795 | | `-ParametersAndQualifiers
3796 | | |-(
3797 | | |-)
3798 | | |-throw
3799 | | |-(
3800 | | `-)
3801 | `-;
3802 |-SimpleDeclaration
3803 | |-int
3804 | |-SimpleDeclarator
3805 | | |-b
3806 | | `-ParametersAndQualifiers
3807 | | |-(
3808 | | |-)
3809 | | |-throw
3810 | | |-(
3811 | | |-...
3812 | | `-)
3813 | `-;
3814 |-SimpleDeclaration
3815 | |-int
3816 | |-SimpleDeclarator
3817 | | |-c
3818 | | `-ParametersAndQualifiers
3819 | | |-(
3820 | | |-)
3821 | | |-throw
3822 | | |-(
3823 | | |-MyException1
3824 | | `-)
3825 | `-;
3826 `-SimpleDeclaration
3827 |-int
3828 |-SimpleDeclarator
3829 | |-d
3830 | `-ParametersAndQualifiers
3831 | |-(
3832 | |-)
3833 | |-throw
3834 | |-(
3835 | |-MyException1
3836 | |-,
3837 | |-MyException2
3838 | `-)
3839 `-;
3840 )txt"));
3841 }
3842
TEST_P(SyntaxTreeTest,NoexceptExceptionSpecification)3843 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
3844 if (!GetParam().isCXX11OrLater()) {
3845 return;
3846 }
3847 EXPECT_TRUE(treeDumpEqual(
3848 R"cpp(
3849 int a() noexcept;
3850 int b() noexcept(true);
3851 )cpp",
3852 R"txt(
3853 *: TranslationUnit
3854 |-SimpleDeclaration
3855 | |-int
3856 | |-SimpleDeclarator
3857 | | |-a
3858 | | `-ParametersAndQualifiers
3859 | | |-(
3860 | | |-)
3861 | | `-noexcept
3862 | `-;
3863 `-SimpleDeclaration
3864 |-int
3865 |-SimpleDeclarator
3866 | |-b
3867 | `-ParametersAndQualifiers
3868 | |-(
3869 | |-)
3870 | |-noexcept
3871 | |-(
3872 | |-BoolLiteralExpression
3873 | | `-true
3874 | `-)
3875 `-;
3876 )txt"));
3877 }
3878
TEST_P(SyntaxTreeTest,DeclaratorsInParentheses)3879 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
3880 EXPECT_TRUE(treeDumpEqual(
3881 R"cpp(
3882 int (a);
3883 int *(b);
3884 int (*c)(int);
3885 int *(d)(int);
3886 )cpp",
3887 R"txt(
3888 *: TranslationUnit
3889 |-SimpleDeclaration
3890 | |-int
3891 | |-SimpleDeclarator
3892 | | `-ParenDeclarator
3893 | | |-(
3894 | | |-a
3895 | | `-)
3896 | `-;
3897 |-SimpleDeclaration
3898 | |-int
3899 | |-SimpleDeclarator
3900 | | |-*
3901 | | `-ParenDeclarator
3902 | | |-(
3903 | | |-b
3904 | | `-)
3905 | `-;
3906 |-SimpleDeclaration
3907 | |-int
3908 | |-SimpleDeclarator
3909 | | |-ParenDeclarator
3910 | | | |-(
3911 | | | |-*
3912 | | | |-c
3913 | | | `-)
3914 | | `-ParametersAndQualifiers
3915 | | |-(
3916 | | |-SimpleDeclaration
3917 | | | `-int
3918 | | `-)
3919 | `-;
3920 `-SimpleDeclaration
3921 |-int
3922 |-SimpleDeclarator
3923 | |-*
3924 | |-ParenDeclarator
3925 | | |-(
3926 | | |-d
3927 | | `-)
3928 | `-ParametersAndQualifiers
3929 | |-(
3930 | |-SimpleDeclaration
3931 | | `-int
3932 | `-)
3933 `-;
3934 )txt"));
3935 }
3936
TEST_P(SyntaxTreeTest,ConstVolatileQualifiers)3937 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
3938 EXPECT_TRUE(treeDumpEqual(
3939 R"cpp(
3940 const int west = -1;
3941 int const east = 1;
3942 const int const universal = 0;
3943 const int const *const *volatile b;
3944 )cpp",
3945 R"txt(
3946 *: TranslationUnit
3947 |-SimpleDeclaration
3948 | |-const
3949 | |-int
3950 | |-SimpleDeclarator
3951 | | |-west
3952 | | |-=
3953 | | `-PrefixUnaryOperatorExpression
3954 | | |--
3955 | | `-IntegerLiteralExpression
3956 | | `-1
3957 | `-;
3958 |-SimpleDeclaration
3959 | |-int
3960 | |-const
3961 | |-SimpleDeclarator
3962 | | |-east
3963 | | |-=
3964 | | `-IntegerLiteralExpression
3965 | | `-1
3966 | `-;
3967 |-SimpleDeclaration
3968 | |-const
3969 | |-int
3970 | |-const
3971 | |-SimpleDeclarator
3972 | | |-universal
3973 | | |-=
3974 | | `-IntegerLiteralExpression
3975 | | `-0
3976 | `-;
3977 `-SimpleDeclaration
3978 |-const
3979 |-int
3980 |-const
3981 |-SimpleDeclarator
3982 | |-*
3983 | |-const
3984 | |-*
3985 | |-volatile
3986 | `-b
3987 `-;
3988 )txt"));
3989 }
3990
TEST_P(SyntaxTreeTest,RangesOfDeclaratorsWithTrailingReturnTypes)3991 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
3992 if (!GetParam().isCXX11OrLater()) {
3993 return;
3994 }
3995 EXPECT_TRUE(treeDumpEqual(
3996 R"cpp(
3997 auto foo() -> auto(*)(int) -> double*;
3998 )cpp",
3999 R"txt(
4000 *: TranslationUnit
4001 `-SimpleDeclaration
4002 |-auto
4003 |-SimpleDeclarator
4004 | |-foo
4005 | `-ParametersAndQualifiers
4006 | |-(
4007 | |-)
4008 | `-TrailingReturnType
4009 | |-->
4010 | |-auto
4011 | `-SimpleDeclarator
4012 | |-ParenDeclarator
4013 | | |-(
4014 | | |-*
4015 | | `-)
4016 | `-ParametersAndQualifiers
4017 | |-(
4018 | |-SimpleDeclaration
4019 | | `-int
4020 | |-)
4021 | `-TrailingReturnType
4022 | |-->
4023 | |-double
4024 | `-SimpleDeclarator
4025 | `-*
4026 `-;
4027 )txt"));
4028 }
4029
TEST_P(SyntaxTreeTest,MemberPointers)4030 TEST_P(SyntaxTreeTest, MemberPointers) {
4031 if (!GetParam().isCXX()) {
4032 return;
4033 }
4034 EXPECT_TRUE(treeDumpEqual(
4035 R"cpp(
4036 struct X {};
4037 int X::* a;
4038 const int X::* b;
4039 )cpp",
4040 R"txt(
4041 *: TranslationUnit
4042 |-SimpleDeclaration
4043 | |-struct
4044 | |-X
4045 | |-{
4046 | |-}
4047 | `-;
4048 |-SimpleDeclaration
4049 | |-int
4050 | |-SimpleDeclarator
4051 | | |-MemberPointer
4052 | | | |-X
4053 | | | |-::
4054 | | | `-*
4055 | | `-a
4056 | `-;
4057 `-SimpleDeclaration
4058 |-const
4059 |-int
4060 |-SimpleDeclarator
4061 | |-MemberPointer
4062 | | |-X
4063 | | |-::
4064 | | `-*
4065 | `-b
4066 `-;
4067 )txt"));
4068 }
4069
TEST_P(SyntaxTreeTest,ComplexDeclarator)4070 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
4071 EXPECT_TRUE(treeDumpEqual(
4072 R"cpp(
4073 void x(char a, short (*b)(int));
4074 )cpp",
4075 R"txt(
4076 *: TranslationUnit
4077 `-SimpleDeclaration
4078 |-void
4079 |-SimpleDeclarator
4080 | |-x
4081 | `-ParametersAndQualifiers
4082 | |-(
4083 | |-SimpleDeclaration
4084 | | |-char
4085 | | `-SimpleDeclarator
4086 | | `-a
4087 | |-,
4088 | |-SimpleDeclaration
4089 | | |-short
4090 | | `-SimpleDeclarator
4091 | | |-ParenDeclarator
4092 | | | |-(
4093 | | | |-*
4094 | | | |-b
4095 | | | `-)
4096 | | `-ParametersAndQualifiers
4097 | | |-(
4098 | | |-SimpleDeclaration
4099 | | | `-int
4100 | | `-)
4101 | `-)
4102 `-;
4103 )txt"));
4104 }
4105
TEST_P(SyntaxTreeTest,ComplexDeclarator2)4106 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
4107 EXPECT_TRUE(treeDumpEqual(
4108 R"cpp(
4109 void x(char a, short (*b)(int), long (**c)(long long));
4110 )cpp",
4111 R"txt(
4112 *: TranslationUnit
4113 `-SimpleDeclaration
4114 |-void
4115 |-SimpleDeclarator
4116 | |-x
4117 | `-ParametersAndQualifiers
4118 | |-(
4119 | |-SimpleDeclaration
4120 | | |-char
4121 | | `-SimpleDeclarator
4122 | | `-a
4123 | |-,
4124 | |-SimpleDeclaration
4125 | | |-short
4126 | | `-SimpleDeclarator
4127 | | |-ParenDeclarator
4128 | | | |-(
4129 | | | |-*
4130 | | | |-b
4131 | | | `-)
4132 | | `-ParametersAndQualifiers
4133 | | |-(
4134 | | |-SimpleDeclaration
4135 | | | `-int
4136 | | `-)
4137 | |-,
4138 | |-SimpleDeclaration
4139 | | |-long
4140 | | `-SimpleDeclarator
4141 | | |-ParenDeclarator
4142 | | | |-(
4143 | | | |-*
4144 | | | |-*
4145 | | | |-c
4146 | | | `-)
4147 | | `-ParametersAndQualifiers
4148 | | |-(
4149 | | |-SimpleDeclaration
4150 | | | |-long
4151 | | | `-long
4152 | | `-)
4153 | `-)
4154 `-;
4155 )txt"));
4156 }
4157
TEST_P(SyntaxTreeTest,Mutations)4158 TEST_P(SyntaxTreeTest, Mutations) {
4159 if (!GetParam().isCXX11OrLater()) {
4160 return;
4161 }
4162
4163 using Transformation = std::function<void(
4164 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
4165 auto CheckTransformation = [this](std::string Input, std::string Expected,
4166 Transformation Transform) -> void {
4167 llvm::Annotations Source(Input);
4168 auto *Root = buildTree(Source.code(), GetParam());
4169
4170 Transform(Source, Root);
4171
4172 auto Replacements = syntax::computeReplacements(*Arena, *Root);
4173 auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
4174 if (!Output) {
4175 ADD_FAILURE() << "could not apply replacements: "
4176 << llvm::toString(Output.takeError());
4177 return;
4178 }
4179
4180 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
4181 };
4182
4183 // Removes the selected statement. Input should have exactly one selected
4184 // range and it should correspond to a single statement.
4185 auto RemoveStatement = [this](const llvm::Annotations &Input,
4186 syntax::TranslationUnit *TU) {
4187 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
4188 ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
4189 syntax::removeStatement(*Arena, S);
4190 EXPECT_TRUE(S->isDetached());
4191 EXPECT_FALSE(S->isOriginal())
4192 << "node removed from tree cannot be marked as original";
4193 };
4194
4195 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
4196 Cases = {
4197 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"},
4198 {"void test() { if (true) [[{}]] else {} }",
4199 "void test() { if (true) ; else {} }"},
4200 {"void test() { [[;]] }", "void test() { }"}};
4201 for (const auto &C : Cases)
4202 CheckTransformation(C.first, C.second, RemoveStatement);
4203 }
4204
TEST_P(SyntaxTreeTest,SynthesizedNodes)4205 TEST_P(SyntaxTreeTest, SynthesizedNodes) {
4206 buildTree("", GetParam());
4207
4208 auto *C = syntax::createPunctuation(*Arena, tok::comma);
4209 ASSERT_NE(C, nullptr);
4210 EXPECT_EQ(C->token()->kind(), tok::comma);
4211 EXPECT_TRUE(C->canModify());
4212 EXPECT_FALSE(C->isOriginal());
4213 EXPECT_TRUE(C->isDetached());
4214
4215 auto *S = syntax::createEmptyStatement(*Arena);
4216 ASSERT_NE(S, nullptr);
4217 EXPECT_TRUE(S->canModify());
4218 EXPECT_FALSE(S->isOriginal());
4219 EXPECT_TRUE(S->isDetached());
4220 }
4221
allTestClangConfigs()4222 static std::vector<TestClangConfig> allTestClangConfigs() {
4223 std::vector<TestClangConfig> all_configs;
4224 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11,
4225 Lang_CXX14, Lang_CXX17, Lang_CXX20}) {
4226 TestClangConfig config;
4227 config.Language = lang;
4228 config.Target = "x86_64-pc-linux-gnu";
4229 all_configs.push_back(config);
4230
4231 // Windows target is interesting to test because it enables
4232 // `-fdelayed-template-parsing`.
4233 config.Target = "x86_64-pc-win32-msvc";
4234 all_configs.push_back(config);
4235 }
4236 return all_configs;
4237 }
4238
4239 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
4240 testing::ValuesIn(allTestClangConfigs()), );
4241
4242 } // namespace
4243