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