xref: /llvm-project/clang/unittests/Tooling/Syntax/TreeTest.cpp (revision ea8bba7e8d0db3541a386ad649c4bf21d53e8380)
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 {
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.
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 
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.
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.
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
1187 TEST_P(SyntaxTreeTest, IntegerLiteral) {
1188   EXPECT_TRUE(treeDumpEqual(
1189       R"cpp(
1190 void test() {
1191   12;
1192   12u;
1193   12l;
1194   12ul;
1195   014;
1196   0XC;
1197 }
1198 )cpp",
1199       R"txt(
1200 *: TranslationUnit
1201 `-SimpleDeclaration
1202   |-void
1203   |-SimpleDeclarator
1204   | |-test
1205   | `-ParametersAndQualifiers
1206   |   |-(
1207   |   `-)
1208   `-CompoundStatement
1209     |-{
1210     |-ExpressionStatement
1211     | |-IntegerLiteralExpression
1212     | | `-12
1213     | `-;
1214     |-ExpressionStatement
1215     | |-IntegerLiteralExpression
1216     | | `-12u
1217     | `-;
1218     |-ExpressionStatement
1219     | |-IntegerLiteralExpression
1220     | | `-12l
1221     | `-;
1222     |-ExpressionStatement
1223     | |-IntegerLiteralExpression
1224     | | `-12ul
1225     | `-;
1226     |-ExpressionStatement
1227     | |-IntegerLiteralExpression
1228     | | `-014
1229     | `-;
1230     |-ExpressionStatement
1231     | |-IntegerLiteralExpression
1232     | | `-0XC
1233     | `-;
1234     `-}
1235 )txt"));
1236 }
1237 
1238 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) {
1239   if (!GetParam().isCXX11OrLater()) {
1240     return;
1241   }
1242   EXPECT_TRUE(treeDumpEqual(
1243       R"cpp(
1244 void test() {
1245   12ll;
1246   12ull;
1247 }
1248 )cpp",
1249       R"txt(
1250 *: TranslationUnit
1251 `-SimpleDeclaration
1252   |-void
1253   |-SimpleDeclarator
1254   | |-test
1255   | `-ParametersAndQualifiers
1256   |   |-(
1257   |   `-)
1258   `-CompoundStatement
1259     |-{
1260     |-ExpressionStatement
1261     | |-IntegerLiteralExpression
1262     | | `-12ll
1263     | `-;
1264     |-ExpressionStatement
1265     | |-IntegerLiteralExpression
1266     | | `-12ull
1267     | `-;
1268     `-}
1269 )txt"));
1270 }
1271 
1272 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) {
1273   if (!GetParam().isCXX14OrLater()) {
1274     return;
1275   }
1276   EXPECT_TRUE(treeDumpEqual(
1277       R"cpp(
1278 void test() {
1279   0b1100;
1280 }
1281 )cpp",
1282       R"txt(
1283 *: TranslationUnit
1284 `-SimpleDeclaration
1285   |-void
1286   |-SimpleDeclarator
1287   | |-test
1288   | `-ParametersAndQualifiers
1289   |   |-(
1290   |   `-)
1291   `-CompoundStatement
1292     |-{
1293     |-ExpressionStatement
1294     | |-IntegerLiteralExpression
1295     | | `-0b1100
1296     | `-;
1297     `-}
1298 )txt"));
1299 }
1300 
1301 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) {
1302   if (!GetParam().isCXX14OrLater()) {
1303     return;
1304   }
1305   EXPECT_TRUE(treeDumpEqual(
1306       R"cpp(
1307 void test() {
1308   1'2'0ull;
1309 }
1310 )cpp",
1311       R"txt(
1312 *: TranslationUnit
1313 `-SimpleDeclaration
1314   |-void
1315   |-SimpleDeclarator
1316   | |-test
1317   | `-ParametersAndQualifiers
1318   |   |-(
1319   |   `-)
1320   `-CompoundStatement
1321     |-{
1322     |-ExpressionStatement
1323     | |-IntegerLiteralExpression
1324     | | `-1'2'0ull
1325     | `-;
1326     `-}
1327 )txt"));
1328 }
1329 
1330 TEST_P(SyntaxTreeTest, CharacterLiteral) {
1331   EXPECT_TRUE(treeDumpEqual(
1332       R"cpp(
1333 void test() {
1334   'a';
1335   '\n';
1336   '\x20';
1337   '\0';
1338   L'a';
1339   L'α';
1340 }
1341 )cpp",
1342       R"txt(
1343 *: TranslationUnit
1344 `-SimpleDeclaration
1345   |-void
1346   |-SimpleDeclarator
1347   | |-test
1348   | `-ParametersAndQualifiers
1349   |   |-(
1350   |   `-)
1351   `-CompoundStatement
1352     |-{
1353     |-ExpressionStatement
1354     | |-CharacterLiteralExpression
1355     | | `-'a'
1356     | `-;
1357     |-ExpressionStatement
1358     | |-CharacterLiteralExpression
1359     | | `-'\n'
1360     | `-;
1361     |-ExpressionStatement
1362     | |-CharacterLiteralExpression
1363     | | `-'\x20'
1364     | `-;
1365     |-ExpressionStatement
1366     | |-CharacterLiteralExpression
1367     | | `-'\0'
1368     | `-;
1369     |-ExpressionStatement
1370     | |-CharacterLiteralExpression
1371     | | `-L'a'
1372     | `-;
1373     |-ExpressionStatement
1374     | |-CharacterLiteralExpression
1375     | | `-L'α'
1376     | `-;
1377     `-}
1378 )txt"));
1379 }
1380 
1381 TEST_P(SyntaxTreeTest, CharacterLiteralUtf) {
1382   if (!GetParam().isCXX11OrLater()) {
1383     return;
1384   }
1385   EXPECT_TRUE(treeDumpEqual(
1386       R"cpp(
1387 void test() {
1388   u'a';
1389   u'構';
1390   U'a';
1391   U'��';
1392 }
1393 )cpp",
1394       R"txt(
1395 *: TranslationUnit
1396 `-SimpleDeclaration
1397   |-void
1398   |-SimpleDeclarator
1399   | |-test
1400   | `-ParametersAndQualifiers
1401   |   |-(
1402   |   `-)
1403   `-CompoundStatement
1404     |-{
1405     |-ExpressionStatement
1406     | |-CharacterLiteralExpression
1407     | | `-u'a'
1408     | `-;
1409     |-ExpressionStatement
1410     | |-CharacterLiteralExpression
1411     | | `-u'構'
1412     | `-;
1413     |-ExpressionStatement
1414     | |-CharacterLiteralExpression
1415     | | `-U'a'
1416     | `-;
1417     |-ExpressionStatement
1418     | |-CharacterLiteralExpression
1419     | | `-U'��'
1420     | `-;
1421     `-}
1422 )txt"));
1423 }
1424 
1425 TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) {
1426   if (!GetParam().isCXX17OrLater()) {
1427     return;
1428   }
1429   EXPECT_TRUE(treeDumpEqual(
1430       R"cpp(
1431 void test() {
1432   u8'a';
1433   u8'\x7f';
1434 }
1435 )cpp",
1436       R"txt(
1437 *: TranslationUnit
1438 `-SimpleDeclaration
1439   |-void
1440   |-SimpleDeclarator
1441   | |-test
1442   | `-ParametersAndQualifiers
1443   |   |-(
1444   |   `-)
1445   `-CompoundStatement
1446     |-{
1447     |-ExpressionStatement
1448     | |-CharacterLiteralExpression
1449     | | `-u8'a'
1450     | `-;
1451     |-ExpressionStatement
1452     | |-CharacterLiteralExpression
1453     | | `-u8'\x7f'
1454     | `-;
1455     `-}
1456 )txt"));
1457 }
1458 
1459 TEST_P(SyntaxTreeTest, FloatingLiteral) {
1460   EXPECT_TRUE(treeDumpEqual(
1461       R"cpp(
1462 void test() {
1463   1e-2;
1464   2.;
1465   .2;
1466   2.f;
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     | |-FloatingLiteralExpression
1482     | | `-1e-2
1483     | `-;
1484     |-ExpressionStatement
1485     | |-FloatingLiteralExpression
1486     | | `-2.
1487     | `-;
1488     |-ExpressionStatement
1489     | |-FloatingLiteralExpression
1490     | | `-.2
1491     | `-;
1492     |-ExpressionStatement
1493     | |-FloatingLiteralExpression
1494     | | `-2.f
1495     | `-;
1496     `-}
1497 )txt"));
1498 }
1499 
1500 TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) {
1501   if (!GetParam().isCXX17OrLater()) {
1502     return;
1503   }
1504   EXPECT_TRUE(treeDumpEqual(
1505       R"cpp(
1506 void test() {
1507   0xfp1;
1508   0xf.p1;
1509   0x.fp1;
1510   0xf.fp1f;
1511 }
1512 )cpp",
1513       R"txt(
1514 *: TranslationUnit
1515 `-SimpleDeclaration
1516   |-void
1517   |-SimpleDeclarator
1518   | |-test
1519   | `-ParametersAndQualifiers
1520   |   |-(
1521   |   `-)
1522   `-CompoundStatement
1523     |-{
1524     |-ExpressionStatement
1525     | |-FloatingLiteralExpression
1526     | | `-0xfp1
1527     | `-;
1528     |-ExpressionStatement
1529     | |-FloatingLiteralExpression
1530     | | `-0xf.p1
1531     | `-;
1532     |-ExpressionStatement
1533     | |-FloatingLiteralExpression
1534     | | `-0x.fp1
1535     | `-;
1536     |-ExpressionStatement
1537     | |-FloatingLiteralExpression
1538     | | `-0xf.fp1f
1539     | `-;
1540     `-}
1541 )txt"));
1542 }
1543 
1544 TEST_P(SyntaxTreeTest, StringLiteral) {
1545   EXPECT_TRUE(treeDumpEqual(
1546       R"cpp(
1547 void test() {
1548   "a\n\0\x20";
1549   L"αβ";
1550 }
1551 )cpp",
1552       R"txt(
1553 *: TranslationUnit
1554 `-SimpleDeclaration
1555   |-void
1556   |-SimpleDeclarator
1557   | |-test
1558   | `-ParametersAndQualifiers
1559   |   |-(
1560   |   `-)
1561   `-CompoundStatement
1562     |-{
1563     |-ExpressionStatement
1564     | |-StringLiteralExpression
1565     | | `-"a\n\0\x20"
1566     | `-;
1567     |-ExpressionStatement
1568     | |-StringLiteralExpression
1569     | | `-L"αβ"
1570     | `-;
1571     `-}
1572 )txt"));
1573 }
1574 
1575 TEST_P(SyntaxTreeTest, StringLiteralUtf) {
1576   if (!GetParam().isCXX11OrLater()) {
1577     return;
1578   }
1579   EXPECT_TRUE(treeDumpEqual(
1580       R"cpp(
1581 void test() {
1582   u8"a\x1f\x05";
1583   u"C++抽象構文木";
1584   U"����\n";
1585 }
1586 )cpp",
1587       R"txt(
1588 *: TranslationUnit
1589 `-SimpleDeclaration
1590   |-void
1591   |-SimpleDeclarator
1592   | |-test
1593   | `-ParametersAndQualifiers
1594   |   |-(
1595   |   `-)
1596   `-CompoundStatement
1597     |-{
1598     |-ExpressionStatement
1599     | |-StringLiteralExpression
1600     | | `-u8"a\x1f\x05"
1601     | `-;
1602     |-ExpressionStatement
1603     | |-StringLiteralExpression
1604     | | `-u"C++抽象構文木"
1605     | `-;
1606     |-ExpressionStatement
1607     | |-StringLiteralExpression
1608     | | `-U"����\n"
1609     | `-;
1610     `-}
1611 )txt"));
1612 }
1613 
1614 TEST_P(SyntaxTreeTest, StringLiteralRaw) {
1615   if (!GetParam().isCXX11OrLater()) {
1616     return;
1617   }
1618   // This test uses regular string literals instead of raw string literals to
1619   // hold source code and expected output because of a bug in MSVC up to MSVC
1620   // 2019 16.2:
1621   // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html
1622   EXPECT_TRUE(treeDumpEqual( //
1623       "void test() {\n"
1624       "  R\"SyntaxTree(\n"
1625       "  Hello \"Syntax\" \\\"\n"
1626       "  )SyntaxTree\";\n"
1627       "}\n",
1628       "*: TranslationUnit\n"
1629       "`-SimpleDeclaration\n"
1630       "  |-void\n"
1631       "  |-SimpleDeclarator\n"
1632       "  | |-test\n"
1633       "  | `-ParametersAndQualifiers\n"
1634       "  |   |-(\n"
1635       "  |   `-)\n"
1636       "  `-CompoundStatement\n"
1637       "    |-{\n"
1638       "    |-ExpressionStatement\n"
1639       "    | |-StringLiteralExpression\n"
1640       "    | | `-R\"SyntaxTree(\n"
1641       "  Hello \"Syntax\" \\\"\n"
1642       "  )SyntaxTree\"\n"
1643       "    | `-;\n"
1644       "    `-}\n"));
1645 }
1646 
1647 TEST_P(SyntaxTreeTest, BoolLiteral) {
1648   if (GetParam().isC()) {
1649     return;
1650   }
1651   EXPECT_TRUE(treeDumpEqual(
1652       R"cpp(
1653 void test() {
1654   true;
1655   false;
1656 }
1657 )cpp",
1658       R"txt(
1659 *: TranslationUnit
1660 `-SimpleDeclaration
1661   |-void
1662   |-SimpleDeclarator
1663   | |-test
1664   | `-ParametersAndQualifiers
1665   |   |-(
1666   |   `-)
1667   `-CompoundStatement
1668     |-{
1669     |-ExpressionStatement
1670     | |-BoolLiteralExpression
1671     | | `-true
1672     | `-;
1673     |-ExpressionStatement
1674     | |-BoolLiteralExpression
1675     | | `-false
1676     | `-;
1677     `-}
1678 )txt"));
1679 }
1680 
1681 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) {
1682   if (!GetParam().isCXX11OrLater()) {
1683     return;
1684   }
1685   EXPECT_TRUE(treeDumpEqual(
1686       R"cpp(
1687 void test() {
1688   nullptr;
1689 }
1690 )cpp",
1691       R"txt(
1692 *: TranslationUnit
1693 `-SimpleDeclaration
1694   |-void
1695   |-SimpleDeclarator
1696   | |-test
1697   | `-ParametersAndQualifiers
1698   |   |-(
1699   |   `-)
1700   `-CompoundStatement
1701     |-{
1702     |-ExpressionStatement
1703     | |-CxxNullPtrExpression
1704     | | `-nullptr
1705     | `-;
1706     `-}
1707 )txt"));
1708 }
1709 
1710 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) {
1711   EXPECT_TRUE(treeDumpEqual(
1712       R"cpp(
1713 void test(int a) {
1714   a++;
1715   a--;
1716 }
1717 )cpp",
1718       R"txt(
1719 *: TranslationUnit
1720 `-SimpleDeclaration
1721   |-void
1722   |-SimpleDeclarator
1723   | |-test
1724   | `-ParametersAndQualifiers
1725   |   |-(
1726   |   |-SimpleDeclaration
1727   |   | |-int
1728   |   | `-SimpleDeclarator
1729   |   |   `-a
1730   |   `-)
1731   `-CompoundStatement
1732     |-{
1733     |-ExpressionStatement
1734     | |-PostfixUnaryOperatorExpression
1735     | | |-IdExpression
1736     | | | `-UnqualifiedId
1737     | | |   `-a
1738     | | `-++
1739     | `-;
1740     |-ExpressionStatement
1741     | |-PostfixUnaryOperatorExpression
1742     | | |-IdExpression
1743     | | | `-UnqualifiedId
1744     | | |   `-a
1745     | | `---
1746     | `-;
1747     `-}
1748 )txt"));
1749 }
1750 
1751 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) {
1752   EXPECT_TRUE(treeDumpEqual(
1753       R"cpp(
1754 void test(int a, int *ap) {
1755   --a; ++a;
1756   ~a;
1757   -a;
1758   +a;
1759   &a;
1760   *ap;
1761   !a;
1762   __real a; __imag a;
1763 }
1764 )cpp",
1765       R"txt(
1766 *: TranslationUnit
1767 `-SimpleDeclaration
1768   |-void
1769   |-SimpleDeclarator
1770   | |-test
1771   | `-ParametersAndQualifiers
1772   |   |-(
1773   |   |-SimpleDeclaration
1774   |   | |-int
1775   |   | `-SimpleDeclarator
1776   |   |   `-a
1777   |   |-,
1778   |   |-SimpleDeclaration
1779   |   | |-int
1780   |   | `-SimpleDeclarator
1781   |   |   |-*
1782   |   |   `-ap
1783   |   `-)
1784   `-CompoundStatement
1785     |-{
1786     |-ExpressionStatement
1787     | |-PrefixUnaryOperatorExpression
1788     | | |---
1789     | | `-IdExpression
1790     | |   `-UnqualifiedId
1791     | |     `-a
1792     | `-;
1793     |-ExpressionStatement
1794     | |-PrefixUnaryOperatorExpression
1795     | | |-++
1796     | | `-IdExpression
1797     | |   `-UnqualifiedId
1798     | |     `-a
1799     | `-;
1800     |-ExpressionStatement
1801     | |-PrefixUnaryOperatorExpression
1802     | | |-~
1803     | | `-IdExpression
1804     | |   `-UnqualifiedId
1805     | |     `-a
1806     | `-;
1807     |-ExpressionStatement
1808     | |-PrefixUnaryOperatorExpression
1809     | | |--
1810     | | `-IdExpression
1811     | |   `-UnqualifiedId
1812     | |     `-a
1813     | `-;
1814     |-ExpressionStatement
1815     | |-PrefixUnaryOperatorExpression
1816     | | |-+
1817     | | `-IdExpression
1818     | |   `-UnqualifiedId
1819     | |     `-a
1820     | `-;
1821     |-ExpressionStatement
1822     | |-PrefixUnaryOperatorExpression
1823     | | |-&
1824     | | `-IdExpression
1825     | |   `-UnqualifiedId
1826     | |     `-a
1827     | `-;
1828     |-ExpressionStatement
1829     | |-PrefixUnaryOperatorExpression
1830     | | |-*
1831     | | `-IdExpression
1832     | |   `-UnqualifiedId
1833     | |     `-ap
1834     | `-;
1835     |-ExpressionStatement
1836     | |-PrefixUnaryOperatorExpression
1837     | | |-!
1838     | | `-IdExpression
1839     | |   `-UnqualifiedId
1840     | |     `-a
1841     | `-;
1842     |-ExpressionStatement
1843     | |-PrefixUnaryOperatorExpression
1844     | | |-__real
1845     | | `-IdExpression
1846     | |   `-UnqualifiedId
1847     | |     `-a
1848     | `-;
1849     |-ExpressionStatement
1850     | |-PrefixUnaryOperatorExpression
1851     | | |-__imag
1852     | | `-IdExpression
1853     | |   `-UnqualifiedId
1854     | |     `-a
1855     | `-;
1856     `-}
1857 )txt"));
1858 }
1859 
1860 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) {
1861   if (!GetParam().isCXX()) {
1862     return;
1863   }
1864   EXPECT_TRUE(treeDumpEqual(
1865       R"cpp(
1866 void test(int a, bool b) {
1867   compl a;
1868   not b;
1869 }
1870 )cpp",
1871       R"txt(
1872 *: TranslationUnit
1873 `-SimpleDeclaration
1874   |-void
1875   |-SimpleDeclarator
1876   | |-test
1877   | `-ParametersAndQualifiers
1878   |   |-(
1879   |   |-SimpleDeclaration
1880   |   | |-int
1881   |   | `-SimpleDeclarator
1882   |   |   `-a
1883   |   |-,
1884   |   |-SimpleDeclaration
1885   |   | |-bool
1886   |   | `-SimpleDeclarator
1887   |   |   `-b
1888   |   `-)
1889   `-CompoundStatement
1890     |-{
1891     |-ExpressionStatement
1892     | |-PrefixUnaryOperatorExpression
1893     | | |-compl
1894     | | `-IdExpression
1895     | |   `-UnqualifiedId
1896     | |     `-a
1897     | `-;
1898     |-ExpressionStatement
1899     | |-PrefixUnaryOperatorExpression
1900     | | |-not
1901     | | `-IdExpression
1902     | |   `-UnqualifiedId
1903     | |     `-b
1904     | `-;
1905     `-}
1906 )txt"));
1907 }
1908 
1909 TEST_P(SyntaxTreeTest, BinaryOperator) {
1910   EXPECT_TRUE(treeDumpEqual(
1911       R"cpp(
1912 void test(int a) {
1913   1 - 2;
1914   1 == 2;
1915   a = 1;
1916   a <<= 1;
1917   1 || 0;
1918   1 & 2;
1919   a ^= 3;
1920 }
1921 )cpp",
1922       R"txt(
1923 *: TranslationUnit
1924 `-SimpleDeclaration
1925   |-void
1926   |-SimpleDeclarator
1927   | |-test
1928   | `-ParametersAndQualifiers
1929   |   |-(
1930   |   |-SimpleDeclaration
1931   |   | |-int
1932   |   | `-SimpleDeclarator
1933   |   |   `-a
1934   |   `-)
1935   `-CompoundStatement
1936     |-{
1937     |-ExpressionStatement
1938     | |-BinaryOperatorExpression
1939     | | |-IntegerLiteralExpression
1940     | | | `-1
1941     | | |--
1942     | | `-IntegerLiteralExpression
1943     | |   `-2
1944     | `-;
1945     |-ExpressionStatement
1946     | |-BinaryOperatorExpression
1947     | | |-IntegerLiteralExpression
1948     | | | `-1
1949     | | |-==
1950     | | `-IntegerLiteralExpression
1951     | |   `-2
1952     | `-;
1953     |-ExpressionStatement
1954     | |-BinaryOperatorExpression
1955     | | |-IdExpression
1956     | | | `-UnqualifiedId
1957     | | |   `-a
1958     | | |-=
1959     | | `-IntegerLiteralExpression
1960     | |   `-1
1961     | `-;
1962     |-ExpressionStatement
1963     | |-BinaryOperatorExpression
1964     | | |-IdExpression
1965     | | | `-UnqualifiedId
1966     | | |   `-a
1967     | | |-<<=
1968     | | `-IntegerLiteralExpression
1969     | |   `-1
1970     | `-;
1971     |-ExpressionStatement
1972     | |-BinaryOperatorExpression
1973     | | |-IntegerLiteralExpression
1974     | | | `-1
1975     | | |-||
1976     | | `-IntegerLiteralExpression
1977     | |   `-0
1978     | `-;
1979     |-ExpressionStatement
1980     | |-BinaryOperatorExpression
1981     | | |-IntegerLiteralExpression
1982     | | | `-1
1983     | | |-&
1984     | | `-IntegerLiteralExpression
1985     | |   `-2
1986     | `-;
1987     |-ExpressionStatement
1988     | |-BinaryOperatorExpression
1989     | | |-IdExpression
1990     | | | `-UnqualifiedId
1991     | | |   `-a
1992     | | |-^=
1993     | | `-IntegerLiteralExpression
1994     | |   `-3
1995     | `-;
1996     `-}
1997 )txt"));
1998 }
1999 
2000 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) {
2001   if (!GetParam().isCXX()) {
2002     return;
2003   }
2004   EXPECT_TRUE(treeDumpEqual(
2005       R"cpp(
2006 void test(int a) {
2007   true || false;
2008   true or false;
2009   1 bitand 2;
2010   a xor_eq 3;
2011 }
2012 )cpp",
2013       R"txt(
2014 *: TranslationUnit
2015 `-SimpleDeclaration
2016   |-void
2017   |-SimpleDeclarator
2018   | |-test
2019   | `-ParametersAndQualifiers
2020   |   |-(
2021   |   |-SimpleDeclaration
2022   |   | |-int
2023   |   | `-SimpleDeclarator
2024   |   |   `-a
2025   |   `-)
2026   `-CompoundStatement
2027     |-{
2028     |-ExpressionStatement
2029     | |-BinaryOperatorExpression
2030     | | |-BoolLiteralExpression
2031     | | | `-true
2032     | | |-||
2033     | | `-BoolLiteralExpression
2034     | |   `-false
2035     | `-;
2036     |-ExpressionStatement
2037     | |-BinaryOperatorExpression
2038     | | |-BoolLiteralExpression
2039     | | | `-true
2040     | | |-or
2041     | | `-BoolLiteralExpression
2042     | |   `-false
2043     | `-;
2044     |-ExpressionStatement
2045     | |-BinaryOperatorExpression
2046     | | |-IntegerLiteralExpression
2047     | | | `-1
2048     | | |-bitand
2049     | | `-IntegerLiteralExpression
2050     | |   `-2
2051     | `-;
2052     |-ExpressionStatement
2053     | |-BinaryOperatorExpression
2054     | | |-IdExpression
2055     | | | `-UnqualifiedId
2056     | | |   `-a
2057     | | |-xor_eq
2058     | | `-IntegerLiteralExpression
2059     | |   `-3
2060     | `-;
2061     `-}
2062 )txt"));
2063 }
2064 
2065 TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
2066   EXPECT_TRUE(treeDumpEqual(
2067       R"cpp(
2068 void test(int a, int b) {
2069   (1 + 2) * (4 / 2);
2070   a + b + 42;
2071   a = b = 42;
2072   a + b * 4 + 2;
2073   a % 2 + b * 42;
2074 }
2075 )cpp",
2076       R"txt(
2077 *: TranslationUnit
2078 `-SimpleDeclaration
2079   |-void
2080   |-SimpleDeclarator
2081   | |-test
2082   | `-ParametersAndQualifiers
2083   |   |-(
2084   |   |-SimpleDeclaration
2085   |   | |-int
2086   |   | `-SimpleDeclarator
2087   |   |   `-a
2088   |   |-,
2089   |   |-SimpleDeclaration
2090   |   | |-int
2091   |   | `-SimpleDeclarator
2092   |   |   `-b
2093   |   `-)
2094   `-CompoundStatement
2095     |-{
2096     |-ExpressionStatement
2097     | |-BinaryOperatorExpression
2098     | | |-ParenExpression
2099     | | | |-(
2100     | | | |-BinaryOperatorExpression
2101     | | | | |-IntegerLiteralExpression
2102     | | | | | `-1
2103     | | | | |-+
2104     | | | | `-IntegerLiteralExpression
2105     | | | |   `-2
2106     | | | `-)
2107     | | |-*
2108     | | `-ParenExpression
2109     | |   |-(
2110     | |   |-BinaryOperatorExpression
2111     | |   | |-IntegerLiteralExpression
2112     | |   | | `-4
2113     | |   | |-/
2114     | |   | `-IntegerLiteralExpression
2115     | |   |   `-2
2116     | |   `-)
2117     | `-;
2118     |-ExpressionStatement
2119     | |-BinaryOperatorExpression
2120     | | |-BinaryOperatorExpression
2121     | | | |-IdExpression
2122     | | | | `-UnqualifiedId
2123     | | | |   `-a
2124     | | | |-+
2125     | | | `-IdExpression
2126     | | |   `-UnqualifiedId
2127     | | |     `-b
2128     | | |-+
2129     | | `-IntegerLiteralExpression
2130     | |   `-42
2131     | `-;
2132     |-ExpressionStatement
2133     | |-BinaryOperatorExpression
2134     | | |-IdExpression
2135     | | | `-UnqualifiedId
2136     | | |   `-a
2137     | | |-=
2138     | | `-BinaryOperatorExpression
2139     | |   |-IdExpression
2140     | |   | `-UnqualifiedId
2141     | |   |   `-b
2142     | |   |-=
2143     | |   `-IntegerLiteralExpression
2144     | |     `-42
2145     | `-;
2146     |-ExpressionStatement
2147     | |-BinaryOperatorExpression
2148     | | |-BinaryOperatorExpression
2149     | | | |-IdExpression
2150     | | | | `-UnqualifiedId
2151     | | | |   `-a
2152     | | | |-+
2153     | | | `-BinaryOperatorExpression
2154     | | |   |-IdExpression
2155     | | |   | `-UnqualifiedId
2156     | | |   |   `-b
2157     | | |   |-*
2158     | | |   `-IntegerLiteralExpression
2159     | | |     `-4
2160     | | |-+
2161     | | `-IntegerLiteralExpression
2162     | |   `-2
2163     | `-;
2164     |-ExpressionStatement
2165     | |-BinaryOperatorExpression
2166     | | |-BinaryOperatorExpression
2167     | | | |-IdExpression
2168     | | | | `-UnqualifiedId
2169     | | | |   `-a
2170     | | | |-%
2171     | | | `-IntegerLiteralExpression
2172     | | |   `-2
2173     | | |-+
2174     | | `-BinaryOperatorExpression
2175     | |   |-IdExpression
2176     | |   | `-UnqualifiedId
2177     | |   |   `-b
2178     | |   |-*
2179     | |   `-IntegerLiteralExpression
2180     | |     `-42
2181     | `-;
2182     `-}
2183 )txt"));
2184 }
2185 
2186 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
2187   if (!GetParam().isCXX()) {
2188     return;
2189   }
2190   EXPECT_TRUE(treeDumpEqual(
2191       R"cpp(
2192 struct X {
2193   X& operator=(const X&);
2194   friend X operator+(X, const X&);
2195   friend bool operator<(const X&, const X&);
2196   friend X operator<<(X&, const X&);
2197   X operator,(X&);
2198   // TODO: Fix crash on member function pointer and add a test for `->*`
2199   // TODO: Unbox operators in syntax tree.
2200   // Represent operators by `+` instead of `IdExpression-UnqualifiedId-+`
2201 };
2202 void test(X x, X y) {
2203   x = y;
2204   x + y;
2205   x < y;
2206   x << y;
2207   x, y;
2208 }
2209 )cpp",
2210       R"txt(
2211 *: TranslationUnit
2212 |-SimpleDeclaration
2213 | |-struct
2214 | |-X
2215 | |-{
2216 | |-SimpleDeclaration
2217 | | |-X
2218 | | |-SimpleDeclarator
2219 | | | |-&
2220 | | | |-operator
2221 | | | |-=
2222 | | | `-ParametersAndQualifiers
2223 | | |   |-(
2224 | | |   |-SimpleDeclaration
2225 | | |   | |-const
2226 | | |   | |-X
2227 | | |   | `-SimpleDeclarator
2228 | | |   |   `-&
2229 | | |   `-)
2230 | | `-;
2231 | |-UnknownDeclaration
2232 | | `-SimpleDeclaration
2233 | |   |-friend
2234 | |   |-X
2235 | |   |-SimpleDeclarator
2236 | |   | |-operator
2237 | |   | |-+
2238 | |   | `-ParametersAndQualifiers
2239 | |   |   |-(
2240 | |   |   |-SimpleDeclaration
2241 | |   |   | `-X
2242 | |   |   |-,
2243 | |   |   |-SimpleDeclaration
2244 | |   |   | |-const
2245 | |   |   | |-X
2246 | |   |   | `-SimpleDeclarator
2247 | |   |   |   `-&
2248 | |   |   `-)
2249 | |   `-;
2250 | |-UnknownDeclaration
2251 | | `-SimpleDeclaration
2252 | |   |-friend
2253 | |   |-bool
2254 | |   |-SimpleDeclarator
2255 | |   | |-operator
2256 | |   | |-<
2257 | |   | `-ParametersAndQualifiers
2258 | |   |   |-(
2259 | |   |   |-SimpleDeclaration
2260 | |   |   | |-const
2261 | |   |   | |-X
2262 | |   |   | `-SimpleDeclarator
2263 | |   |   |   `-&
2264 | |   |   |-,
2265 | |   |   |-SimpleDeclaration
2266 | |   |   | |-const
2267 | |   |   | |-X
2268 | |   |   | `-SimpleDeclarator
2269 | |   |   |   `-&
2270 | |   |   `-)
2271 | |   `-;
2272 | |-UnknownDeclaration
2273 | | `-SimpleDeclaration
2274 | |   |-friend
2275 | |   |-X
2276 | |   |-SimpleDeclarator
2277 | |   | |-operator
2278 | |   | |-<<
2279 | |   | `-ParametersAndQualifiers
2280 | |   |   |-(
2281 | |   |   |-SimpleDeclaration
2282 | |   |   | |-X
2283 | |   |   | `-SimpleDeclarator
2284 | |   |   |   `-&
2285 | |   |   |-,
2286 | |   |   |-SimpleDeclaration
2287 | |   |   | |-const
2288 | |   |   | |-X
2289 | |   |   | `-SimpleDeclarator
2290 | |   |   |   `-&
2291 | |   |   `-)
2292 | |   `-;
2293 | |-SimpleDeclaration
2294 | | |-X
2295 | | |-SimpleDeclarator
2296 | | | |-operator
2297 | | | |-,
2298 | | | `-ParametersAndQualifiers
2299 | | |   |-(
2300 | | |   |-SimpleDeclaration
2301 | | |   | |-X
2302 | | |   | `-SimpleDeclarator
2303 | | |   |   `-&
2304 | | |   `-)
2305 | | `-;
2306 | |-}
2307 | `-;
2308 `-SimpleDeclaration
2309   |-void
2310   |-SimpleDeclarator
2311   | |-test
2312   | `-ParametersAndQualifiers
2313   |   |-(
2314   |   |-SimpleDeclaration
2315   |   | |-X
2316   |   | `-SimpleDeclarator
2317   |   |   `-x
2318   |   |-,
2319   |   |-SimpleDeclaration
2320   |   | |-X
2321   |   | `-SimpleDeclarator
2322   |   |   `-y
2323   |   `-)
2324   `-CompoundStatement
2325     |-{
2326     |-ExpressionStatement
2327     | |-BinaryOperatorExpression
2328     | | |-IdExpression
2329     | | | `-UnqualifiedId
2330     | | |   `-x
2331     | | |-IdExpression
2332     | | | `-UnqualifiedId
2333     | | |   `-=
2334     | | `-IdExpression
2335     | |   `-UnqualifiedId
2336     | |     `-y
2337     | `-;
2338     |-ExpressionStatement
2339     | |-BinaryOperatorExpression
2340     | | |-UnknownExpression
2341     | | | `-IdExpression
2342     | | |   `-UnqualifiedId
2343     | | |     `-x
2344     | | |-IdExpression
2345     | | | `-UnqualifiedId
2346     | | |   `-+
2347     | | `-IdExpression
2348     | |   `-UnqualifiedId
2349     | |     `-y
2350     | `-;
2351     |-ExpressionStatement
2352     | |-BinaryOperatorExpression
2353     | | |-IdExpression
2354     | | | `-UnqualifiedId
2355     | | |   `-x
2356     | | |-IdExpression
2357     | | | `-UnqualifiedId
2358     | | |   `-<
2359     | | `-IdExpression
2360     | |   `-UnqualifiedId
2361     | |     `-y
2362     | `-;
2363     |-ExpressionStatement
2364     | |-BinaryOperatorExpression
2365     | | |-IdExpression
2366     | | | `-UnqualifiedId
2367     | | |   `-x
2368     | | |-IdExpression
2369     | | | `-UnqualifiedId
2370     | | |   `-<<
2371     | | `-IdExpression
2372     | |   `-UnqualifiedId
2373     | |     `-y
2374     | `-;
2375     |-ExpressionStatement
2376     | |-BinaryOperatorExpression
2377     | | |-IdExpression
2378     | | | `-UnqualifiedId
2379     | | |   `-x
2380     | | |-IdExpression
2381     | | | `-UnqualifiedId
2382     | | |   `-,
2383     | | `-IdExpression
2384     | |   `-UnqualifiedId
2385     | |     `-y
2386     | `-;
2387     `-}
2388 )txt"));
2389 }
2390 
2391 TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
2392   if (!GetParam().isCXX()) {
2393     return;
2394   }
2395   EXPECT_TRUE(treeDumpEqual(
2396       R"cpp(
2397 struct X {
2398   X operator++();
2399   bool operator!();
2400   X* operator&();
2401 };
2402 void test(X x) {
2403   ++x;
2404   !x;
2405   &x;
2406 }
2407 )cpp",
2408       R"txt(
2409 *: TranslationUnit
2410 |-SimpleDeclaration
2411 | |-struct
2412 | |-X
2413 | |-{
2414 | |-SimpleDeclaration
2415 | | |-X
2416 | | |-SimpleDeclarator
2417 | | | |-operator
2418 | | | |-++
2419 | | | `-ParametersAndQualifiers
2420 | | |   |-(
2421 | | |   `-)
2422 | | `-;
2423 | |-SimpleDeclaration
2424 | | |-bool
2425 | | |-SimpleDeclarator
2426 | | | |-operator
2427 | | | |-!
2428 | | | `-ParametersAndQualifiers
2429 | | |   |-(
2430 | | |   `-)
2431 | | `-;
2432 | |-SimpleDeclaration
2433 | | |-X
2434 | | |-SimpleDeclarator
2435 | | | |-*
2436 | | | |-operator
2437 | | | |-&
2438 | | | `-ParametersAndQualifiers
2439 | | |   |-(
2440 | | |   `-)
2441 | | `-;
2442 | |-}
2443 | `-;
2444 `-SimpleDeclaration
2445   |-void
2446   |-SimpleDeclarator
2447   | |-test
2448   | `-ParametersAndQualifiers
2449   |   |-(
2450   |   |-SimpleDeclaration
2451   |   | |-X
2452   |   | `-SimpleDeclarator
2453   |   |   `-x
2454   |   `-)
2455   `-CompoundStatement
2456     |-{
2457     |-ExpressionStatement
2458     | |-PrefixUnaryOperatorExpression
2459     | | |-IdExpression
2460     | | | `-UnqualifiedId
2461     | | |   `-++
2462     | | `-IdExpression
2463     | |   `-UnqualifiedId
2464     | |     `-x
2465     | `-;
2466     |-ExpressionStatement
2467     | |-PrefixUnaryOperatorExpression
2468     | | |-IdExpression
2469     | | | `-UnqualifiedId
2470     | | |   `-!
2471     | | `-IdExpression
2472     | |   `-UnqualifiedId
2473     | |     `-x
2474     | `-;
2475     |-ExpressionStatement
2476     | |-PrefixUnaryOperatorExpression
2477     | | |-IdExpression
2478     | | | `-UnqualifiedId
2479     | | |   `-&
2480     | | `-IdExpression
2481     | |   `-UnqualifiedId
2482     | |     `-x
2483     | `-;
2484     `-}
2485 )txt"));
2486 }
2487 
2488 TEST_P(SyntaxTreeTest, UserDefinedUnaryPostfixOperator) {
2489   if (!GetParam().isCXX()) {
2490     return;
2491   }
2492   EXPECT_TRUE(treeDumpEqual(
2493       R"cpp(
2494 struct X {
2495   X operator++(int);
2496 };
2497 void test(X x) {
2498   x++;
2499 }
2500 )cpp",
2501       R"txt(
2502 *: TranslationUnit
2503 |-SimpleDeclaration
2504 | |-struct
2505 | |-X
2506 | |-{
2507 | |-SimpleDeclaration
2508 | | |-X
2509 | | |-SimpleDeclarator
2510 | | | |-operator
2511 | | | |-++
2512 | | | `-ParametersAndQualifiers
2513 | | |   |-(
2514 | | |   |-SimpleDeclaration
2515 | | |   | `-int
2516 | | |   `-)
2517 | | `-;
2518 | |-}
2519 | `-;
2520 `-SimpleDeclaration
2521   |-void
2522   |-SimpleDeclarator
2523   | |-test
2524   | `-ParametersAndQualifiers
2525   |   |-(
2526   |   |-SimpleDeclaration
2527   |   | |-X
2528   |   | `-SimpleDeclarator
2529   |   |   `-x
2530   |   `-)
2531   `-CompoundStatement
2532     |-{
2533     |-ExpressionStatement
2534     | |-PostfixUnaryOperatorExpression
2535     | | |-IdExpression
2536     | | | `-UnqualifiedId
2537     | | |   `-x
2538     | | `-IdExpression
2539     | |   `-UnqualifiedId
2540     | |     `-++
2541     | `-;
2542     `-}
2543 )txt"));
2544 }
2545 
2546 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
2547   EXPECT_TRUE(treeDumpEqual(
2548       R"cpp(
2549 int *a, b;
2550 int *c, d;
2551 )cpp",
2552       R"txt(
2553 *: TranslationUnit
2554 |-SimpleDeclaration
2555 | |-int
2556 | |-SimpleDeclarator
2557 | | |-*
2558 | | `-a
2559 | |-,
2560 | |-SimpleDeclarator
2561 | | `-b
2562 | `-;
2563 `-SimpleDeclaration
2564   |-int
2565   |-SimpleDeclarator
2566   | |-*
2567   | `-c
2568   |-,
2569   |-SimpleDeclarator
2570   | `-d
2571   `-;
2572 )txt"));
2573 }
2574 
2575 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2576   EXPECT_TRUE(treeDumpEqual(
2577       R"cpp(
2578 typedef int *a, b;
2579 )cpp",
2580       R"txt(
2581 *: TranslationUnit
2582 `-SimpleDeclaration
2583   |-typedef
2584   |-int
2585   |-SimpleDeclarator
2586   | |-*
2587   | `-a
2588   |-,
2589   |-SimpleDeclarator
2590   | `-b
2591   `-;
2592 )txt"));
2593 }
2594 
2595 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2596   EXPECT_TRUE(treeDumpEqual(
2597       R"cpp(
2598 void foo() {
2599   int *a, b;
2600   typedef int *ta, tb;
2601 }
2602 )cpp",
2603       R"txt(
2604 *: TranslationUnit
2605 `-SimpleDeclaration
2606   |-void
2607   |-SimpleDeclarator
2608   | |-foo
2609   | `-ParametersAndQualifiers
2610   |   |-(
2611   |   `-)
2612   `-CompoundStatement
2613     |-{
2614     |-DeclarationStatement
2615     | |-SimpleDeclaration
2616     | | |-int
2617     | | |-SimpleDeclarator
2618     | | | |-*
2619     | | | `-a
2620     | | |-,
2621     | | `-SimpleDeclarator
2622     | |   `-b
2623     | `-;
2624     |-DeclarationStatement
2625     | |-SimpleDeclaration
2626     | | |-typedef
2627     | | |-int
2628     | | |-SimpleDeclarator
2629     | | | |-*
2630     | | | `-ta
2631     | | |-,
2632     | | `-SimpleDeclarator
2633     | |   `-tb
2634     | `-;
2635     `-}
2636 )txt"));
2637 }
2638 
2639 TEST_P(SyntaxTreeTest, Namespaces) {
2640   if (!GetParam().isCXX()) {
2641     return;
2642   }
2643   EXPECT_TRUE(treeDumpEqual(
2644       R"cpp(
2645 namespace a { namespace b {} }
2646 namespace a::b {}
2647 namespace {}
2648 
2649 namespace foo = a;
2650 )cpp",
2651       R"txt(
2652 *: TranslationUnit
2653 |-NamespaceDefinition
2654 | |-namespace
2655 | |-a
2656 | |-{
2657 | |-NamespaceDefinition
2658 | | |-namespace
2659 | | |-b
2660 | | |-{
2661 | | `-}
2662 | `-}
2663 |-NamespaceDefinition
2664 | |-namespace
2665 | |-a
2666 | |-::
2667 | |-b
2668 | |-{
2669 | `-}
2670 |-NamespaceDefinition
2671 | |-namespace
2672 | |-{
2673 | `-}
2674 `-NamespaceAliasDefinition
2675   |-namespace
2676   |-foo
2677   |-=
2678   |-a
2679   `-;
2680 )txt"));
2681 }
2682 
2683 TEST_P(SyntaxTreeTest, UsingDirective) {
2684   if (!GetParam().isCXX()) {
2685     return;
2686   }
2687   EXPECT_TRUE(treeDumpEqual(
2688       R"cpp(
2689 namespace ns {}
2690 using namespace ::ns;
2691 )cpp",
2692       R"txt(
2693 *: TranslationUnit
2694 |-NamespaceDefinition
2695 | |-namespace
2696 | |-ns
2697 | |-{
2698 | `-}
2699 `-UsingNamespaceDirective
2700   |-using
2701   |-namespace
2702   |-::
2703   |-ns
2704   `-;
2705 )txt"));
2706 }
2707 
2708 TEST_P(SyntaxTreeTest, UsingDeclaration) {
2709   if (!GetParam().isCXX()) {
2710     return;
2711   }
2712   EXPECT_TRUE(treeDumpEqual(
2713       R"cpp(
2714 namespace ns { int a; }
2715 using ns::a;
2716 )cpp",
2717       R"txt(
2718 *: TranslationUnit
2719 |-NamespaceDefinition
2720 | |-namespace
2721 | |-ns
2722 | |-{
2723 | |-SimpleDeclaration
2724 | | |-int
2725 | | |-SimpleDeclarator
2726 | | | `-a
2727 | | `-;
2728 | `-}
2729 `-UsingDeclaration
2730   |-using
2731   |-ns
2732   |-::
2733   |-a
2734   `-;
2735 )txt"));
2736 }
2737 
2738 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
2739   // Free-standing classes, must live inside a SimpleDeclaration.
2740   EXPECT_TRUE(treeDumpEqual(
2741       R"cpp(
2742 struct X;
2743 struct X {};
2744 
2745 struct Y *y1;
2746 struct Y {} *y2;
2747 
2748 struct {} *a1;
2749 )cpp",
2750       R"txt(
2751 *: TranslationUnit
2752 |-SimpleDeclaration
2753 | |-struct
2754 | |-X
2755 | `-;
2756 |-SimpleDeclaration
2757 | |-struct
2758 | |-X
2759 | |-{
2760 | |-}
2761 | `-;
2762 |-SimpleDeclaration
2763 | |-struct
2764 | |-Y
2765 | |-SimpleDeclarator
2766 | | |-*
2767 | | `-y1
2768 | `-;
2769 |-SimpleDeclaration
2770 | |-struct
2771 | |-Y
2772 | |-{
2773 | |-}
2774 | |-SimpleDeclarator
2775 | | |-*
2776 | | `-y2
2777 | `-;
2778 `-SimpleDeclaration
2779   |-struct
2780   |-{
2781   |-}
2782   |-SimpleDeclarator
2783   | |-*
2784   | `-a1
2785   `-;
2786 )txt"));
2787 }
2788 
2789 TEST_P(SyntaxTreeTest, Templates) {
2790   if (!GetParam().isCXX()) {
2791     return;
2792   }
2793   if (GetParam().hasDelayedTemplateParsing()) {
2794     // FIXME: Make this test work on Windows by generating the expected syntax
2795     // tree when `-fdelayed-template-parsing` is active.
2796     return;
2797   }
2798   EXPECT_TRUE(treeDumpEqual(
2799       R"cpp(
2800 template <class T> struct cls {};
2801 template <class T> int var = 10;
2802 template <class T> int fun() {}
2803 )cpp",
2804       R"txt(
2805 *: TranslationUnit
2806 |-TemplateDeclaration
2807 | |-template
2808 | |-<
2809 | |-UnknownDeclaration
2810 | | |-class
2811 | | `-T
2812 | |->
2813 | `-SimpleDeclaration
2814 |   |-struct
2815 |   |-cls
2816 |   |-{
2817 |   |-}
2818 |   `-;
2819 |-TemplateDeclaration
2820 | |-template
2821 | |-<
2822 | |-UnknownDeclaration
2823 | | |-class
2824 | | `-T
2825 | |->
2826 | `-SimpleDeclaration
2827 |   |-int
2828 |   |-SimpleDeclarator
2829 |   | |-var
2830 |   | |-=
2831 |   | `-IntegerLiteralExpression
2832 |   |   `-10
2833 |   `-;
2834 `-TemplateDeclaration
2835   |-template
2836   |-<
2837   |-UnknownDeclaration
2838   | |-class
2839   | `-T
2840   |->
2841   `-SimpleDeclaration
2842     |-int
2843     |-SimpleDeclarator
2844     | |-fun
2845     | `-ParametersAndQualifiers
2846     |   |-(
2847     |   `-)
2848     `-CompoundStatement
2849       |-{
2850       `-}
2851 )txt"));
2852 }
2853 
2854 TEST_P(SyntaxTreeTest, NestedTemplates) {
2855   if (!GetParam().isCXX()) {
2856     return;
2857   }
2858   EXPECT_TRUE(treeDumpEqual(
2859       R"cpp(
2860 template <class T>
2861 struct X {
2862   template <class U>
2863   U foo();
2864 };
2865 )cpp",
2866       R"txt(
2867 *: TranslationUnit
2868 `-TemplateDeclaration
2869   |-template
2870   |-<
2871   |-UnknownDeclaration
2872   | |-class
2873   | `-T
2874   |->
2875   `-SimpleDeclaration
2876     |-struct
2877     |-X
2878     |-{
2879     |-TemplateDeclaration
2880     | |-template
2881     | |-<
2882     | |-UnknownDeclaration
2883     | | |-class
2884     | | `-U
2885     | |->
2886     | `-SimpleDeclaration
2887     |   |-U
2888     |   |-SimpleDeclarator
2889     |   | |-foo
2890     |   | `-ParametersAndQualifiers
2891     |   |   |-(
2892     |   |   `-)
2893     |   `-;
2894     |-}
2895     `-;
2896 )txt"));
2897 }
2898 
2899 TEST_P(SyntaxTreeTest, Templates2) {
2900   if (!GetParam().isCXX()) {
2901     return;
2902   }
2903   EXPECT_TRUE(treeDumpEqual(
2904       R"cpp(
2905 template <class T> struct X { struct Y; };
2906 template <class T> struct X<T>::Y {};
2907 )cpp",
2908       R"txt(
2909 *: TranslationUnit
2910 |-TemplateDeclaration
2911 | |-template
2912 | |-<
2913 | |-UnknownDeclaration
2914 | | |-class
2915 | | `-T
2916 | |->
2917 | `-SimpleDeclaration
2918 |   |-struct
2919 |   |-X
2920 |   |-{
2921 |   |-SimpleDeclaration
2922 |   | |-struct
2923 |   | |-Y
2924 |   | `-;
2925 |   |-}
2926 |   `-;
2927 `-TemplateDeclaration
2928   |-template
2929   |-<
2930   |-UnknownDeclaration
2931   | |-class
2932   | `-T
2933   |->
2934   `-SimpleDeclaration
2935     |-struct
2936     |-X
2937     |-<
2938     |-T
2939     |->
2940     |-::
2941     |-Y
2942     |-{
2943     |-}
2944     `-;
2945 )txt"));
2946 }
2947 
2948 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
2949   if (!GetParam().isCXX()) {
2950     return;
2951   }
2952   EXPECT_TRUE(treeDumpEqual(
2953       R"cpp(
2954 template <class T> struct X {
2955   using T::foo;
2956   using typename T::bar;
2957 };
2958 )cpp",
2959       R"txt(
2960 *: TranslationUnit
2961 `-TemplateDeclaration
2962   |-template
2963   |-<
2964   |-UnknownDeclaration
2965   | |-class
2966   | `-T
2967   |->
2968   `-SimpleDeclaration
2969     |-struct
2970     |-X
2971     |-{
2972     |-UsingDeclaration
2973     | |-using
2974     | |-T
2975     | |-::
2976     | |-foo
2977     | `-;
2978     |-UsingDeclaration
2979     | |-using
2980     | |-typename
2981     | |-T
2982     | |-::
2983     | |-bar
2984     | `-;
2985     |-}
2986     `-;
2987 )txt"));
2988 }
2989 
2990 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
2991   if (!GetParam().isCXX()) {
2992     return;
2993   }
2994   EXPECT_TRUE(treeDumpEqual(
2995       R"cpp(
2996 template <class T> struct X {};
2997 template <class T> struct X<T*> {};
2998 template <> struct X<int> {};
2999 
3000 template struct X<double>;
3001 extern template struct X<float>;
3002 )cpp",
3003       R"txt(
3004 *: TranslationUnit
3005 |-TemplateDeclaration
3006 | |-template
3007 | |-<
3008 | |-UnknownDeclaration
3009 | | |-class
3010 | | `-T
3011 | |->
3012 | `-SimpleDeclaration
3013 |   |-struct
3014 |   |-X
3015 |   |-{
3016 |   |-}
3017 |   `-;
3018 |-TemplateDeclaration
3019 | |-template
3020 | |-<
3021 | |-UnknownDeclaration
3022 | | |-class
3023 | | `-T
3024 | |->
3025 | `-SimpleDeclaration
3026 |   |-struct
3027 |   |-X
3028 |   |-<
3029 |   |-T
3030 |   |-*
3031 |   |->
3032 |   |-{
3033 |   |-}
3034 |   `-;
3035 |-TemplateDeclaration
3036 | |-template
3037 | |-<
3038 | |->
3039 | `-SimpleDeclaration
3040 |   |-struct
3041 |   |-X
3042 |   |-<
3043 |   |-int
3044 |   |->
3045 |   |-{
3046 |   |-}
3047 |   `-;
3048 |-ExplicitTemplateInstantiation
3049 | |-template
3050 | `-SimpleDeclaration
3051 |   |-struct
3052 |   |-X
3053 |   |-<
3054 |   |-double
3055 |   |->
3056 |   `-;
3057 `-ExplicitTemplateInstantiation
3058   |-extern
3059   |-template
3060   `-SimpleDeclaration
3061     |-struct
3062     |-X
3063     |-<
3064     |-float
3065     |->
3066     `-;
3067 )txt"));
3068 }
3069 
3070 TEST_P(SyntaxTreeTest, UsingType) {
3071   if (!GetParam().isCXX()) {
3072     return;
3073   }
3074   EXPECT_TRUE(treeDumpEqual(
3075       R"cpp(
3076 using type = int;
3077 )cpp",
3078       R"txt(
3079 *: TranslationUnit
3080 `-TypeAliasDeclaration
3081   |-using
3082   |-type
3083   |-=
3084   |-int
3085   `-;
3086 )txt"));
3087 }
3088 
3089 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3090   EXPECT_TRUE(treeDumpEqual(
3091       R"cpp(
3092 ;
3093 )cpp",
3094       R"txt(
3095 *: TranslationUnit
3096 `-EmptyDeclaration
3097   `-;
3098 )txt"));
3099 }
3100 
3101 TEST_P(SyntaxTreeTest, StaticAssert) {
3102   if (!GetParam().isCXX11OrLater()) {
3103     return;
3104   }
3105   EXPECT_TRUE(treeDumpEqual(
3106       R"cpp(
3107 static_assert(true, "message");
3108 static_assert(true);
3109 )cpp",
3110       R"txt(
3111 *: TranslationUnit
3112 |-StaticAssertDeclaration
3113 | |-static_assert
3114 | |-(
3115 | |-BoolLiteralExpression
3116 | | `-true
3117 | |-,
3118 | |-StringLiteralExpression
3119 | | `-"message"
3120 | |-)
3121 | `-;
3122 `-StaticAssertDeclaration
3123   |-static_assert
3124   |-(
3125   |-BoolLiteralExpression
3126   | `-true
3127   |-)
3128   `-;
3129 )txt"));
3130 }
3131 
3132 TEST_P(SyntaxTreeTest, ExternC) {
3133   if (!GetParam().isCXX()) {
3134     return;
3135   }
3136   EXPECT_TRUE(treeDumpEqual(
3137       R"cpp(
3138 extern "C" int a;
3139 extern "C" { int b; int c; }
3140 )cpp",
3141       R"txt(
3142 *: TranslationUnit
3143 |-LinkageSpecificationDeclaration
3144 | |-extern
3145 | |-"C"
3146 | `-SimpleDeclaration
3147 |   |-int
3148 |   |-SimpleDeclarator
3149 |   | `-a
3150 |   `-;
3151 `-LinkageSpecificationDeclaration
3152   |-extern
3153   |-"C"
3154   |-{
3155   |-SimpleDeclaration
3156   | |-int
3157   | |-SimpleDeclarator
3158   | | `-b
3159   | `-;
3160   |-SimpleDeclaration
3161   | |-int
3162   | |-SimpleDeclarator
3163   | | `-c
3164   | `-;
3165   `-}
3166 )txt"));
3167 }
3168 
3169 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3170   // Some nodes are non-modifiable, they are marked with 'I:'.
3171   EXPECT_TRUE(treeDumpEqual(
3172       R"cpp(
3173 #define HALF_IF if (1+
3174 #define HALF_IF_2 1) {}
3175 void test() {
3176   HALF_IF HALF_IF_2 else {}
3177 })cpp",
3178       R"txt(
3179 *: TranslationUnit
3180 `-SimpleDeclaration
3181   |-void
3182   |-SimpleDeclarator
3183   | |-test
3184   | `-ParametersAndQualifiers
3185   |   |-(
3186   |   `-)
3187   `-CompoundStatement
3188     |-{
3189     |-IfStatement
3190     | |-I: if
3191     | |-I: (
3192     | |-I: BinaryOperatorExpression
3193     | | |-I: IntegerLiteralExpression
3194     | | | `-I: 1
3195     | | |-I: +
3196     | | `-I: IntegerLiteralExpression
3197     | |   `-I: 1
3198     | |-I: )
3199     | |-I: CompoundStatement
3200     | | |-I: {
3201     | | `-I: }
3202     | |-else
3203     | `-CompoundStatement
3204     |   |-{
3205     |   `-}
3206     `-}
3207 )txt"));
3208 }
3209 
3210 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3211   // All nodes can be mutated.
3212   EXPECT_TRUE(treeDumpEqual(
3213       R"cpp(
3214 #define OPEN {
3215 #define CLOSE }
3216 
3217 void test() {
3218   OPEN
3219     1;
3220   CLOSE
3221 
3222   OPEN
3223     2;
3224   }
3225 }
3226 )cpp",
3227       R"txt(
3228 *: TranslationUnit
3229 `-SimpleDeclaration
3230   |-void
3231   |-SimpleDeclarator
3232   | |-test
3233   | `-ParametersAndQualifiers
3234   |   |-(
3235   |   `-)
3236   `-CompoundStatement
3237     |-{
3238     |-CompoundStatement
3239     | |-{
3240     | |-ExpressionStatement
3241     | | |-IntegerLiteralExpression
3242     | | | `-1
3243     | | `-;
3244     | `-}
3245     |-CompoundStatement
3246     | |-{
3247     | |-ExpressionStatement
3248     | | |-IntegerLiteralExpression
3249     | | | `-2
3250     | | `-;
3251     | `-}
3252     `-}
3253 )txt"));
3254 }
3255 
3256 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
3257   EXPECT_TRUE(treeDumpEqual(
3258       R"cpp(
3259 int a[10];
3260 int b[1][2][3];
3261 int c[] = {1,2,3};
3262 )cpp",
3263       R"txt(
3264 *: TranslationUnit
3265 |-SimpleDeclaration
3266 | |-int
3267 | |-SimpleDeclarator
3268 | | |-a
3269 | | `-ArraySubscript
3270 | |   |-[
3271 | |   |-IntegerLiteralExpression
3272 | |   | `-10
3273 | |   `-]
3274 | `-;
3275 |-SimpleDeclaration
3276 | |-int
3277 | |-SimpleDeclarator
3278 | | |-b
3279 | | |-ArraySubscript
3280 | | | |-[
3281 | | | |-IntegerLiteralExpression
3282 | | | | `-1
3283 | | | `-]
3284 | | |-ArraySubscript
3285 | | | |-[
3286 | | | |-IntegerLiteralExpression
3287 | | | | `-2
3288 | | | `-]
3289 | | `-ArraySubscript
3290 | |   |-[
3291 | |   |-IntegerLiteralExpression
3292 | |   | `-3
3293 | |   `-]
3294 | `-;
3295 `-SimpleDeclaration
3296   |-int
3297   |-SimpleDeclarator
3298   | |-c
3299   | |-ArraySubscript
3300   | | |-[
3301   | | `-]
3302   | |-=
3303   | `-UnknownExpression
3304   |   `-UnknownExpression
3305   |     |-{
3306   |     |-IntegerLiteralExpression
3307   |     | `-1
3308   |     |-,
3309   |     |-IntegerLiteralExpression
3310   |     | `-2
3311   |     |-,
3312   |     |-IntegerLiteralExpression
3313   |     | `-3
3314   |     `-}
3315   `-;
3316 )txt"));
3317 }
3318 
3319 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
3320   if (!GetParam().isC99OrLater()) {
3321     return;
3322   }
3323   EXPECT_TRUE(treeDumpEqual(
3324       R"cpp(
3325 void f(int xs[static 10]);
3326 )cpp",
3327       R"txt(
3328 *: TranslationUnit
3329 `-SimpleDeclaration
3330   |-void
3331   |-SimpleDeclarator
3332   | |-f
3333   | `-ParametersAndQualifiers
3334   |   |-(
3335   |   |-SimpleDeclaration
3336   |   | |-int
3337   |   | `-SimpleDeclarator
3338   |   |   |-xs
3339   |   |   `-ArraySubscript
3340   |   |     |-[
3341   |   |     |-static
3342   |   |     |-IntegerLiteralExpression
3343   |   |     | `-10
3344   |   |     `-]
3345   |   `-)
3346   `-;
3347 )txt"));
3348 }
3349 
3350 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
3351   if (!GetParam().isCXX()) {
3352     return;
3353   }
3354   EXPECT_TRUE(treeDumpEqual(
3355       R"cpp(
3356 int func1();
3357 int func2a(int a);
3358 int func2b(int);
3359 int func3a(int *ap);
3360 int func3b(int *);
3361 int func4a(int a, float b);
3362 int func4b(int, float);
3363 )cpp",
3364       R"txt(
3365 *: TranslationUnit
3366 |-SimpleDeclaration
3367 | |-int
3368 | |-SimpleDeclarator
3369 | | |-func1
3370 | | `-ParametersAndQualifiers
3371 | |   |-(
3372 | |   `-)
3373 | `-;
3374 |-SimpleDeclaration
3375 | |-int
3376 | |-SimpleDeclarator
3377 | | |-func2a
3378 | | `-ParametersAndQualifiers
3379 | |   |-(
3380 | |   |-SimpleDeclaration
3381 | |   | |-int
3382 | |   | `-SimpleDeclarator
3383 | |   |   `-a
3384 | |   `-)
3385 | `-;
3386 |-SimpleDeclaration
3387 | |-int
3388 | |-SimpleDeclarator
3389 | | |-func2b
3390 | | `-ParametersAndQualifiers
3391 | |   |-(
3392 | |   |-SimpleDeclaration
3393 | |   | `-int
3394 | |   `-)
3395 | `-;
3396 |-SimpleDeclaration
3397 | |-int
3398 | |-SimpleDeclarator
3399 | | |-func3a
3400 | | `-ParametersAndQualifiers
3401 | |   |-(
3402 | |   |-SimpleDeclaration
3403 | |   | |-int
3404 | |   | `-SimpleDeclarator
3405 | |   |   |-*
3406 | |   |   `-ap
3407 | |   `-)
3408 | `-;
3409 |-SimpleDeclaration
3410 | |-int
3411 | |-SimpleDeclarator
3412 | | |-func3b
3413 | | `-ParametersAndQualifiers
3414 | |   |-(
3415 | |   |-SimpleDeclaration
3416 | |   | |-int
3417 | |   | `-SimpleDeclarator
3418 | |   |   `-*
3419 | |   `-)
3420 | `-;
3421 |-SimpleDeclaration
3422 | |-int
3423 | |-SimpleDeclarator
3424 | | |-func4a
3425 | | `-ParametersAndQualifiers
3426 | |   |-(
3427 | |   |-SimpleDeclaration
3428 | |   | |-int
3429 | |   | `-SimpleDeclarator
3430 | |   |   `-a
3431 | |   |-,
3432 | |   |-SimpleDeclaration
3433 | |   | |-float
3434 | |   | `-SimpleDeclarator
3435 | |   |   `-b
3436 | |   `-)
3437 | `-;
3438 `-SimpleDeclaration
3439   |-int
3440   |-SimpleDeclarator
3441   | |-func4b
3442   | `-ParametersAndQualifiers
3443   |   |-(
3444   |   |-SimpleDeclaration
3445   |   | `-int
3446   |   |-,
3447   |   |-SimpleDeclaration
3448   |   | `-float
3449   |   `-)
3450   `-;
3451 )txt"));
3452 }
3453 
3454 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
3455   if (!GetParam().isCXX()) {
3456     return;
3457   }
3458   EXPECT_TRUE(treeDumpEqual(
3459       R"cpp(
3460 int func1(const int a, volatile int b, const volatile int c);
3461 int func2(int& a);
3462 )cpp",
3463       R"txt(
3464 *: TranslationUnit
3465 |-SimpleDeclaration
3466 | |-int
3467 | |-SimpleDeclarator
3468 | | |-func1
3469 | | `-ParametersAndQualifiers
3470 | |   |-(
3471 | |   |-SimpleDeclaration
3472 | |   | |-const
3473 | |   | |-int
3474 | |   | `-SimpleDeclarator
3475 | |   |   `-a
3476 | |   |-,
3477 | |   |-SimpleDeclaration
3478 | |   | |-volatile
3479 | |   | |-int
3480 | |   | `-SimpleDeclarator
3481 | |   |   `-b
3482 | |   |-,
3483 | |   |-SimpleDeclaration
3484 | |   | |-const
3485 | |   | |-volatile
3486 | |   | |-int
3487 | |   | `-SimpleDeclarator
3488 | |   |   `-c
3489 | |   `-)
3490 | `-;
3491 `-SimpleDeclaration
3492   |-int
3493   |-SimpleDeclarator
3494   | |-func2
3495   | `-ParametersAndQualifiers
3496   |   |-(
3497   |   |-SimpleDeclaration
3498   |   | |-int
3499   |   | `-SimpleDeclarator
3500   |   |   |-&
3501   |   |   `-a
3502   |   `-)
3503   `-;
3504 )txt"));
3505 }
3506 
3507 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
3508   if (!GetParam().isCXX11OrLater()) {
3509     return;
3510   }
3511   EXPECT_TRUE(treeDumpEqual(
3512       R"cpp(
3513 int func1(int&& a);
3514 )cpp",
3515       R"txt(
3516 *: TranslationUnit
3517 `-SimpleDeclaration
3518   |-int
3519   |-SimpleDeclarator
3520   | |-func1
3521   | `-ParametersAndQualifiers
3522   |   |-(
3523   |   |-SimpleDeclaration
3524   |   | |-int
3525   |   | `-SimpleDeclarator
3526   |   |   |-&&
3527   |   |   `-a
3528   |   `-)
3529   `-;
3530 )txt"));
3531 }
3532 
3533 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
3534   if (!GetParam().isCXX()) {
3535     return;
3536   }
3537   EXPECT_TRUE(treeDumpEqual(
3538       R"cpp(
3539 struct Test {
3540   int a();
3541   int b() const;
3542   int c() volatile;
3543   int d() const volatile;
3544   int e() &;
3545   int f() &&;
3546 };
3547 )cpp",
3548       R"txt(
3549 *: TranslationUnit
3550 `-SimpleDeclaration
3551   |-struct
3552   |-Test
3553   |-{
3554   |-SimpleDeclaration
3555   | |-int
3556   | |-SimpleDeclarator
3557   | | |-a
3558   | | `-ParametersAndQualifiers
3559   | |   |-(
3560   | |   `-)
3561   | `-;
3562   |-SimpleDeclaration
3563   | |-int
3564   | |-SimpleDeclarator
3565   | | |-b
3566   | | `-ParametersAndQualifiers
3567   | |   |-(
3568   | |   |-)
3569   | |   `-const
3570   | `-;
3571   |-SimpleDeclaration
3572   | |-int
3573   | |-SimpleDeclarator
3574   | | |-c
3575   | | `-ParametersAndQualifiers
3576   | |   |-(
3577   | |   |-)
3578   | |   `-volatile
3579   | `-;
3580   |-SimpleDeclaration
3581   | |-int
3582   | |-SimpleDeclarator
3583   | | |-d
3584   | | `-ParametersAndQualifiers
3585   | |   |-(
3586   | |   |-)
3587   | |   |-const
3588   | |   `-volatile
3589   | `-;
3590   |-SimpleDeclaration
3591   | |-int
3592   | |-SimpleDeclarator
3593   | | |-e
3594   | | `-ParametersAndQualifiers
3595   | |   |-(
3596   | |   |-)
3597   | |   `-&
3598   | `-;
3599   |-SimpleDeclaration
3600   | |-int
3601   | |-SimpleDeclarator
3602   | | |-f
3603   | | `-ParametersAndQualifiers
3604   | |   |-(
3605   | |   |-)
3606   | |   `-&&
3607   | `-;
3608   |-}
3609   `-;
3610 )txt"));
3611 }
3612 
3613 TEST_P(SyntaxTreeTest, TrailingReturn) {
3614   if (!GetParam().isCXX11OrLater()) {
3615     return;
3616   }
3617   EXPECT_TRUE(treeDumpEqual(
3618       R"cpp(
3619 auto foo() -> int;
3620 )cpp",
3621       R"txt(
3622 *: TranslationUnit
3623 `-SimpleDeclaration
3624   |-auto
3625   |-SimpleDeclarator
3626   | |-foo
3627   | `-ParametersAndQualifiers
3628   |   |-(
3629   |   |-)
3630   |   `-TrailingReturnType
3631   |     |-->
3632   |     `-int
3633   `-;
3634 )txt"));
3635 }
3636 
3637 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
3638   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
3639     return;
3640   }
3641   EXPECT_TRUE(treeDumpEqual(
3642       R"cpp(
3643 struct MyException1 {};
3644 struct MyException2 {};
3645 int a() throw();
3646 int b() throw(...);
3647 int c() throw(MyException1);
3648 int d() throw(MyException1, MyException2);
3649 )cpp",
3650       R"txt(
3651 *: TranslationUnit
3652 |-SimpleDeclaration
3653 | |-struct
3654 | |-MyException1
3655 | |-{
3656 | |-}
3657 | `-;
3658 |-SimpleDeclaration
3659 | |-struct
3660 | |-MyException2
3661 | |-{
3662 | |-}
3663 | `-;
3664 |-SimpleDeclaration
3665 | |-int
3666 | |-SimpleDeclarator
3667 | | |-a
3668 | | `-ParametersAndQualifiers
3669 | |   |-(
3670 | |   |-)
3671 | |   |-throw
3672 | |   |-(
3673 | |   `-)
3674 | `-;
3675 |-SimpleDeclaration
3676 | |-int
3677 | |-SimpleDeclarator
3678 | | |-b
3679 | | `-ParametersAndQualifiers
3680 | |   |-(
3681 | |   |-)
3682 | |   |-throw
3683 | |   |-(
3684 | |   |-...
3685 | |   `-)
3686 | `-;
3687 |-SimpleDeclaration
3688 | |-int
3689 | |-SimpleDeclarator
3690 | | |-c
3691 | | `-ParametersAndQualifiers
3692 | |   |-(
3693 | |   |-)
3694 | |   |-throw
3695 | |   |-(
3696 | |   |-MyException1
3697 | |   `-)
3698 | `-;
3699 `-SimpleDeclaration
3700   |-int
3701   |-SimpleDeclarator
3702   | |-d
3703   | `-ParametersAndQualifiers
3704   |   |-(
3705   |   |-)
3706   |   |-throw
3707   |   |-(
3708   |   |-MyException1
3709   |   |-,
3710   |   |-MyException2
3711   |   `-)
3712   `-;
3713 )txt"));
3714 }
3715 
3716 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
3717   if (!GetParam().isCXX11OrLater()) {
3718     return;
3719   }
3720   EXPECT_TRUE(treeDumpEqual(
3721       R"cpp(
3722 int a() noexcept;
3723 int b() noexcept(true);
3724 )cpp",
3725       R"txt(
3726 *: TranslationUnit
3727 |-SimpleDeclaration
3728 | |-int
3729 | |-SimpleDeclarator
3730 | | |-a
3731 | | `-ParametersAndQualifiers
3732 | |   |-(
3733 | |   |-)
3734 | |   `-noexcept
3735 | `-;
3736 `-SimpleDeclaration
3737   |-int
3738   |-SimpleDeclarator
3739   | |-b
3740   | `-ParametersAndQualifiers
3741   |   |-(
3742   |   |-)
3743   |   |-noexcept
3744   |   |-(
3745   |   |-BoolLiteralExpression
3746   |   | `-true
3747   |   `-)
3748   `-;
3749 )txt"));
3750 }
3751 
3752 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
3753   EXPECT_TRUE(treeDumpEqual(
3754       R"cpp(
3755 int (a);
3756 int *(b);
3757 int (*c)(int);
3758 int *(d)(int);
3759 )cpp",
3760       R"txt(
3761 *: TranslationUnit
3762 |-SimpleDeclaration
3763 | |-int
3764 | |-SimpleDeclarator
3765 | | `-ParenDeclarator
3766 | |   |-(
3767 | |   |-a
3768 | |   `-)
3769 | `-;
3770 |-SimpleDeclaration
3771 | |-int
3772 | |-SimpleDeclarator
3773 | | |-*
3774 | | `-ParenDeclarator
3775 | |   |-(
3776 | |   |-b
3777 | |   `-)
3778 | `-;
3779 |-SimpleDeclaration
3780 | |-int
3781 | |-SimpleDeclarator
3782 | | |-ParenDeclarator
3783 | | | |-(
3784 | | | |-*
3785 | | | |-c
3786 | | | `-)
3787 | | `-ParametersAndQualifiers
3788 | |   |-(
3789 | |   |-SimpleDeclaration
3790 | |   | `-int
3791 | |   `-)
3792 | `-;
3793 `-SimpleDeclaration
3794   |-int
3795   |-SimpleDeclarator
3796   | |-*
3797   | |-ParenDeclarator
3798   | | |-(
3799   | | |-d
3800   | | `-)
3801   | `-ParametersAndQualifiers
3802   |   |-(
3803   |   |-SimpleDeclaration
3804   |   | `-int
3805   |   `-)
3806   `-;
3807 )txt"));
3808 }
3809 
3810 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
3811   EXPECT_TRUE(treeDumpEqual(
3812       R"cpp(
3813 const int west = -1;
3814 int const east = 1;
3815 const int const universal = 0;
3816 const int const *const *volatile b;
3817 )cpp",
3818       R"txt(
3819 *: TranslationUnit
3820 |-SimpleDeclaration
3821 | |-const
3822 | |-int
3823 | |-SimpleDeclarator
3824 | | |-west
3825 | | |-=
3826 | | `-PrefixUnaryOperatorExpression
3827 | |   |--
3828 | |   `-IntegerLiteralExpression
3829 | |     `-1
3830 | `-;
3831 |-SimpleDeclaration
3832 | |-int
3833 | |-const
3834 | |-SimpleDeclarator
3835 | | |-east
3836 | | |-=
3837 | | `-IntegerLiteralExpression
3838 | |   `-1
3839 | `-;
3840 |-SimpleDeclaration
3841 | |-const
3842 | |-int
3843 | |-const
3844 | |-SimpleDeclarator
3845 | | |-universal
3846 | | |-=
3847 | | `-IntegerLiteralExpression
3848 | |   `-0
3849 | `-;
3850 `-SimpleDeclaration
3851   |-const
3852   |-int
3853   |-const
3854   |-SimpleDeclarator
3855   | |-*
3856   | |-const
3857   | |-*
3858   | |-volatile
3859   | `-b
3860   `-;
3861 )txt"));
3862 }
3863 
3864 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
3865   if (!GetParam().isCXX11OrLater()) {
3866     return;
3867   }
3868   EXPECT_TRUE(treeDumpEqual(
3869       R"cpp(
3870 auto foo() -> auto(*)(int) -> double*;
3871 )cpp",
3872       R"txt(
3873 *: TranslationUnit
3874 `-SimpleDeclaration
3875   |-auto
3876   |-SimpleDeclarator
3877   | |-foo
3878   | `-ParametersAndQualifiers
3879   |   |-(
3880   |   |-)
3881   |   `-TrailingReturnType
3882   |     |-->
3883   |     |-auto
3884   |     `-SimpleDeclarator
3885   |       |-ParenDeclarator
3886   |       | |-(
3887   |       | |-*
3888   |       | `-)
3889   |       `-ParametersAndQualifiers
3890   |         |-(
3891   |         |-SimpleDeclaration
3892   |         | `-int
3893   |         |-)
3894   |         `-TrailingReturnType
3895   |           |-->
3896   |           |-double
3897   |           `-SimpleDeclarator
3898   |             `-*
3899   `-;
3900 )txt"));
3901 }
3902 
3903 TEST_P(SyntaxTreeTest, MemberPointers) {
3904   if (!GetParam().isCXX()) {
3905     return;
3906   }
3907   EXPECT_TRUE(treeDumpEqual(
3908       R"cpp(
3909 struct X {};
3910 int X::* a;
3911 const int X::* b;
3912 )cpp",
3913       R"txt(
3914 *: TranslationUnit
3915 |-SimpleDeclaration
3916 | |-struct
3917 | |-X
3918 | |-{
3919 | |-}
3920 | `-;
3921 |-SimpleDeclaration
3922 | |-int
3923 | |-SimpleDeclarator
3924 | | |-MemberPointer
3925 | | | |-X
3926 | | | |-::
3927 | | | `-*
3928 | | `-a
3929 | `-;
3930 `-SimpleDeclaration
3931   |-const
3932   |-int
3933   |-SimpleDeclarator
3934   | |-MemberPointer
3935   | | |-X
3936   | | |-::
3937   | | `-*
3938   | `-b
3939   `-;
3940 )txt"));
3941 }
3942 
3943 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
3944   EXPECT_TRUE(treeDumpEqual(
3945       R"cpp(
3946 void x(char a, short (*b)(int));
3947 )cpp",
3948       R"txt(
3949 *: TranslationUnit
3950 `-SimpleDeclaration
3951   |-void
3952   |-SimpleDeclarator
3953   | |-x
3954   | `-ParametersAndQualifiers
3955   |   |-(
3956   |   |-SimpleDeclaration
3957   |   | |-char
3958   |   | `-SimpleDeclarator
3959   |   |   `-a
3960   |   |-,
3961   |   |-SimpleDeclaration
3962   |   | |-short
3963   |   | `-SimpleDeclarator
3964   |   |   |-ParenDeclarator
3965   |   |   | |-(
3966   |   |   | |-*
3967   |   |   | |-b
3968   |   |   | `-)
3969   |   |   `-ParametersAndQualifiers
3970   |   |     |-(
3971   |   |     |-SimpleDeclaration
3972   |   |     | `-int
3973   |   |     `-)
3974   |   `-)
3975   `-;
3976 )txt"));
3977 }
3978 
3979 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
3980   EXPECT_TRUE(treeDumpEqual(
3981       R"cpp(
3982 void x(char a, short (*b)(int), long (**c)(long long));
3983 )cpp",
3984       R"txt(
3985 *: TranslationUnit
3986 `-SimpleDeclaration
3987   |-void
3988   |-SimpleDeclarator
3989   | |-x
3990   | `-ParametersAndQualifiers
3991   |   |-(
3992   |   |-SimpleDeclaration
3993   |   | |-char
3994   |   | `-SimpleDeclarator
3995   |   |   `-a
3996   |   |-,
3997   |   |-SimpleDeclaration
3998   |   | |-short
3999   |   | `-SimpleDeclarator
4000   |   |   |-ParenDeclarator
4001   |   |   | |-(
4002   |   |   | |-*
4003   |   |   | |-b
4004   |   |   | `-)
4005   |   |   `-ParametersAndQualifiers
4006   |   |     |-(
4007   |   |     |-SimpleDeclaration
4008   |   |     | `-int
4009   |   |     `-)
4010   |   |-,
4011   |   |-SimpleDeclaration
4012   |   | |-long
4013   |   | `-SimpleDeclarator
4014   |   |   |-ParenDeclarator
4015   |   |   | |-(
4016   |   |   | |-*
4017   |   |   | |-*
4018   |   |   | |-c
4019   |   |   | `-)
4020   |   |   `-ParametersAndQualifiers
4021   |   |     |-(
4022   |   |     |-SimpleDeclaration
4023   |   |     | |-long
4024   |   |     | `-long
4025   |   |     `-)
4026   |   `-)
4027   `-;
4028 )txt"));
4029 }
4030 
4031 TEST_P(SyntaxTreeTest, Mutations) {
4032   if (!GetParam().isCXX11OrLater()) {
4033     return;
4034   }
4035 
4036   using Transformation = std::function<void(
4037       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
4038   auto CheckTransformation = [this](std::string Input, std::string Expected,
4039                                     Transformation Transform) -> void {
4040     llvm::Annotations Source(Input);
4041     auto *Root = buildTree(Source.code(), GetParam());
4042 
4043     Transform(Source, Root);
4044 
4045     auto Replacements = syntax::computeReplacements(*Arena, *Root);
4046     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
4047     if (!Output) {
4048       ADD_FAILURE() << "could not apply replacements: "
4049                     << llvm::toString(Output.takeError());
4050       return;
4051     }
4052 
4053     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
4054   };
4055 
4056   // Removes the selected statement. Input should have exactly one selected
4057   // range and it should correspond to a single statement.
4058   auto RemoveStatement = [this](const llvm::Annotations &Input,
4059                                 syntax::TranslationUnit *TU) {
4060     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
4061     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
4062     syntax::removeStatement(*Arena, S);
4063     EXPECT_TRUE(S->isDetached());
4064     EXPECT_FALSE(S->isOriginal())
4065         << "node removed from tree cannot be marked as original";
4066   };
4067 
4068   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
4069       Cases = {
4070           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
4071           {"void test() { if (true) [[{}]] else {} }",
4072            "void test() { if (true) ; else {} }"},
4073           {"void test() { [[;]] }", "void test() {  }"}};
4074   for (const auto &C : Cases)
4075     CheckTransformation(C.first, C.second, RemoveStatement);
4076 }
4077 
4078 TEST_P(SyntaxTreeTest, SynthesizedNodes) {
4079   buildTree("", GetParam());
4080 
4081   auto *C = syntax::createPunctuation(*Arena, tok::comma);
4082   ASSERT_NE(C, nullptr);
4083   EXPECT_EQ(C->token()->kind(), tok::comma);
4084   EXPECT_TRUE(C->canModify());
4085   EXPECT_FALSE(C->isOriginal());
4086   EXPECT_TRUE(C->isDetached());
4087 
4088   auto *S = syntax::createEmptyStatement(*Arena);
4089   ASSERT_NE(S, nullptr);
4090   EXPECT_TRUE(S->canModify());
4091   EXPECT_FALSE(S->isOriginal());
4092   EXPECT_TRUE(S->isDetached());
4093 }
4094 
4095 static std::vector<TestClangConfig> allTestClangConfigs() {
4096   std::vector<TestClangConfig> all_configs;
4097   for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11,
4098                             Lang_CXX14, Lang_CXX17, Lang_CXX20}) {
4099     TestClangConfig config;
4100     config.Language = lang;
4101     config.Target = "x86_64-pc-linux-gnu";
4102     all_configs.push_back(config);
4103 
4104     // Windows target is interesting to test because it enables
4105     // `-fdelayed-template-parsing`.
4106     config.Target = "x86_64-pc-win32-msvc";
4107     all_configs.push_back(config);
4108   }
4109   return all_configs;
4110 }
4111 
4112 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
4113                         testing::ValuesIn(allTestClangConfigs()), );
4114 
4115 } // namespace
4116