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/Tooling/Core/Replacement.h"
22 #include "clang/Tooling/Syntax/BuildTree.h"
23 #include "clang/Tooling/Syntax/Mutations.h"
24 #include "clang/Tooling/Syntax/Nodes.h"
25 #include "clang/Tooling/Syntax/Tokens.h"
26 #include "clang/Tooling/Tooling.h"
27 #include "llvm/ADT/ArrayRef.h"
28 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/ADT/StringRef.h"
31 #include "llvm/Support/Casting.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Testing/Support/Annotations.h"
34 #include "gmock/gmock.h"
35 #include "gtest/gtest.h"
36 #include <cstdlib>
37 
38 using namespace clang;
39 
40 namespace {
41 static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) {
42   assert(N->isOriginal() && "tokens of modified nodes are not well-defined");
43   if (auto *L = dyn_cast<syntax::Leaf>(N))
44     return llvm::makeArrayRef(L->token(), 1);
45   auto *T = cast<syntax::Tree>(N);
46   return llvm::makeArrayRef(T->firstLeaf()->token(),
47                             T->lastLeaf()->token() + 1);
48 }
49 
50 struct TestClangConfig {
51   TestLanguage Language;
52   std::string Target;
53 
54   bool isC99OrLater() const { return Language == Lang_C99; }
55 
56   bool isCXX() const {
57     return Language == Lang_CXX03 || Language == Lang_CXX11 ||
58            Language == Lang_CXX14 || Language == Lang_CXX17 ||
59            Language == Lang_CXX20;
60   }
61 
62   bool isCXX11OrLater() const {
63     return Language == Lang_CXX11 || Language == Lang_CXX14 ||
64            Language == Lang_CXX17 || Language == Lang_CXX20;
65   }
66 
67   bool isCXX14OrLater() const {
68     return Language == Lang_CXX14 || Language == Lang_CXX17 ||
69            Language == Lang_CXX20;
70   }
71 
72   bool supportsCXXDynamicExceptionSpecification() const {
73     return Language == Lang_CXX03 || Language == Lang_CXX11 ||
74            Language == Lang_CXX14;
75   }
76 
77   bool hasDelayedTemplateParsing() const {
78     return Target == "x86_64-pc-win32-msvc";
79   }
80 
81   std::vector<std::string> getCommandLineArgs() const {
82     std::vector<std::string> Result = getCommandLineArgsForTesting(Language);
83     Result.push_back("-target");
84     Result.push_back(Target);
85     return Result;
86   }
87 
88   std::string toString() const {
89     std::string Result;
90     llvm::raw_string_ostream OS(Result);
91     OS << "{ Language=" << Language << ", Target=" << Target << " }";
92     return OS.str();
93   }
94 
95   friend std::ostream &operator<<(std::ostream &OS,
96                                   const TestClangConfig &ClangConfig) {
97     return OS << ClangConfig.toString();
98   }
99 
100   static std::vector<TestClangConfig> &allConfigs() {
101     static std::vector<TestClangConfig> all_configs = []() {
102       std::vector<TestClangConfig> all_configs;
103       for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11,
104                                 Lang_CXX14, Lang_CXX17, Lang_CXX20}) {
105         TestClangConfig config;
106         config.Language = lang;
107         config.Target = "x86_64-pc-linux-gnu";
108         all_configs.push_back(config);
109 
110         // Windows target is interesting to test because it enables
111         // `-fdelayed-template-parsing`.
112         config.Target = "x86_64-pc-win32-msvc";
113         all_configs.push_back(config);
114       }
115       return all_configs;
116     }();
117     return all_configs;
118   }
119 };
120 
121 class SyntaxTreeTest : public ::testing::Test,
122                        public ::testing::WithParamInterface<TestClangConfig> {
123 protected:
124   // Build a syntax tree for the code.
125   syntax::TranslationUnit *buildTree(llvm::StringRef Code,
126                                      const TestClangConfig &ClangConfig) {
127     // FIXME: this code is almost the identical to the one in TokensTest. Share
128     //        it.
129     class BuildSyntaxTree : public ASTConsumer {
130     public:
131       BuildSyntaxTree(syntax::TranslationUnit *&Root,
132                       std::unique_ptr<syntax::Arena> &Arena,
133                       std::unique_ptr<syntax::TokenCollector> Tokens)
134           : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) {
135         assert(this->Tokens);
136       }
137 
138       void HandleTranslationUnit(ASTContext &Ctx) override {
139         Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
140                                                 Ctx.getLangOpts(),
141                                                 std::move(*Tokens).consume());
142         Tokens = nullptr; // make sure we fail if this gets called twice.
143         Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl());
144       }
145 
146     private:
147       syntax::TranslationUnit *&Root;
148       std::unique_ptr<syntax::Arena> &Arena;
149       std::unique_ptr<syntax::TokenCollector> Tokens;
150     };
151 
152     class BuildSyntaxTreeAction : public ASTFrontendAction {
153     public:
154       BuildSyntaxTreeAction(syntax::TranslationUnit *&Root,
155                             std::unique_ptr<syntax::Arena> &Arena)
156           : Root(Root), Arena(Arena) {}
157 
158       std::unique_ptr<ASTConsumer>
159       CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
160         // We start recording the tokens, ast consumer will take on the result.
161         auto Tokens =
162             std::make_unique<syntax::TokenCollector>(CI.getPreprocessor());
163         return std::make_unique<BuildSyntaxTree>(Root, Arena,
164                                                  std::move(Tokens));
165       }
166 
167     private:
168       syntax::TranslationUnit *&Root;
169       std::unique_ptr<syntax::Arena> &Arena;
170     };
171 
172     constexpr const char *FileName = "./input.cpp";
173     FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy(""));
174 
175     if (!Diags->getClient())
176       Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagOpts.get()));
177     Diags->setSeverityForGroup(diag::Flavor::WarningOrError, "unused-value",
178                                diag::Severity::Ignored, SourceLocation());
179 
180     // Prepare to run a compiler.
181     std::vector<std::string> Args = {
182         "syntax-test",
183         "-fsyntax-only",
184     };
185     llvm::copy(ClangConfig.getCommandLineArgs(), std::back_inserter(Args));
186     Args.push_back(FileName);
187 
188     std::vector<const char *> ArgsCStr;
189     for (const std::string &arg : Args) {
190       ArgsCStr.push_back(arg.c_str());
191     }
192 
193     Invocation = createInvocationFromCommandLine(ArgsCStr, Diags, FS);
194     assert(Invocation);
195     Invocation->getFrontendOpts().DisableFree = false;
196     Invocation->getPreprocessorOpts().addRemappedFile(
197         FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release());
198     CompilerInstance Compiler;
199     Compiler.setInvocation(Invocation);
200     Compiler.setDiagnostics(Diags.get());
201     Compiler.setFileManager(FileMgr.get());
202     Compiler.setSourceManager(SourceMgr.get());
203 
204     syntax::TranslationUnit *Root = nullptr;
205     BuildSyntaxTreeAction Recorder(Root, this->Arena);
206 
207     // Action could not be executed but the frontend didn't identify any errors
208     // in the code ==> problem in setting up the action.
209     if (!Compiler.ExecuteAction(Recorder) &&
210         Diags->getClient()->getNumErrors() == 0) {
211       ADD_FAILURE() << "failed to run the frontend";
212       std::abort();
213     }
214     return Root;
215   }
216 
217   ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
218     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
219 
220     auto *Root = buildTree(Code, GetParam());
221     if (Diags->getClient()->getNumErrors() != 0) {
222       return ::testing::AssertionFailure()
223              << "Source file has syntax errors, they were printed to the test "
224                 "log";
225     }
226     std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim());
227     // EXPECT_EQ shows the diff between the two strings if they are different.
228     EXPECT_EQ(Tree.trim().str(), Actual);
229     if (Actual != Tree.trim().str()) {
230       return ::testing::AssertionFailure();
231     }
232     return ::testing::AssertionSuccess();
233   }
234 
235   // Adds a file to the test VFS.
236   void addFile(llvm::StringRef Path, llvm::StringRef Contents) {
237     if (!FS->addFile(Path, time_t(),
238                      llvm::MemoryBuffer::getMemBufferCopy(Contents))) {
239       ADD_FAILURE() << "could not add a file to VFS: " << Path;
240     }
241   }
242 
243   /// Finds the deepest node in the tree that covers exactly \p R.
244   /// FIXME: implement this efficiently and move to public syntax tree API.
245   syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) {
246     llvm::ArrayRef<syntax::Token> Toks = tokens(Root);
247 
248     if (Toks.front().location().isFileID() &&
249         Toks.back().location().isFileID() &&
250         syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) ==
251             syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End))
252       return Root;
253 
254     auto *T = dyn_cast<syntax::Tree>(Root);
255     if (!T)
256       return nullptr;
257     for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) {
258       if (auto *Result = nodeByRange(R, C))
259         return Result;
260     }
261     return nullptr;
262   }
263 
264   // Data fields.
265   llvm::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
266       new DiagnosticOptions();
267   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
268       new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get());
269   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
270       new llvm::vfs::InMemoryFileSystem;
271   llvm::IntrusiveRefCntPtr<FileManager> FileMgr =
272       new FileManager(FileSystemOptions(), FS);
273   llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr =
274       new SourceManager(*Diags, *FileMgr);
275   std::shared_ptr<CompilerInvocation> Invocation;
276   // Set after calling buildTree().
277   std::unique_ptr<syntax::Arena> Arena;
278 };
279 
280 TEST_P(SyntaxTreeTest, Simple) {
281   EXPECT_TRUE(treeDumpEqual(
282       R"cpp(
283 int main() {}
284 void foo() {}
285 )cpp",
286       R"txt(
287 *: TranslationUnit
288 |-SimpleDeclaration
289 | |-int
290 | |-SimpleDeclarator
291 | | |-main
292 | | `-ParametersAndQualifiers
293 | |   |-(
294 | |   `-)
295 | `-CompoundStatement
296 |   |-{
297 |   `-}
298 `-SimpleDeclaration
299   |-void
300   |-SimpleDeclarator
301   | |-foo
302   | `-ParametersAndQualifiers
303   |   |-(
304   |   `-)
305   `-CompoundStatement
306     |-{
307     `-}
308 )txt"));
309 }
310 
311 TEST_P(SyntaxTreeTest, SimpleVariable) {
312   EXPECT_TRUE(treeDumpEqual(
313       R"cpp(
314 int a;
315 int b = 42;
316 )cpp",
317       R"txt(
318 *: TranslationUnit
319 |-SimpleDeclaration
320 | |-int
321 | |-SimpleDeclarator
322 | | `-a
323 | `-;
324 `-SimpleDeclaration
325   |-int
326   |-SimpleDeclarator
327   | |-b
328   | |-=
329   | `-IntegerLiteralExpression
330   |   `-42
331   `-;
332 )txt"));
333 }
334 
335 TEST_P(SyntaxTreeTest, SimpleFunction) {
336   EXPECT_TRUE(treeDumpEqual(
337       R"cpp(
338 void foo(int a, int b) {}
339 )cpp",
340       R"txt(
341 *: TranslationUnit
342 `-SimpleDeclaration
343   |-void
344   |-SimpleDeclarator
345   | |-foo
346   | `-ParametersAndQualifiers
347   |   |-(
348   |   |-SimpleDeclaration
349   |   | |-int
350   |   | `-SimpleDeclarator
351   |   |   `-a
352   |   |-,
353   |   |-SimpleDeclaration
354   |   | |-int
355   |   | `-SimpleDeclarator
356   |   |   `-b
357   |   `-)
358   `-CompoundStatement
359     |-{
360     `-}
361 )txt"));
362 }
363 
364 TEST_P(SyntaxTreeTest, If) {
365   EXPECT_TRUE(treeDumpEqual(
366       R"cpp(
367 int main() {
368   if (1) {}
369   if (1) {} else if (0) {}
370 }
371 )cpp",
372       R"txt(
373 *: TranslationUnit
374 `-SimpleDeclaration
375   |-int
376   |-SimpleDeclarator
377   | |-main
378   | `-ParametersAndQualifiers
379   |   |-(
380   |   `-)
381   `-CompoundStatement
382     |-{
383     |-IfStatement
384     | |-if
385     | |-(
386     | |-IntegerLiteralExpression
387     | | `-1
388     | |-)
389     | `-CompoundStatement
390     |   |-{
391     |   `-}
392     |-IfStatement
393     | |-if
394     | |-(
395     | |-IntegerLiteralExpression
396     | | `-1
397     | |-)
398     | |-CompoundStatement
399     | | |-{
400     | | `-}
401     | |-else
402     | `-IfStatement
403     |   |-if
404     |   |-(
405     |   |-IntegerLiteralExpression
406     |   | `-0
407     |   |-)
408     |   `-CompoundStatement
409     |     |-{
410     |     `-}
411     `-}
412 )txt"));
413 }
414 
415 TEST_P(SyntaxTreeTest, For) {
416   EXPECT_TRUE(treeDumpEqual(
417       R"cpp(
418 void test() {
419   for (;;)  {}
420 }
421 )cpp",
422       R"txt(
423 *: TranslationUnit
424 `-SimpleDeclaration
425   |-void
426   |-SimpleDeclarator
427   | |-test
428   | `-ParametersAndQualifiers
429   |   |-(
430   |   `-)
431   `-CompoundStatement
432     |-{
433     |-ForStatement
434     | |-for
435     | |-(
436     | |-;
437     | |-;
438     | |-)
439     | `-CompoundStatement
440     |   |-{
441     |   `-}
442     `-}
443 )txt"));
444 }
445 
446 TEST_P(SyntaxTreeTest, RangeBasedFor) {
447   if (!GetParam().isCXX11OrLater()) {
448     return;
449   }
450   EXPECT_TRUE(treeDumpEqual(
451       R"cpp(
452 void test() {
453   int a[3];
454   for (int x : a)
455     ;
456 }
457 )cpp",
458       R"txt(
459 *: TranslationUnit
460 `-SimpleDeclaration
461   |-void
462   |-SimpleDeclarator
463   | |-test
464   | `-ParametersAndQualifiers
465   |   |-(
466   |   `-)
467   `-CompoundStatement
468     |-{
469     |-DeclarationStatement
470     | |-SimpleDeclaration
471     | | |-int
472     | | `-SimpleDeclarator
473     | |   |-a
474     | |   `-ArraySubscript
475     | |     |-[
476     | |     |-IntegerLiteralExpression
477     | |     | `-3
478     | |     `-]
479     | `-;
480     |-RangeBasedForStatement
481     | |-for
482     | |-(
483     | |-SimpleDeclaration
484     | | |-int
485     | | |-SimpleDeclarator
486     | | | `-x
487     | | `-:
488     | |-UnknownExpression
489     | | `-a
490     | |-)
491     | `-EmptyStatement
492     |   `-;
493     `-}
494 )txt"));
495 }
496 
497 TEST_P(SyntaxTreeTest, DeclarationStatement) {
498   EXPECT_TRUE(treeDumpEqual(
499       R"cpp(
500 void test() {
501   int a = 10;
502 }
503 )cpp",
504       R"txt(
505 *: TranslationUnit
506 `-SimpleDeclaration
507   |-void
508   |-SimpleDeclarator
509   | |-test
510   | `-ParametersAndQualifiers
511   |   |-(
512   |   `-)
513   `-CompoundStatement
514     |-{
515     |-DeclarationStatement
516     | |-SimpleDeclaration
517     | | |-int
518     | | `-SimpleDeclarator
519     | |   |-a
520     | |   |-=
521     | |   `-IntegerLiteralExpression
522     | |     `-10
523     | `-;
524     `-}
525 )txt"));
526 }
527 
528 TEST_P(SyntaxTreeTest, Switch) {
529   EXPECT_TRUE(treeDumpEqual(
530       R"cpp(
531 void test() {
532   switch (1) {
533     case 0:
534     default:;
535   }
536 }
537 )cpp",
538       R"txt(
539 *: TranslationUnit
540 `-SimpleDeclaration
541   |-void
542   |-SimpleDeclarator
543   | |-test
544   | `-ParametersAndQualifiers
545   |   |-(
546   |   `-)
547   `-CompoundStatement
548     |-{
549     |-SwitchStatement
550     | |-switch
551     | |-(
552     | |-IntegerLiteralExpression
553     | | `-1
554     | |-)
555     | `-CompoundStatement
556     |   |-{
557     |   |-CaseStatement
558     |   | |-case
559     |   | |-IntegerLiteralExpression
560     |   | | `-0
561     |   | |-:
562     |   | `-DefaultStatement
563     |   |   |-default
564     |   |   |-:
565     |   |   `-EmptyStatement
566     |   |     `-;
567     |   `-}
568     `-}
569 )txt"));
570 }
571 
572 TEST_P(SyntaxTreeTest, While) {
573   EXPECT_TRUE(treeDumpEqual(
574       R"cpp(
575 void test() {
576   while (1) { continue; break; }
577 }
578 )cpp",
579       R"txt(
580 *: TranslationUnit
581 `-SimpleDeclaration
582   |-void
583   |-SimpleDeclarator
584   | |-test
585   | `-ParametersAndQualifiers
586   |   |-(
587   |   `-)
588   `-CompoundStatement
589     |-{
590     |-WhileStatement
591     | |-while
592     | |-(
593     | |-IntegerLiteralExpression
594     | | `-1
595     | |-)
596     | `-CompoundStatement
597     |   |-{
598     |   |-ContinueStatement
599     |   | |-continue
600     |   | `-;
601     |   |-BreakStatement
602     |   | |-break
603     |   | `-;
604     |   `-}
605     `-}
606 )txt"));
607 }
608 
609 TEST_P(SyntaxTreeTest, UnhandledStatement) {
610   // Unhandled statements should end up as 'unknown statement'.
611   // This example uses a 'label statement', which does not yet have a syntax
612   // counterpart.
613   EXPECT_TRUE(treeDumpEqual(
614       R"cpp(
615 int main() {
616   foo: return 100;
617 }
618 )cpp",
619       R"txt(
620 *: TranslationUnit
621 `-SimpleDeclaration
622   |-int
623   |-SimpleDeclarator
624   | |-main
625   | `-ParametersAndQualifiers
626   |   |-(
627   |   `-)
628   `-CompoundStatement
629     |-{
630     |-UnknownStatement
631     | |-foo
632     | |-:
633     | `-ReturnStatement
634     |   |-return
635     |   |-IntegerLiteralExpression
636     |   | `-100
637     |   `-;
638     `-}
639 )txt"));
640 }
641 
642 TEST_P(SyntaxTreeTest, Expressions) {
643   // expressions should be wrapped in 'ExpressionStatement' when they appear
644   // in a statement position.
645   EXPECT_TRUE(treeDumpEqual(
646       R"cpp(
647 void test() {
648   test();
649   if (1) test(); else test();
650 }
651 )cpp",
652       R"txt(
653 *: TranslationUnit
654 `-SimpleDeclaration
655   |-void
656   |-SimpleDeclarator
657   | |-test
658   | `-ParametersAndQualifiers
659   |   |-(
660   |   `-)
661   `-CompoundStatement
662     |-{
663     |-ExpressionStatement
664     | |-UnknownExpression
665     | | |-UnknownExpression
666     | | | `-test
667     | | |-(
668     | | `-)
669     | `-;
670     |-IfStatement
671     | |-if
672     | |-(
673     | |-IntegerLiteralExpression
674     | | `-1
675     | |-)
676     | |-ExpressionStatement
677     | | |-UnknownExpression
678     | | | |-UnknownExpression
679     | | | | `-test
680     | | | |-(
681     | | | `-)
682     | | `-;
683     | |-else
684     | `-ExpressionStatement
685     |   |-UnknownExpression
686     |   | |-UnknownExpression
687     |   | | `-test
688     |   | |-(
689     |   | `-)
690     |   `-;
691     `-}
692 )txt"));
693 }
694 
695 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) {
696   if (!GetParam().isCXX11OrLater()) {
697     return;
698   }
699   EXPECT_TRUE(treeDumpEqual(
700       R"cpp(
701 void test() {
702   nullptr;
703 }
704 )cpp",
705       R"txt(
706 *: TranslationUnit
707 `-SimpleDeclaration
708   |-void
709   |-SimpleDeclarator
710   | |-test
711   | `-ParametersAndQualifiers
712   |   |-(
713   |   `-)
714   `-CompoundStatement
715     |-{
716     |-ExpressionStatement
717     | |-CxxNullPtrExpression
718     | | `-nullptr
719     | `-;
720     `-}
721 )txt"));
722 }
723 
724 TEST_P(SyntaxTreeTest, IntegerLiteral) {
725   EXPECT_TRUE(treeDumpEqual(
726       R"cpp(
727 void test() {
728   12;
729   12u;
730   12l;
731   12ul;
732   014;
733   0XC;
734 }
735 )cpp",
736       R"txt(
737 *: TranslationUnit
738 `-SimpleDeclaration
739   |-void
740   |-SimpleDeclarator
741   | |-test
742   | `-ParametersAndQualifiers
743   |   |-(
744   |   `-)
745   `-CompoundStatement
746     |-{
747     |-ExpressionStatement
748     | |-IntegerLiteralExpression
749     | | `-12
750     | `-;
751     |-ExpressionStatement
752     | |-IntegerLiteralExpression
753     | | `-12u
754     | `-;
755     |-ExpressionStatement
756     | |-IntegerLiteralExpression
757     | | `-12l
758     | `-;
759     |-ExpressionStatement
760     | |-IntegerLiteralExpression
761     | | `-12ul
762     | `-;
763     |-ExpressionStatement
764     | |-IntegerLiteralExpression
765     | | `-014
766     | `-;
767     |-ExpressionStatement
768     | |-IntegerLiteralExpression
769     | | `-0XC
770     | `-;
771     `-}
772 )txt"));
773 }
774 
775 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) {
776   if (!GetParam().isCXX11OrLater()) {
777     return;
778   }
779   EXPECT_TRUE(treeDumpEqual(
780       R"cpp(
781 void test() {
782   12ll;
783   12ull;
784 }
785 )cpp",
786       R"txt(
787 *: TranslationUnit
788 `-SimpleDeclaration
789   |-void
790   |-SimpleDeclarator
791   | |-test
792   | `-ParametersAndQualifiers
793   |   |-(
794   |   `-)
795   `-CompoundStatement
796     |-{
797     |-ExpressionStatement
798     | |-IntegerLiteralExpression
799     | | `-12ll
800     | `-;
801     |-ExpressionStatement
802     | |-IntegerLiteralExpression
803     | | `-12ull
804     | `-;
805     `-}
806 )txt"));
807 }
808 
809 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) {
810   if (!GetParam().isCXX14OrLater()) {
811     return;
812   }
813   EXPECT_TRUE(treeDumpEqual(
814       R"cpp(
815 void test() {
816   0b1100;
817 }
818 )cpp",
819       R"txt(
820 *: TranslationUnit
821 `-SimpleDeclaration
822   |-void
823   |-SimpleDeclarator
824   | |-test
825   | `-ParametersAndQualifiers
826   |   |-(
827   |   `-)
828   `-CompoundStatement
829     |-{
830     |-ExpressionStatement
831     | |-IntegerLiteralExpression
832     | | `-0b1100
833     | `-;
834     `-}
835 )txt"));
836 }
837 
838 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) {
839   if (!GetParam().isCXX14OrLater()) {
840     return;
841   }
842   EXPECT_TRUE(treeDumpEqual(
843       R"cpp(
844 void test() {
845   1'2'0ull;
846 }
847 )cpp",
848       R"txt(
849 *: TranslationUnit
850 `-SimpleDeclaration
851   |-void
852   |-SimpleDeclarator
853   | |-test
854   | `-ParametersAndQualifiers
855   |   |-(
856   |   `-)
857   `-CompoundStatement
858     |-{
859     |-ExpressionStatement
860     | |-IntegerLiteralExpression
861     | | `-1'2'0ull
862     | `-;
863     `-}
864 )txt"));
865 }
866 
867 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) {
868   EXPECT_TRUE(treeDumpEqual(
869       R"cpp(
870 void test(int a) {
871   a++;
872   a--;
873 }
874 )cpp",
875       R"txt(
876 *: TranslationUnit
877 `-SimpleDeclaration
878   |-void
879   |-SimpleDeclarator
880   | |-test
881   | `-ParametersAndQualifiers
882   |   |-(
883   |   |-SimpleDeclaration
884   |   | |-int
885   |   | `-SimpleDeclarator
886   |   |   `-a
887   |   `-)
888   `-CompoundStatement
889     |-{
890     |-ExpressionStatement
891     | |-PostfixUnaryOperatorExpression
892     | | |-UnknownExpression
893     | | | `-a
894     | | `-++
895     | `-;
896     |-ExpressionStatement
897     | |-PostfixUnaryOperatorExpression
898     | | |-UnknownExpression
899     | | | `-a
900     | | `---
901     | `-;
902     `-}
903 )txt"));
904 }
905 
906 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) {
907   EXPECT_TRUE(treeDumpEqual(
908       R"cpp(
909 void test(int a, int *ap) {
910   --a; ++a;
911   ~a;
912   -a;
913   +a;
914   &a;
915   *ap;
916   !a;
917   __real a; __imag a;
918 }
919 )cpp",
920       R"txt(
921 *: TranslationUnit
922 `-SimpleDeclaration
923   |-void
924   |-SimpleDeclarator
925   | |-test
926   | `-ParametersAndQualifiers
927   |   |-(
928   |   |-SimpleDeclaration
929   |   | |-int
930   |   | `-SimpleDeclarator
931   |   |   `-a
932   |   |-,
933   |   |-SimpleDeclaration
934   |   | |-int
935   |   | `-SimpleDeclarator
936   |   |   |-*
937   |   |   `-ap
938   |   `-)
939   `-CompoundStatement
940     |-{
941     |-ExpressionStatement
942     | |-PrefixUnaryOperatorExpression
943     | | |---
944     | | `-UnknownExpression
945     | |   `-a
946     | `-;
947     |-ExpressionStatement
948     | |-PrefixUnaryOperatorExpression
949     | | |-++
950     | | `-UnknownExpression
951     | |   `-a
952     | `-;
953     |-ExpressionStatement
954     | |-PrefixUnaryOperatorExpression
955     | | |-~
956     | | `-UnknownExpression
957     | |   `-a
958     | `-;
959     |-ExpressionStatement
960     | |-PrefixUnaryOperatorExpression
961     | | |--
962     | | `-UnknownExpression
963     | |   `-a
964     | `-;
965     |-ExpressionStatement
966     | |-PrefixUnaryOperatorExpression
967     | | |-+
968     | | `-UnknownExpression
969     | |   `-a
970     | `-;
971     |-ExpressionStatement
972     | |-PrefixUnaryOperatorExpression
973     | | |-&
974     | | `-UnknownExpression
975     | |   `-a
976     | `-;
977     |-ExpressionStatement
978     | |-PrefixUnaryOperatorExpression
979     | | |-*
980     | | `-UnknownExpression
981     | |   `-ap
982     | `-;
983     |-ExpressionStatement
984     | |-PrefixUnaryOperatorExpression
985     | | |-!
986     | | `-UnknownExpression
987     | |   `-a
988     | `-;
989     |-ExpressionStatement
990     | |-PrefixUnaryOperatorExpression
991     | | |-__real
992     | | `-UnknownExpression
993     | |   `-a
994     | `-;
995     |-ExpressionStatement
996     | |-PrefixUnaryOperatorExpression
997     | | |-__imag
998     | | `-UnknownExpression
999     | |   `-a
1000     | `-;
1001     `-}
1002 )txt"));
1003 }
1004 
1005 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) {
1006   if (!GetParam().isCXX()) {
1007     return;
1008   }
1009   EXPECT_TRUE(treeDumpEqual(
1010       R"cpp(
1011 void test(int a, bool b) {
1012   compl a;
1013   not b;
1014 }
1015 )cpp",
1016       R"txt(
1017 *: TranslationUnit
1018 `-SimpleDeclaration
1019   |-void
1020   |-SimpleDeclarator
1021   | |-test
1022   | `-ParametersAndQualifiers
1023   |   |-(
1024   |   |-SimpleDeclaration
1025   |   | |-int
1026   |   | `-SimpleDeclarator
1027   |   |   `-a
1028   |   |-,
1029   |   |-SimpleDeclaration
1030   |   | |-bool
1031   |   | `-SimpleDeclarator
1032   |   |   `-b
1033   |   `-)
1034   `-CompoundStatement
1035     |-{
1036     |-ExpressionStatement
1037     | |-PrefixUnaryOperatorExpression
1038     | | |-compl
1039     | | `-UnknownExpression
1040     | |   `-a
1041     | `-;
1042     |-ExpressionStatement
1043     | |-PrefixUnaryOperatorExpression
1044     | | |-not
1045     | | `-UnknownExpression
1046     | |   `-b
1047     | `-;
1048     `-}
1049 )txt"));
1050 }
1051 
1052 TEST_P(SyntaxTreeTest, BinaryOperator) {
1053   EXPECT_TRUE(treeDumpEqual(
1054       R"cpp(
1055 void test(int a) {
1056   1 - 2;
1057   1 == 2;
1058   a = 1;
1059   a <<= 1;
1060   1 || 0;
1061   1 & 2;
1062   a ^= 3;
1063 }
1064 )cpp",
1065       R"txt(
1066 *: TranslationUnit
1067 `-SimpleDeclaration
1068   |-void
1069   |-SimpleDeclarator
1070   | |-test
1071   | `-ParametersAndQualifiers
1072   |   |-(
1073   |   |-SimpleDeclaration
1074   |   | |-int
1075   |   | `-SimpleDeclarator
1076   |   |   `-a
1077   |   `-)
1078   `-CompoundStatement
1079     |-{
1080     |-ExpressionStatement
1081     | |-BinaryOperatorExpression
1082     | | |-IntegerLiteralExpression
1083     | | | `-1
1084     | | |--
1085     | | `-IntegerLiteralExpression
1086     | |   `-2
1087     | `-;
1088     |-ExpressionStatement
1089     | |-BinaryOperatorExpression
1090     | | |-IntegerLiteralExpression
1091     | | | `-1
1092     | | |-==
1093     | | `-IntegerLiteralExpression
1094     | |   `-2
1095     | `-;
1096     |-ExpressionStatement
1097     | |-BinaryOperatorExpression
1098     | | |-UnknownExpression
1099     | | | `-a
1100     | | |-=
1101     | | `-IntegerLiteralExpression
1102     | |   `-1
1103     | `-;
1104     |-ExpressionStatement
1105     | |-BinaryOperatorExpression
1106     | | |-UnknownExpression
1107     | | | `-a
1108     | | |-<<=
1109     | | `-IntegerLiteralExpression
1110     | |   `-1
1111     | `-;
1112     |-ExpressionStatement
1113     | |-BinaryOperatorExpression
1114     | | |-IntegerLiteralExpression
1115     | | | `-1
1116     | | |-||
1117     | | `-IntegerLiteralExpression
1118     | |   `-0
1119     | `-;
1120     |-ExpressionStatement
1121     | |-BinaryOperatorExpression
1122     | | |-IntegerLiteralExpression
1123     | | | `-1
1124     | | |-&
1125     | | `-IntegerLiteralExpression
1126     | |   `-2
1127     | `-;
1128     |-ExpressionStatement
1129     | |-BinaryOperatorExpression
1130     | | |-UnknownExpression
1131     | | | `-a
1132     | | |-^=
1133     | | `-IntegerLiteralExpression
1134     | |   `-3
1135     | `-;
1136     `-}
1137 )txt"));
1138 }
1139 
1140 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) {
1141   if (!GetParam().isCXX()) {
1142     return;
1143   }
1144   EXPECT_TRUE(treeDumpEqual(
1145       R"cpp(
1146 void test(int a) {
1147   true || false;
1148   true or false;
1149   1 bitand 2;
1150   a xor_eq 3;
1151 }
1152 )cpp",
1153       R"txt(
1154 *: TranslationUnit
1155 `-SimpleDeclaration
1156   |-void
1157   |-SimpleDeclarator
1158   | |-test
1159   | `-ParametersAndQualifiers
1160   |   |-(
1161   |   |-SimpleDeclaration
1162   |   | |-int
1163   |   | `-SimpleDeclarator
1164   |   |   `-a
1165   |   `-)
1166   `-CompoundStatement
1167     |-{
1168     |-ExpressionStatement
1169     | |-BinaryOperatorExpression
1170     | | |-UnknownExpression
1171     | | | `-true
1172     | | |-||
1173     | | `-UnknownExpression
1174     | |   `-false
1175     | `-;
1176     |-ExpressionStatement
1177     | |-BinaryOperatorExpression
1178     | | |-UnknownExpression
1179     | | | `-true
1180     | | |-or
1181     | | `-UnknownExpression
1182     | |   `-false
1183     | `-;
1184     |-ExpressionStatement
1185     | |-BinaryOperatorExpression
1186     | | |-IntegerLiteralExpression
1187     | | | `-1
1188     | | |-bitand
1189     | | `-IntegerLiteralExpression
1190     | |   `-2
1191     | `-;
1192     |-ExpressionStatement
1193     | |-BinaryOperatorExpression
1194     | | |-UnknownExpression
1195     | | | `-a
1196     | | |-xor_eq
1197     | | `-IntegerLiteralExpression
1198     | |   `-3
1199     | `-;
1200     `-}
1201 )txt"));
1202 }
1203 
1204 TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
1205   EXPECT_TRUE(treeDumpEqual(
1206       R"cpp(
1207 void test(int a, int b) {
1208   (1 + 2) * (4 / 2);
1209   a + b + 42;
1210   a = b = 42;
1211   a + b * 4 + 2;
1212   a % 2 + b * 42;
1213 }
1214 )cpp",
1215       R"txt(
1216 *: TranslationUnit
1217 `-SimpleDeclaration
1218   |-void
1219   |-SimpleDeclarator
1220   | |-test
1221   | `-ParametersAndQualifiers
1222   |   |-(
1223   |   |-SimpleDeclaration
1224   |   | |-int
1225   |   | `-SimpleDeclarator
1226   |   |   `-a
1227   |   |-,
1228   |   |-SimpleDeclaration
1229   |   | |-int
1230   |   | `-SimpleDeclarator
1231   |   |   `-b
1232   |   `-)
1233   `-CompoundStatement
1234     |-{
1235     |-ExpressionStatement
1236     | |-BinaryOperatorExpression
1237     | | |-UnknownExpression
1238     | | | |-(
1239     | | | |-BinaryOperatorExpression
1240     | | | | |-IntegerLiteralExpression
1241     | | | | | `-1
1242     | | | | |-+
1243     | | | | `-IntegerLiteralExpression
1244     | | | |   `-2
1245     | | | `-)
1246     | | |-*
1247     | | `-UnknownExpression
1248     | |   |-(
1249     | |   |-BinaryOperatorExpression
1250     | |   | |-IntegerLiteralExpression
1251     | |   | | `-4
1252     | |   | |-/
1253     | |   | `-IntegerLiteralExpression
1254     | |   |   `-2
1255     | |   `-)
1256     | `-;
1257     |-ExpressionStatement
1258     | |-BinaryOperatorExpression
1259     | | |-BinaryOperatorExpression
1260     | | | |-UnknownExpression
1261     | | | | `-a
1262     | | | |-+
1263     | | | `-UnknownExpression
1264     | | |   `-b
1265     | | |-+
1266     | | `-IntegerLiteralExpression
1267     | |   `-42
1268     | `-;
1269     |-ExpressionStatement
1270     | |-BinaryOperatorExpression
1271     | | |-UnknownExpression
1272     | | | `-a
1273     | | |-=
1274     | | `-BinaryOperatorExpression
1275     | |   |-UnknownExpression
1276     | |   | `-b
1277     | |   |-=
1278     | |   `-IntegerLiteralExpression
1279     | |     `-42
1280     | `-;
1281     |-ExpressionStatement
1282     | |-BinaryOperatorExpression
1283     | | |-BinaryOperatorExpression
1284     | | | |-UnknownExpression
1285     | | | | `-a
1286     | | | |-+
1287     | | | `-BinaryOperatorExpression
1288     | | |   |-UnknownExpression
1289     | | |   | `-b
1290     | | |   |-*
1291     | | |   `-IntegerLiteralExpression
1292     | | |     `-4
1293     | | |-+
1294     | | `-IntegerLiteralExpression
1295     | |   `-2
1296     | `-;
1297     |-ExpressionStatement
1298     | |-BinaryOperatorExpression
1299     | | |-BinaryOperatorExpression
1300     | | | |-UnknownExpression
1301     | | | | `-a
1302     | | | |-%
1303     | | | `-IntegerLiteralExpression
1304     | | |   `-2
1305     | | |-+
1306     | | `-BinaryOperatorExpression
1307     | |   |-UnknownExpression
1308     | |   | `-b
1309     | |   |-*
1310     | |   `-IntegerLiteralExpression
1311     | |     `-42
1312     | `-;
1313     `-}
1314 )txt"));
1315 }
1316 
1317 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
1318   if (!GetParam().isCXX()) {
1319     return;
1320   }
1321   EXPECT_TRUE(treeDumpEqual(
1322       R"cpp(
1323 struct X {
1324   X& operator=(const X&);
1325   friend X operator+(X, const X&);
1326   friend bool operator<(const X&, const X&);
1327 };
1328 void test(X x, X y) {
1329   x = y;
1330   x + y;
1331   x < y;
1332 }
1333 )cpp",
1334       R"txt(
1335 *: TranslationUnit
1336 |-SimpleDeclaration
1337 | |-struct
1338 | |-X
1339 | |-{
1340 | |-SimpleDeclaration
1341 | | |-X
1342 | | |-SimpleDeclarator
1343 | | | |-&
1344 | | | |-operator
1345 | | | |-=
1346 | | | `-ParametersAndQualifiers
1347 | | |   |-(
1348 | | |   |-SimpleDeclaration
1349 | | |   | |-const
1350 | | |   | |-X
1351 | | |   | `-SimpleDeclarator
1352 | | |   |   `-&
1353 | | |   `-)
1354 | | `-;
1355 | |-UnknownDeclaration
1356 | | `-SimpleDeclaration
1357 | |   |-friend
1358 | |   |-X
1359 | |   |-SimpleDeclarator
1360 | |   | |-operator
1361 | |   | |-+
1362 | |   | `-ParametersAndQualifiers
1363 | |   |   |-(
1364 | |   |   |-SimpleDeclaration
1365 | |   |   | `-X
1366 | |   |   |-,
1367 | |   |   |-SimpleDeclaration
1368 | |   |   | |-const
1369 | |   |   | |-X
1370 | |   |   | `-SimpleDeclarator
1371 | |   |   |   `-&
1372 | |   |   `-)
1373 | |   `-;
1374 | |-UnknownDeclaration
1375 | | `-SimpleDeclaration
1376 | |   |-friend
1377 | |   |-bool
1378 | |   |-SimpleDeclarator
1379 | |   | |-operator
1380 | |   | |-<
1381 | |   | `-ParametersAndQualifiers
1382 | |   |   |-(
1383 | |   |   |-SimpleDeclaration
1384 | |   |   | |-const
1385 | |   |   | |-X
1386 | |   |   | `-SimpleDeclarator
1387 | |   |   |   `-&
1388 | |   |   |-,
1389 | |   |   |-SimpleDeclaration
1390 | |   |   | |-const
1391 | |   |   | |-X
1392 | |   |   | `-SimpleDeclarator
1393 | |   |   |   `-&
1394 | |   |   `-)
1395 | |   `-;
1396 | |-}
1397 | `-;
1398 `-SimpleDeclaration
1399   |-void
1400   |-SimpleDeclarator
1401   | |-test
1402   | `-ParametersAndQualifiers
1403   |   |-(
1404   |   |-SimpleDeclaration
1405   |   | |-X
1406   |   | `-SimpleDeclarator
1407   |   |   `-x
1408   |   |-,
1409   |   |-SimpleDeclaration
1410   |   | |-X
1411   |   | `-SimpleDeclarator
1412   |   |   `-y
1413   |   `-)
1414   `-CompoundStatement
1415     |-{
1416     |-ExpressionStatement
1417     | |-BinaryOperatorExpression
1418     | | |-UnknownExpression
1419     | | | `-x
1420     | | |-UnknownExpression
1421     | | | `-=
1422     | | `-UnknownExpression
1423     | |   `-y
1424     | `-;
1425     |-ExpressionStatement
1426     | |-BinaryOperatorExpression
1427     | | |-UnknownExpression
1428     | | | `-UnknownExpression
1429     | | |   `-x
1430     | | |-UnknownExpression
1431     | | | `-+
1432     | | `-UnknownExpression
1433     | |   `-y
1434     | `-;
1435     |-ExpressionStatement
1436     | |-BinaryOperatorExpression
1437     | | |-UnknownExpression
1438     | | | `-x
1439     | | |-UnknownExpression
1440     | | | `-<
1441     | | `-UnknownExpression
1442     | |   `-y
1443     | `-;
1444     `-}
1445 )txt"));
1446 }
1447 
1448 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
1449   EXPECT_TRUE(treeDumpEqual(
1450       R"cpp(
1451 int *a, b;
1452 int *c, d;
1453 )cpp",
1454       R"txt(
1455 *: TranslationUnit
1456 |-SimpleDeclaration
1457 | |-int
1458 | |-SimpleDeclarator
1459 | | |-*
1460 | | `-a
1461 | |-,
1462 | |-SimpleDeclarator
1463 | | `-b
1464 | `-;
1465 `-SimpleDeclaration
1466   |-int
1467   |-SimpleDeclarator
1468   | |-*
1469   | `-c
1470   |-,
1471   |-SimpleDeclarator
1472   | `-d
1473   `-;
1474 )txt"));
1475 }
1476 
1477 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
1478   EXPECT_TRUE(treeDumpEqual(
1479       R"cpp(
1480 typedef int *a, b;
1481 )cpp",
1482       R"txt(
1483 *: TranslationUnit
1484 `-SimpleDeclaration
1485   |-typedef
1486   |-int
1487   |-SimpleDeclarator
1488   | |-*
1489   | `-a
1490   |-,
1491   |-SimpleDeclarator
1492   | `-b
1493   `-;
1494 )txt"));
1495 }
1496 
1497 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
1498   EXPECT_TRUE(treeDumpEqual(
1499       R"cpp(
1500 void foo() {
1501   int *a, b;
1502   typedef int *ta, tb;
1503 }
1504 )cpp",
1505       R"txt(
1506 *: TranslationUnit
1507 `-SimpleDeclaration
1508   |-void
1509   |-SimpleDeclarator
1510   | |-foo
1511   | `-ParametersAndQualifiers
1512   |   |-(
1513   |   `-)
1514   `-CompoundStatement
1515     |-{
1516     |-DeclarationStatement
1517     | |-SimpleDeclaration
1518     | | |-int
1519     | | |-SimpleDeclarator
1520     | | | |-*
1521     | | | `-a
1522     | | |-,
1523     | | `-SimpleDeclarator
1524     | |   `-b
1525     | `-;
1526     |-DeclarationStatement
1527     | |-SimpleDeclaration
1528     | | |-typedef
1529     | | |-int
1530     | | |-SimpleDeclarator
1531     | | | |-*
1532     | | | `-ta
1533     | | |-,
1534     | | `-SimpleDeclarator
1535     | |   `-tb
1536     | `-;
1537     `-}
1538 )txt"));
1539 }
1540 
1541 TEST_P(SyntaxTreeTest, Namespaces) {
1542   if (!GetParam().isCXX()) {
1543     return;
1544   }
1545   EXPECT_TRUE(treeDumpEqual(
1546       R"cpp(
1547 namespace a { namespace b {} }
1548 namespace a::b {}
1549 namespace {}
1550 
1551 namespace foo = a;
1552 )cpp",
1553       R"txt(
1554 *: TranslationUnit
1555 |-NamespaceDefinition
1556 | |-namespace
1557 | |-a
1558 | |-{
1559 | |-NamespaceDefinition
1560 | | |-namespace
1561 | | |-b
1562 | | |-{
1563 | | `-}
1564 | `-}
1565 |-NamespaceDefinition
1566 | |-namespace
1567 | |-a
1568 | |-::
1569 | |-b
1570 | |-{
1571 | `-}
1572 |-NamespaceDefinition
1573 | |-namespace
1574 | |-{
1575 | `-}
1576 `-NamespaceAliasDefinition
1577   |-namespace
1578   |-foo
1579   |-=
1580   |-a
1581   `-;
1582 )txt"));
1583 }
1584 
1585 TEST_P(SyntaxTreeTest, UsingDirective) {
1586   if (!GetParam().isCXX()) {
1587     return;
1588   }
1589   EXPECT_TRUE(treeDumpEqual(
1590       R"cpp(
1591 namespace ns {}
1592 using namespace ::ns;
1593 )cpp",
1594       R"txt(
1595 *: TranslationUnit
1596 |-NamespaceDefinition
1597 | |-namespace
1598 | |-ns
1599 | |-{
1600 | `-}
1601 `-UsingNamespaceDirective
1602   |-using
1603   |-namespace
1604   |-::
1605   |-ns
1606   `-;
1607 )txt"));
1608 }
1609 
1610 TEST_P(SyntaxTreeTest, UsingDeclaration) {
1611   if (!GetParam().isCXX()) {
1612     return;
1613   }
1614   EXPECT_TRUE(treeDumpEqual(
1615       R"cpp(
1616 namespace ns { int a; }
1617 using ns::a;
1618 )cpp",
1619       R"txt(
1620 *: TranslationUnit
1621 |-NamespaceDefinition
1622 | |-namespace
1623 | |-ns
1624 | |-{
1625 | |-SimpleDeclaration
1626 | | |-int
1627 | | |-SimpleDeclarator
1628 | | | `-a
1629 | | `-;
1630 | `-}
1631 `-UsingDeclaration
1632   |-using
1633   |-ns
1634   |-::
1635   |-a
1636   `-;
1637 )txt"));
1638 }
1639 
1640 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
1641   // Free-standing classes, must live inside a SimpleDeclaration.
1642   EXPECT_TRUE(treeDumpEqual(
1643       R"cpp(
1644 struct X;
1645 struct X {};
1646 
1647 struct Y *y1;
1648 struct Y {} *y2;
1649 
1650 struct {} *a1;
1651 )cpp",
1652       R"txt(
1653 *: TranslationUnit
1654 |-SimpleDeclaration
1655 | |-struct
1656 | |-X
1657 | `-;
1658 |-SimpleDeclaration
1659 | |-struct
1660 | |-X
1661 | |-{
1662 | |-}
1663 | `-;
1664 |-SimpleDeclaration
1665 | |-struct
1666 | |-Y
1667 | |-SimpleDeclarator
1668 | | |-*
1669 | | `-y1
1670 | `-;
1671 |-SimpleDeclaration
1672 | |-struct
1673 | |-Y
1674 | |-{
1675 | |-}
1676 | |-SimpleDeclarator
1677 | | |-*
1678 | | `-y2
1679 | `-;
1680 `-SimpleDeclaration
1681   |-struct
1682   |-{
1683   |-}
1684   |-SimpleDeclarator
1685   | |-*
1686   | `-a1
1687   `-;
1688 )txt"));
1689 }
1690 
1691 TEST_P(SyntaxTreeTest, Templates) {
1692   if (!GetParam().isCXX()) {
1693     return;
1694   }
1695   if (GetParam().hasDelayedTemplateParsing()) {
1696     // FIXME: Make this test work on Windows by generating the expected syntax
1697     // tree when `-fdelayed-template-parsing` is active.
1698     return;
1699   }
1700   EXPECT_TRUE(treeDumpEqual(
1701       R"cpp(
1702 template <class T> struct cls {};
1703 template <class T> int var = 10;
1704 template <class T> int fun() {}
1705 )cpp",
1706       R"txt(
1707 *: TranslationUnit
1708 |-TemplateDeclaration
1709 | |-template
1710 | |-<
1711 | |-UnknownDeclaration
1712 | | |-class
1713 | | `-T
1714 | |->
1715 | `-SimpleDeclaration
1716 |   |-struct
1717 |   |-cls
1718 |   |-{
1719 |   |-}
1720 |   `-;
1721 |-TemplateDeclaration
1722 | |-template
1723 | |-<
1724 | |-UnknownDeclaration
1725 | | |-class
1726 | | `-T
1727 | |->
1728 | `-SimpleDeclaration
1729 |   |-int
1730 |   |-SimpleDeclarator
1731 |   | |-var
1732 |   | |-=
1733 |   | `-IntegerLiteralExpression
1734 |   |   `-10
1735 |   `-;
1736 `-TemplateDeclaration
1737   |-template
1738   |-<
1739   |-UnknownDeclaration
1740   | |-class
1741   | `-T
1742   |->
1743   `-SimpleDeclaration
1744     |-int
1745     |-SimpleDeclarator
1746     | |-fun
1747     | `-ParametersAndQualifiers
1748     |   |-(
1749     |   `-)
1750     `-CompoundStatement
1751       |-{
1752       `-}
1753 )txt"));
1754 }
1755 
1756 TEST_P(SyntaxTreeTest, NestedTemplates) {
1757   if (!GetParam().isCXX()) {
1758     return;
1759   }
1760   EXPECT_TRUE(treeDumpEqual(
1761       R"cpp(
1762 template <class T>
1763 struct X {
1764   template <class U>
1765   U foo();
1766 };
1767 )cpp",
1768       R"txt(
1769 *: TranslationUnit
1770 `-TemplateDeclaration
1771   |-template
1772   |-<
1773   |-UnknownDeclaration
1774   | |-class
1775   | `-T
1776   |->
1777   `-SimpleDeclaration
1778     |-struct
1779     |-X
1780     |-{
1781     |-TemplateDeclaration
1782     | |-template
1783     | |-<
1784     | |-UnknownDeclaration
1785     | | |-class
1786     | | `-U
1787     | |->
1788     | `-SimpleDeclaration
1789     |   |-U
1790     |   |-SimpleDeclarator
1791     |   | |-foo
1792     |   | `-ParametersAndQualifiers
1793     |   |   |-(
1794     |   |   `-)
1795     |   `-;
1796     |-}
1797     `-;
1798 )txt"));
1799 }
1800 
1801 TEST_P(SyntaxTreeTest, Templates2) {
1802   if (!GetParam().isCXX()) {
1803     return;
1804   }
1805   EXPECT_TRUE(treeDumpEqual(
1806       R"cpp(
1807 template <class T> struct X { struct Y; };
1808 template <class T> struct X<T>::Y {};
1809 )cpp",
1810       R"txt(
1811 *: TranslationUnit
1812 |-TemplateDeclaration
1813 | |-template
1814 | |-<
1815 | |-UnknownDeclaration
1816 | | |-class
1817 | | `-T
1818 | |->
1819 | `-SimpleDeclaration
1820 |   |-struct
1821 |   |-X
1822 |   |-{
1823 |   |-SimpleDeclaration
1824 |   | |-struct
1825 |   | |-Y
1826 |   | `-;
1827 |   |-}
1828 |   `-;
1829 `-TemplateDeclaration
1830   |-template
1831   |-<
1832   |-UnknownDeclaration
1833   | |-class
1834   | `-T
1835   |->
1836   `-SimpleDeclaration
1837     |-struct
1838     |-X
1839     |-<
1840     |-T
1841     |->
1842     |-::
1843     |-Y
1844     |-{
1845     |-}
1846     `-;
1847 )txt"));
1848 }
1849 
1850 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
1851   if (!GetParam().isCXX()) {
1852     return;
1853   }
1854   EXPECT_TRUE(treeDumpEqual(
1855       R"cpp(
1856 template <class T> struct X {
1857   using T::foo;
1858   using typename T::bar;
1859 };
1860 )cpp",
1861       R"txt(
1862 *: TranslationUnit
1863 `-TemplateDeclaration
1864   |-template
1865   |-<
1866   |-UnknownDeclaration
1867   | |-class
1868   | `-T
1869   |->
1870   `-SimpleDeclaration
1871     |-struct
1872     |-X
1873     |-{
1874     |-UsingDeclaration
1875     | |-using
1876     | |-T
1877     | |-::
1878     | |-foo
1879     | `-;
1880     |-UsingDeclaration
1881     | |-using
1882     | |-typename
1883     | |-T
1884     | |-::
1885     | |-bar
1886     | `-;
1887     |-}
1888     `-;
1889 )txt"));
1890 }
1891 
1892 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
1893   if (!GetParam().isCXX()) {
1894     return;
1895   }
1896   EXPECT_TRUE(treeDumpEqual(
1897       R"cpp(
1898 template <class T> struct X {};
1899 template <class T> struct X<T*> {};
1900 template <> struct X<int> {};
1901 
1902 template struct X<double>;
1903 extern template struct X<float>;
1904 )cpp",
1905       R"txt(
1906 *: TranslationUnit
1907 |-TemplateDeclaration
1908 | |-template
1909 | |-<
1910 | |-UnknownDeclaration
1911 | | |-class
1912 | | `-T
1913 | |->
1914 | `-SimpleDeclaration
1915 |   |-struct
1916 |   |-X
1917 |   |-{
1918 |   |-}
1919 |   `-;
1920 |-TemplateDeclaration
1921 | |-template
1922 | |-<
1923 | |-UnknownDeclaration
1924 | | |-class
1925 | | `-T
1926 | |->
1927 | `-SimpleDeclaration
1928 |   |-struct
1929 |   |-X
1930 |   |-<
1931 |   |-T
1932 |   |-*
1933 |   |->
1934 |   |-{
1935 |   |-}
1936 |   `-;
1937 |-TemplateDeclaration
1938 | |-template
1939 | |-<
1940 | |->
1941 | `-SimpleDeclaration
1942 |   |-struct
1943 |   |-X
1944 |   |-<
1945 |   |-int
1946 |   |->
1947 |   |-{
1948 |   |-}
1949 |   `-;
1950 |-ExplicitTemplateInstantiation
1951 | |-template
1952 | `-SimpleDeclaration
1953 |   |-struct
1954 |   |-X
1955 |   |-<
1956 |   |-double
1957 |   |->
1958 |   `-;
1959 `-ExplicitTemplateInstantiation
1960   |-extern
1961   |-template
1962   `-SimpleDeclaration
1963     |-struct
1964     |-X
1965     |-<
1966     |-float
1967     |->
1968     `-;
1969 )txt"));
1970 }
1971 
1972 TEST_P(SyntaxTreeTest, UsingType) {
1973   if (!GetParam().isCXX()) {
1974     return;
1975   }
1976   EXPECT_TRUE(treeDumpEqual(
1977       R"cpp(
1978 using type = int;
1979 )cpp",
1980       R"txt(
1981 *: TranslationUnit
1982 `-TypeAliasDeclaration
1983   |-using
1984   |-type
1985   |-=
1986   |-int
1987   `-;
1988 )txt"));
1989 }
1990 
1991 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
1992   EXPECT_TRUE(treeDumpEqual(
1993       R"cpp(
1994 ;
1995 )cpp",
1996       R"txt(
1997 *: TranslationUnit
1998 `-EmptyDeclaration
1999   `-;
2000 )txt"));
2001 }
2002 
2003 TEST_P(SyntaxTreeTest, StaticAssert) {
2004   if (!GetParam().isCXX11OrLater()) {
2005     return;
2006   }
2007   EXPECT_TRUE(treeDumpEqual(
2008       R"cpp(
2009 static_assert(true, "message");
2010 static_assert(true);
2011 )cpp",
2012       R"txt(
2013 *: TranslationUnit
2014 |-StaticAssertDeclaration
2015 | |-static_assert
2016 | |-(
2017 | |-UnknownExpression
2018 | | `-true
2019 | |-,
2020 | |-UnknownExpression
2021 | | `-"message"
2022 | |-)
2023 | `-;
2024 `-StaticAssertDeclaration
2025   |-static_assert
2026   |-(
2027   |-UnknownExpression
2028   | `-true
2029   |-)
2030   `-;
2031 )txt"));
2032 }
2033 
2034 TEST_P(SyntaxTreeTest, ExternC) {
2035   if (!GetParam().isCXX()) {
2036     return;
2037   }
2038   EXPECT_TRUE(treeDumpEqual(
2039       R"cpp(
2040 extern "C" int a;
2041 extern "C" { int b; int c; }
2042 )cpp",
2043       R"txt(
2044 *: TranslationUnit
2045 |-LinkageSpecificationDeclaration
2046 | |-extern
2047 | |-"C"
2048 | `-SimpleDeclaration
2049 |   |-int
2050 |   |-SimpleDeclarator
2051 |   | `-a
2052 |   `-;
2053 `-LinkageSpecificationDeclaration
2054   |-extern
2055   |-"C"
2056   |-{
2057   |-SimpleDeclaration
2058   | |-int
2059   | |-SimpleDeclarator
2060   | | `-b
2061   | `-;
2062   |-SimpleDeclaration
2063   | |-int
2064   | |-SimpleDeclarator
2065   | | `-c
2066   | `-;
2067   `-}
2068 )txt"));
2069 }
2070 
2071 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
2072   // Some nodes are non-modifiable, they are marked with 'I:'.
2073   EXPECT_TRUE(treeDumpEqual(
2074       R"cpp(
2075 #define HALF_IF if (1+
2076 #define HALF_IF_2 1) {}
2077 void test() {
2078   HALF_IF HALF_IF_2 else {}
2079 })cpp",
2080       R"txt(
2081 *: TranslationUnit
2082 `-SimpleDeclaration
2083   |-void
2084   |-SimpleDeclarator
2085   | |-test
2086   | `-ParametersAndQualifiers
2087   |   |-(
2088   |   `-)
2089   `-CompoundStatement
2090     |-{
2091     |-IfStatement
2092     | |-I: if
2093     | |-I: (
2094     | |-I: BinaryOperatorExpression
2095     | | |-I: IntegerLiteralExpression
2096     | | | `-I: 1
2097     | | |-I: +
2098     | | `-I: IntegerLiteralExpression
2099     | |   `-I: 1
2100     | |-I: )
2101     | |-I: CompoundStatement
2102     | | |-I: {
2103     | | `-I: }
2104     | |-else
2105     | `-CompoundStatement
2106     |   |-{
2107     |   `-}
2108     `-}
2109 )txt"));
2110 }
2111 
2112 TEST_P(SyntaxTreeTest, ModifiableNodes) {
2113   // All nodes can be mutated.
2114   EXPECT_TRUE(treeDumpEqual(
2115       R"cpp(
2116 #define OPEN {
2117 #define CLOSE }
2118 
2119 void test() {
2120   OPEN
2121     1;
2122   CLOSE
2123 
2124   OPEN
2125     2;
2126   }
2127 }
2128 )cpp",
2129       R"txt(
2130 *: TranslationUnit
2131 `-SimpleDeclaration
2132   |-void
2133   |-SimpleDeclarator
2134   | |-test
2135   | `-ParametersAndQualifiers
2136   |   |-(
2137   |   `-)
2138   `-CompoundStatement
2139     |-{
2140     |-CompoundStatement
2141     | |-{
2142     | |-ExpressionStatement
2143     | | |-IntegerLiteralExpression
2144     | | | `-1
2145     | | `-;
2146     | `-}
2147     |-CompoundStatement
2148     | |-{
2149     | |-ExpressionStatement
2150     | | |-IntegerLiteralExpression
2151     | | | `-2
2152     | | `-;
2153     | `-}
2154     `-}
2155 )txt"));
2156 }
2157 
2158 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
2159   EXPECT_TRUE(treeDumpEqual(
2160       R"cpp(
2161 int a[10];
2162 int b[1][2][3];
2163 int c[] = {1,2,3};
2164 )cpp",
2165       R"txt(
2166 *: TranslationUnit
2167 |-SimpleDeclaration
2168 | |-int
2169 | |-SimpleDeclarator
2170 | | |-a
2171 | | `-ArraySubscript
2172 | |   |-[
2173 | |   |-IntegerLiteralExpression
2174 | |   | `-10
2175 | |   `-]
2176 | `-;
2177 |-SimpleDeclaration
2178 | |-int
2179 | |-SimpleDeclarator
2180 | | |-b
2181 | | |-ArraySubscript
2182 | | | |-[
2183 | | | |-IntegerLiteralExpression
2184 | | | | `-1
2185 | | | `-]
2186 | | |-ArraySubscript
2187 | | | |-[
2188 | | | |-IntegerLiteralExpression
2189 | | | | `-2
2190 | | | `-]
2191 | | `-ArraySubscript
2192 | |   |-[
2193 | |   |-IntegerLiteralExpression
2194 | |   | `-3
2195 | |   `-]
2196 | `-;
2197 `-SimpleDeclaration
2198   |-int
2199   |-SimpleDeclarator
2200   | |-c
2201   | |-ArraySubscript
2202   | | |-[
2203   | | `-]
2204   | |-=
2205   | `-UnknownExpression
2206   |   `-UnknownExpression
2207   |     |-{
2208   |     |-IntegerLiteralExpression
2209   |     | `-1
2210   |     |-,
2211   |     |-IntegerLiteralExpression
2212   |     | `-2
2213   |     |-,
2214   |     |-IntegerLiteralExpression
2215   |     | `-3
2216   |     `-}
2217   `-;
2218 )txt"));
2219 }
2220 
2221 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
2222   if (!GetParam().isC99OrLater()) {
2223     return;
2224   }
2225   EXPECT_TRUE(treeDumpEqual(
2226       R"cpp(
2227 void f(int xs[static 10]);
2228 )cpp",
2229       R"txt(
2230 *: TranslationUnit
2231 `-SimpleDeclaration
2232   |-void
2233   |-SimpleDeclarator
2234   | |-f
2235   | `-ParametersAndQualifiers
2236   |   |-(
2237   |   |-SimpleDeclaration
2238   |   | |-int
2239   |   | `-SimpleDeclarator
2240   |   |   |-xs
2241   |   |   `-ArraySubscript
2242   |   |     |-[
2243   |   |     |-static
2244   |   |     |-IntegerLiteralExpression
2245   |   |     | `-10
2246   |   |     `-]
2247   |   `-)
2248   `-;
2249 )txt"));
2250 }
2251 
2252 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
2253   if (!GetParam().isCXX()) {
2254     return;
2255   }
2256   EXPECT_TRUE(treeDumpEqual(
2257       R"cpp(
2258 int func1();
2259 int func2a(int a);
2260 int func2b(int);
2261 int func3a(int *ap);
2262 int func3b(int *);
2263 int func4a(int a, float b);
2264 int func4b(int, float);
2265 )cpp",
2266       R"txt(
2267 *: TranslationUnit
2268 |-SimpleDeclaration
2269 | |-int
2270 | |-SimpleDeclarator
2271 | | |-func1
2272 | | `-ParametersAndQualifiers
2273 | |   |-(
2274 | |   `-)
2275 | `-;
2276 |-SimpleDeclaration
2277 | |-int
2278 | |-SimpleDeclarator
2279 | | |-func2a
2280 | | `-ParametersAndQualifiers
2281 | |   |-(
2282 | |   |-SimpleDeclaration
2283 | |   | |-int
2284 | |   | `-SimpleDeclarator
2285 | |   |   `-a
2286 | |   `-)
2287 | `-;
2288 |-SimpleDeclaration
2289 | |-int
2290 | |-SimpleDeclarator
2291 | | |-func2b
2292 | | `-ParametersAndQualifiers
2293 | |   |-(
2294 | |   |-SimpleDeclaration
2295 | |   | `-int
2296 | |   `-)
2297 | `-;
2298 |-SimpleDeclaration
2299 | |-int
2300 | |-SimpleDeclarator
2301 | | |-func3a
2302 | | `-ParametersAndQualifiers
2303 | |   |-(
2304 | |   |-SimpleDeclaration
2305 | |   | |-int
2306 | |   | `-SimpleDeclarator
2307 | |   |   |-*
2308 | |   |   `-ap
2309 | |   `-)
2310 | `-;
2311 |-SimpleDeclaration
2312 | |-int
2313 | |-SimpleDeclarator
2314 | | |-func3b
2315 | | `-ParametersAndQualifiers
2316 | |   |-(
2317 | |   |-SimpleDeclaration
2318 | |   | |-int
2319 | |   | `-SimpleDeclarator
2320 | |   |   `-*
2321 | |   `-)
2322 | `-;
2323 |-SimpleDeclaration
2324 | |-int
2325 | |-SimpleDeclarator
2326 | | |-func4a
2327 | | `-ParametersAndQualifiers
2328 | |   |-(
2329 | |   |-SimpleDeclaration
2330 | |   | |-int
2331 | |   | `-SimpleDeclarator
2332 | |   |   `-a
2333 | |   |-,
2334 | |   |-SimpleDeclaration
2335 | |   | |-float
2336 | |   | `-SimpleDeclarator
2337 | |   |   `-b
2338 | |   `-)
2339 | `-;
2340 `-SimpleDeclaration
2341   |-int
2342   |-SimpleDeclarator
2343   | |-func4b
2344   | `-ParametersAndQualifiers
2345   |   |-(
2346   |   |-SimpleDeclaration
2347   |   | `-int
2348   |   |-,
2349   |   |-SimpleDeclaration
2350   |   | `-float
2351   |   `-)
2352   `-;
2353 )txt"));
2354 }
2355 
2356 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
2357   if (!GetParam().isCXX()) {
2358     return;
2359   }
2360   EXPECT_TRUE(treeDumpEqual(
2361       R"cpp(
2362 int func1(const int a, volatile int b, const volatile int c);
2363 int func2(int& a);
2364 )cpp",
2365       R"txt(
2366 *: TranslationUnit
2367 |-SimpleDeclaration
2368 | |-int
2369 | |-SimpleDeclarator
2370 | | |-func1
2371 | | `-ParametersAndQualifiers
2372 | |   |-(
2373 | |   |-SimpleDeclaration
2374 | |   | |-const
2375 | |   | |-int
2376 | |   | `-SimpleDeclarator
2377 | |   |   `-a
2378 | |   |-,
2379 | |   |-SimpleDeclaration
2380 | |   | |-volatile
2381 | |   | |-int
2382 | |   | `-SimpleDeclarator
2383 | |   |   `-b
2384 | |   |-,
2385 | |   |-SimpleDeclaration
2386 | |   | |-const
2387 | |   | |-volatile
2388 | |   | |-int
2389 | |   | `-SimpleDeclarator
2390 | |   |   `-c
2391 | |   `-)
2392 | `-;
2393 `-SimpleDeclaration
2394   |-int
2395   |-SimpleDeclarator
2396   | |-func2
2397   | `-ParametersAndQualifiers
2398   |   |-(
2399   |   |-SimpleDeclaration
2400   |   | |-int
2401   |   | `-SimpleDeclarator
2402   |   |   |-&
2403   |   |   `-a
2404   |   `-)
2405   `-;
2406 )txt"));
2407 }
2408 
2409 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
2410   if (!GetParam().isCXX11OrLater()) {
2411     return;
2412   }
2413   EXPECT_TRUE(treeDumpEqual(
2414       R"cpp(
2415 int func1(int&& a);
2416 )cpp",
2417       R"txt(
2418 *: TranslationUnit
2419 `-SimpleDeclaration
2420   |-int
2421   |-SimpleDeclarator
2422   | |-func1
2423   | `-ParametersAndQualifiers
2424   |   |-(
2425   |   |-SimpleDeclaration
2426   |   | |-int
2427   |   | `-SimpleDeclarator
2428   |   |   |-&&
2429   |   |   `-a
2430   |   `-)
2431   `-;
2432 )txt"));
2433 }
2434 
2435 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
2436   if (!GetParam().isCXX()) {
2437     return;
2438   }
2439   EXPECT_TRUE(treeDumpEqual(
2440       R"cpp(
2441 struct Test {
2442   int a();
2443   int b() const;
2444   int c() volatile;
2445   int d() const volatile;
2446   int e() &;
2447   int f() &&;
2448 };
2449 )cpp",
2450       R"txt(
2451 *: TranslationUnit
2452 `-SimpleDeclaration
2453   |-struct
2454   |-Test
2455   |-{
2456   |-SimpleDeclaration
2457   | |-int
2458   | |-SimpleDeclarator
2459   | | |-a
2460   | | `-ParametersAndQualifiers
2461   | |   |-(
2462   | |   `-)
2463   | `-;
2464   |-SimpleDeclaration
2465   | |-int
2466   | |-SimpleDeclarator
2467   | | |-b
2468   | | `-ParametersAndQualifiers
2469   | |   |-(
2470   | |   |-)
2471   | |   `-const
2472   | `-;
2473   |-SimpleDeclaration
2474   | |-int
2475   | |-SimpleDeclarator
2476   | | |-c
2477   | | `-ParametersAndQualifiers
2478   | |   |-(
2479   | |   |-)
2480   | |   `-volatile
2481   | `-;
2482   |-SimpleDeclaration
2483   | |-int
2484   | |-SimpleDeclarator
2485   | | |-d
2486   | | `-ParametersAndQualifiers
2487   | |   |-(
2488   | |   |-)
2489   | |   |-const
2490   | |   `-volatile
2491   | `-;
2492   |-SimpleDeclaration
2493   | |-int
2494   | |-SimpleDeclarator
2495   | | |-e
2496   | | `-ParametersAndQualifiers
2497   | |   |-(
2498   | |   |-)
2499   | |   `-&
2500   | `-;
2501   |-SimpleDeclaration
2502   | |-int
2503   | |-SimpleDeclarator
2504   | | |-f
2505   | | `-ParametersAndQualifiers
2506   | |   |-(
2507   | |   |-)
2508   | |   `-&&
2509   | `-;
2510   |-}
2511   `-;
2512 )txt"));
2513 }
2514 
2515 TEST_P(SyntaxTreeTest, TrailingReturn) {
2516   if (!GetParam().isCXX11OrLater()) {
2517     return;
2518   }
2519   EXPECT_TRUE(treeDumpEqual(
2520       R"cpp(
2521 auto foo() -> int;
2522 )cpp",
2523       R"txt(
2524 *: TranslationUnit
2525 `-SimpleDeclaration
2526   |-auto
2527   |-SimpleDeclarator
2528   | |-foo
2529   | `-ParametersAndQualifiers
2530   |   |-(
2531   |   |-)
2532   |   `-TrailingReturnType
2533   |     |-->
2534   |     `-int
2535   `-;
2536 )txt"));
2537 }
2538 
2539 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
2540   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
2541     return;
2542   }
2543   EXPECT_TRUE(treeDumpEqual(
2544       R"cpp(
2545 struct MyException1 {};
2546 struct MyException2 {};
2547 int a() throw();
2548 int b() throw(...);
2549 int c() throw(MyException1);
2550 int d() throw(MyException1, MyException2);
2551 )cpp",
2552       R"txt(
2553 *: TranslationUnit
2554 |-SimpleDeclaration
2555 | |-struct
2556 | |-MyException1
2557 | |-{
2558 | |-}
2559 | `-;
2560 |-SimpleDeclaration
2561 | |-struct
2562 | |-MyException2
2563 | |-{
2564 | |-}
2565 | `-;
2566 |-SimpleDeclaration
2567 | |-int
2568 | |-SimpleDeclarator
2569 | | |-a
2570 | | `-ParametersAndQualifiers
2571 | |   |-(
2572 | |   |-)
2573 | |   |-throw
2574 | |   |-(
2575 | |   `-)
2576 | `-;
2577 |-SimpleDeclaration
2578 | |-int
2579 | |-SimpleDeclarator
2580 | | |-b
2581 | | `-ParametersAndQualifiers
2582 | |   |-(
2583 | |   |-)
2584 | |   |-throw
2585 | |   |-(
2586 | |   |-...
2587 | |   `-)
2588 | `-;
2589 |-SimpleDeclaration
2590 | |-int
2591 | |-SimpleDeclarator
2592 | | |-c
2593 | | `-ParametersAndQualifiers
2594 | |   |-(
2595 | |   |-)
2596 | |   |-throw
2597 | |   |-(
2598 | |   |-MyException1
2599 | |   `-)
2600 | `-;
2601 `-SimpleDeclaration
2602   |-int
2603   |-SimpleDeclarator
2604   | |-d
2605   | `-ParametersAndQualifiers
2606   |   |-(
2607   |   |-)
2608   |   |-throw
2609   |   |-(
2610   |   |-MyException1
2611   |   |-,
2612   |   |-MyException2
2613   |   `-)
2614   `-;
2615 )txt"));
2616 }
2617 
2618 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
2619   if (!GetParam().isCXX11OrLater()) {
2620     return;
2621   }
2622   EXPECT_TRUE(treeDumpEqual(
2623       R"cpp(
2624 int a() noexcept;
2625 int b() noexcept(true);
2626 )cpp",
2627       R"txt(
2628 *: TranslationUnit
2629 |-SimpleDeclaration
2630 | |-int
2631 | |-SimpleDeclarator
2632 | | |-a
2633 | | `-ParametersAndQualifiers
2634 | |   |-(
2635 | |   |-)
2636 | |   `-noexcept
2637 | `-;
2638 `-SimpleDeclaration
2639   |-int
2640   |-SimpleDeclarator
2641   | |-b
2642   | `-ParametersAndQualifiers
2643   |   |-(
2644   |   |-)
2645   |   |-noexcept
2646   |   |-(
2647   |   |-UnknownExpression
2648   |   | `-true
2649   |   `-)
2650   `-;
2651 )txt"));
2652 }
2653 
2654 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
2655   EXPECT_TRUE(treeDumpEqual(
2656       R"cpp(
2657 int (a);
2658 int *(b);
2659 int (*c)(int);
2660 int *(d)(int);
2661 )cpp",
2662       R"txt(
2663 *: TranslationUnit
2664 |-SimpleDeclaration
2665 | |-int
2666 | |-SimpleDeclarator
2667 | | `-ParenDeclarator
2668 | |   |-(
2669 | |   |-a
2670 | |   `-)
2671 | `-;
2672 |-SimpleDeclaration
2673 | |-int
2674 | |-SimpleDeclarator
2675 | | |-*
2676 | | `-ParenDeclarator
2677 | |   |-(
2678 | |   |-b
2679 | |   `-)
2680 | `-;
2681 |-SimpleDeclaration
2682 | |-int
2683 | |-SimpleDeclarator
2684 | | |-ParenDeclarator
2685 | | | |-(
2686 | | | |-*
2687 | | | |-c
2688 | | | `-)
2689 | | `-ParametersAndQualifiers
2690 | |   |-(
2691 | |   |-SimpleDeclaration
2692 | |   | `-int
2693 | |   `-)
2694 | `-;
2695 `-SimpleDeclaration
2696   |-int
2697   |-SimpleDeclarator
2698   | |-*
2699   | |-ParenDeclarator
2700   | | |-(
2701   | | |-d
2702   | | `-)
2703   | `-ParametersAndQualifiers
2704   |   |-(
2705   |   |-SimpleDeclaration
2706   |   | `-int
2707   |   `-)
2708   `-;
2709 )txt"));
2710 }
2711 
2712 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
2713   EXPECT_TRUE(treeDumpEqual(
2714       R"cpp(
2715 const int west = -1;
2716 int const east = 1;
2717 const int const universal = 0;
2718 const int const *const *volatile b;
2719 )cpp",
2720       R"txt(
2721 *: TranslationUnit
2722 |-SimpleDeclaration
2723 | |-const
2724 | |-int
2725 | |-SimpleDeclarator
2726 | | |-west
2727 | | |-=
2728 | | `-PrefixUnaryOperatorExpression
2729 | |   |--
2730 | |   `-IntegerLiteralExpression
2731 | |     `-1
2732 | `-;
2733 |-SimpleDeclaration
2734 | |-int
2735 | |-const
2736 | |-SimpleDeclarator
2737 | | |-east
2738 | | |-=
2739 | | `-IntegerLiteralExpression
2740 | |   `-1
2741 | `-;
2742 |-SimpleDeclaration
2743 | |-const
2744 | |-int
2745 | |-const
2746 | |-SimpleDeclarator
2747 | | |-universal
2748 | | |-=
2749 | | `-IntegerLiteralExpression
2750 | |   `-0
2751 | `-;
2752 `-SimpleDeclaration
2753   |-const
2754   |-int
2755   |-const
2756   |-SimpleDeclarator
2757   | |-*
2758   | |-const
2759   | |-*
2760   | |-volatile
2761   | `-b
2762   `-;
2763 )txt"));
2764 }
2765 
2766 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
2767   if (!GetParam().isCXX11OrLater()) {
2768     return;
2769   }
2770   EXPECT_TRUE(treeDumpEqual(
2771       R"cpp(
2772 auto foo() -> auto(*)(int) -> double*;
2773 )cpp",
2774       R"txt(
2775 *: TranslationUnit
2776 `-SimpleDeclaration
2777   |-auto
2778   |-SimpleDeclarator
2779   | |-foo
2780   | `-ParametersAndQualifiers
2781   |   |-(
2782   |   |-)
2783   |   `-TrailingReturnType
2784   |     |-->
2785   |     |-auto
2786   |     `-SimpleDeclarator
2787   |       |-ParenDeclarator
2788   |       | |-(
2789   |       | |-*
2790   |       | `-)
2791   |       `-ParametersAndQualifiers
2792   |         |-(
2793   |         |-SimpleDeclaration
2794   |         | `-int
2795   |         |-)
2796   |         `-TrailingReturnType
2797   |           |-->
2798   |           |-double
2799   |           `-SimpleDeclarator
2800   |             `-*
2801   `-;
2802 )txt"));
2803 }
2804 
2805 TEST_P(SyntaxTreeTest, MemberPointers) {
2806   if (!GetParam().isCXX()) {
2807     return;
2808   }
2809   EXPECT_TRUE(treeDumpEqual(
2810       R"cpp(
2811 struct X {};
2812 int X::* a;
2813 const int X::* b;
2814 )cpp",
2815       R"txt(
2816 *: TranslationUnit
2817 |-SimpleDeclaration
2818 | |-struct
2819 | |-X
2820 | |-{
2821 | |-}
2822 | `-;
2823 |-SimpleDeclaration
2824 | |-int
2825 | |-SimpleDeclarator
2826 | | |-MemberPointer
2827 | | | |-X
2828 | | | |-::
2829 | | | `-*
2830 | | `-a
2831 | `-;
2832 `-SimpleDeclaration
2833   |-const
2834   |-int
2835   |-SimpleDeclarator
2836   | |-MemberPointer
2837   | | |-X
2838   | | |-::
2839   | | `-*
2840   | `-b
2841   `-;
2842 )txt"));
2843 }
2844 
2845 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
2846   EXPECT_TRUE(treeDumpEqual(
2847       R"cpp(
2848 void x(char a, short (*b)(int));
2849 )cpp",
2850       R"txt(
2851 *: TranslationUnit
2852 `-SimpleDeclaration
2853   |-void
2854   |-SimpleDeclarator
2855   | |-x
2856   | `-ParametersAndQualifiers
2857   |   |-(
2858   |   |-SimpleDeclaration
2859   |   | |-char
2860   |   | `-SimpleDeclarator
2861   |   |   `-a
2862   |   |-,
2863   |   |-SimpleDeclaration
2864   |   | |-short
2865   |   | `-SimpleDeclarator
2866   |   |   |-ParenDeclarator
2867   |   |   | |-(
2868   |   |   | |-*
2869   |   |   | |-b
2870   |   |   | `-)
2871   |   |   `-ParametersAndQualifiers
2872   |   |     |-(
2873   |   |     |-SimpleDeclaration
2874   |   |     | `-int
2875   |   |     `-)
2876   |   `-)
2877   `-;
2878 )txt"));
2879 }
2880 
2881 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
2882   EXPECT_TRUE(treeDumpEqual(
2883       R"cpp(
2884 void x(char a, short (*b)(int), long (**c)(long long));
2885 )cpp",
2886       R"txt(
2887 *: TranslationUnit
2888 `-SimpleDeclaration
2889   |-void
2890   |-SimpleDeclarator
2891   | |-x
2892   | `-ParametersAndQualifiers
2893   |   |-(
2894   |   |-SimpleDeclaration
2895   |   | |-char
2896   |   | `-SimpleDeclarator
2897   |   |   `-a
2898   |   |-,
2899   |   |-SimpleDeclaration
2900   |   | |-short
2901   |   | `-SimpleDeclarator
2902   |   |   |-ParenDeclarator
2903   |   |   | |-(
2904   |   |   | |-*
2905   |   |   | |-b
2906   |   |   | `-)
2907   |   |   `-ParametersAndQualifiers
2908   |   |     |-(
2909   |   |     |-SimpleDeclaration
2910   |   |     | `-int
2911   |   |     `-)
2912   |   |-,
2913   |   |-SimpleDeclaration
2914   |   | |-long
2915   |   | `-SimpleDeclarator
2916   |   |   |-ParenDeclarator
2917   |   |   | |-(
2918   |   |   | |-*
2919   |   |   | |-*
2920   |   |   | |-c
2921   |   |   | `-)
2922   |   |   `-ParametersAndQualifiers
2923   |   |     |-(
2924   |   |     |-SimpleDeclaration
2925   |   |     | |-long
2926   |   |     | `-long
2927   |   |     `-)
2928   |   `-)
2929   `-;
2930 )txt"));
2931 }
2932 
2933 TEST_P(SyntaxTreeTest, Mutations) {
2934   if (!GetParam().isCXX11OrLater()) {
2935     return;
2936   }
2937 
2938   using Transformation = std::function<void(
2939       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
2940   auto CheckTransformation = [this](std::string Input, std::string Expected,
2941                                     Transformation Transform) -> void {
2942     llvm::Annotations Source(Input);
2943     auto *Root = buildTree(Source.code(), GetParam());
2944 
2945     Transform(Source, Root);
2946 
2947     auto Replacements = syntax::computeReplacements(*Arena, *Root);
2948     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
2949     if (!Output) {
2950       ADD_FAILURE() << "could not apply replacements: "
2951                     << llvm::toString(Output.takeError());
2952       return;
2953     }
2954 
2955     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
2956   };
2957 
2958   // Removes the selected statement. Input should have exactly one selected
2959   // range and it should correspond to a single statement.
2960   auto RemoveStatement = [this](const llvm::Annotations &Input,
2961                                 syntax::TranslationUnit *TU) {
2962     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
2963     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
2964     syntax::removeStatement(*Arena, S);
2965     EXPECT_TRUE(S->isDetached());
2966     EXPECT_FALSE(S->isOriginal())
2967         << "node removed from tree cannot be marked as original";
2968   };
2969 
2970   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
2971       Cases = {
2972           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
2973           {"void test() { if (true) [[{}]] else {} }",
2974            "void test() { if (true) ; else {} }"},
2975           {"void test() { [[;]] }", "void test() {  }"}};
2976   for (const auto &C : Cases)
2977     CheckTransformation(C.first, C.second, RemoveStatement);
2978 }
2979 
2980 TEST_P(SyntaxTreeTest, SynthesizedNodes) {
2981   buildTree("", GetParam());
2982 
2983   auto *C = syntax::createPunctuation(*Arena, tok::comma);
2984   ASSERT_NE(C, nullptr);
2985   EXPECT_EQ(C->token()->kind(), tok::comma);
2986   EXPECT_TRUE(C->canModify());
2987   EXPECT_FALSE(C->isOriginal());
2988   EXPECT_TRUE(C->isDetached());
2989 
2990   auto *S = syntax::createEmptyStatement(*Arena);
2991   ASSERT_NE(S, nullptr);
2992   EXPECT_TRUE(S->canModify());
2993   EXPECT_FALSE(S->isOriginal());
2994   EXPECT_TRUE(S->isDetached());
2995 }
2996 
2997 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
2998                         testing::ValuesIn(TestClangConfig::allConfigs()), );
2999 
3000 } // namespace
3001