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