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     | |-IdExpression
489     | | `-UnqualifiedId
490     | |   `-a
491     | |-)
492     | `-EmptyStatement
493     |   `-;
494     `-}
495 )txt"));
496 }
497 
498 TEST_P(SyntaxTreeTest, DeclarationStatement) {
499   EXPECT_TRUE(treeDumpEqual(
500       R"cpp(
501 void test() {
502   int a = 10;
503 }
504 )cpp",
505       R"txt(
506 *: TranslationUnit
507 `-SimpleDeclaration
508   |-void
509   |-SimpleDeclarator
510   | |-test
511   | `-ParametersAndQualifiers
512   |   |-(
513   |   `-)
514   `-CompoundStatement
515     |-{
516     |-DeclarationStatement
517     | |-SimpleDeclaration
518     | | |-int
519     | | `-SimpleDeclarator
520     | |   |-a
521     | |   |-=
522     | |   `-IntegerLiteralExpression
523     | |     `-10
524     | `-;
525     `-}
526 )txt"));
527 }
528 
529 TEST_P(SyntaxTreeTest, Switch) {
530   EXPECT_TRUE(treeDumpEqual(
531       R"cpp(
532 void test() {
533   switch (1) {
534     case 0:
535     default:;
536   }
537 }
538 )cpp",
539       R"txt(
540 *: TranslationUnit
541 `-SimpleDeclaration
542   |-void
543   |-SimpleDeclarator
544   | |-test
545   | `-ParametersAndQualifiers
546   |   |-(
547   |   `-)
548   `-CompoundStatement
549     |-{
550     |-SwitchStatement
551     | |-switch
552     | |-(
553     | |-IntegerLiteralExpression
554     | | `-1
555     | |-)
556     | `-CompoundStatement
557     |   |-{
558     |   |-CaseStatement
559     |   | |-case
560     |   | |-IntegerLiteralExpression
561     |   | | `-0
562     |   | |-:
563     |   | `-DefaultStatement
564     |   |   |-default
565     |   |   |-:
566     |   |   `-EmptyStatement
567     |   |     `-;
568     |   `-}
569     `-}
570 )txt"));
571 }
572 
573 TEST_P(SyntaxTreeTest, While) {
574   EXPECT_TRUE(treeDumpEqual(
575       R"cpp(
576 void test() {
577   while (1) { continue; break; }
578 }
579 )cpp",
580       R"txt(
581 *: TranslationUnit
582 `-SimpleDeclaration
583   |-void
584   |-SimpleDeclarator
585   | |-test
586   | `-ParametersAndQualifiers
587   |   |-(
588   |   `-)
589   `-CompoundStatement
590     |-{
591     |-WhileStatement
592     | |-while
593     | |-(
594     | |-IntegerLiteralExpression
595     | | `-1
596     | |-)
597     | `-CompoundStatement
598     |   |-{
599     |   |-ContinueStatement
600     |   | |-continue
601     |   | `-;
602     |   |-BreakStatement
603     |   | |-break
604     |   | `-;
605     |   `-}
606     `-}
607 )txt"));
608 }
609 
610 TEST_P(SyntaxTreeTest, UnhandledStatement) {
611   // Unhandled statements should end up as 'unknown statement'.
612   // This example uses a 'label statement', which does not yet have a syntax
613   // counterpart.
614   EXPECT_TRUE(treeDumpEqual(
615       R"cpp(
616 int main() {
617   foo: return 100;
618 }
619 )cpp",
620       R"txt(
621 *: TranslationUnit
622 `-SimpleDeclaration
623   |-int
624   |-SimpleDeclarator
625   | |-main
626   | `-ParametersAndQualifiers
627   |   |-(
628   |   `-)
629   `-CompoundStatement
630     |-{
631     |-UnknownStatement
632     | |-foo
633     | |-:
634     | `-ReturnStatement
635     |   |-return
636     |   |-IntegerLiteralExpression
637     |   | `-100
638     |   `-;
639     `-}
640 )txt"));
641 }
642 
643 TEST_P(SyntaxTreeTest, Expressions) {
644   // expressions should be wrapped in 'ExpressionStatement' when they appear
645   // in a statement position.
646   EXPECT_TRUE(treeDumpEqual(
647       R"cpp(
648 void test() {
649   test();
650   if (1) test(); else test();
651 }
652 )cpp",
653       R"txt(
654 *: TranslationUnit
655 `-SimpleDeclaration
656   |-void
657   |-SimpleDeclarator
658   | |-test
659   | `-ParametersAndQualifiers
660   |   |-(
661   |   `-)
662   `-CompoundStatement
663     |-{
664     |-ExpressionStatement
665     | |-UnknownExpression
666     | | |-IdExpression
667     | | | `-UnqualifiedId
668     | | |   `-test
669     | | |-(
670     | | `-)
671     | `-;
672     |-IfStatement
673     | |-if
674     | |-(
675     | |-IntegerLiteralExpression
676     | | `-1
677     | |-)
678     | |-ExpressionStatement
679     | | |-UnknownExpression
680     | | | |-IdExpression
681     | | | | `-UnqualifiedId
682     | | | |   `-test
683     | | | |-(
684     | | | `-)
685     | | `-;
686     | |-else
687     | `-ExpressionStatement
688     |   |-UnknownExpression
689     |   | |-IdExpression
690     |   | | `-UnqualifiedId
691     |   | |   `-test
692     |   | |-(
693     |   | `-)
694     |   `-;
695     `-}
696 )txt"));
697 }
698 
699 TEST_P(SyntaxTreeTest, UnqualifiedId) {
700   if (!GetParam().isCXX()) {
701     return;
702   }
703   EXPECT_TRUE(treeDumpEqual(
704       R"cpp(
705 struct X {
706   // TODO: Expose `id-expression` from `Declarator`
707   friend X operator+(const X&, const X&);
708   operator int();
709 };
710 template<typename T>
711 void f(T&);
712 void test(X x) {
713   x;                      // identifier
714   operator+(x, x);        // operator-function-id
715   f<X>(x);                // template-id
716   // TODO: Expose `id-expression` from `MemberExpr`
717   x.operator int();       // conversion-funtion-id
718   x.~X();                 // ~type-name
719 }
720 )cpp",
721       R"txt(
722 *: TranslationUnit
723 |-SimpleDeclaration
724 | |-struct
725 | |-X
726 | |-{
727 | |-UnknownDeclaration
728 | | `-SimpleDeclaration
729 | |   |-friend
730 | |   |-X
731 | |   |-SimpleDeclarator
732 | |   | |-operator
733 | |   | |-+
734 | |   | `-ParametersAndQualifiers
735 | |   |   |-(
736 | |   |   |-SimpleDeclaration
737 | |   |   | |-const
738 | |   |   | |-X
739 | |   |   | `-SimpleDeclarator
740 | |   |   |   `-&
741 | |   |   |-,
742 | |   |   |-SimpleDeclaration
743 | |   |   | |-const
744 | |   |   | |-X
745 | |   |   | `-SimpleDeclarator
746 | |   |   |   `-&
747 | |   |   `-)
748 | |   `-;
749 | |-SimpleDeclaration
750 | | |-SimpleDeclarator
751 | | | |-operator
752 | | | |-int
753 | | | `-ParametersAndQualifiers
754 | | |   |-(
755 | | |   `-)
756 | | `-;
757 | |-}
758 | `-;
759 |-TemplateDeclaration
760 | |-template
761 | |-<
762 | |-UnknownDeclaration
763 | | |-typename
764 | | `-T
765 | |->
766 | `-SimpleDeclaration
767 |   |-void
768 |   |-SimpleDeclarator
769 |   | |-f
770 |   | `-ParametersAndQualifiers
771 |   |   |-(
772 |   |   |-SimpleDeclaration
773 |   |   | |-T
774 |   |   | `-SimpleDeclarator
775 |   |   |   `-&
776 |   |   `-)
777 |   `-;
778 `-SimpleDeclaration
779   |-void
780   |-SimpleDeclarator
781   | |-test
782   | `-ParametersAndQualifiers
783   |   |-(
784   |   |-SimpleDeclaration
785   |   | |-X
786   |   | `-SimpleDeclarator
787   |   |   `-x
788   |   `-)
789   `-CompoundStatement
790     |-{
791     |-ExpressionStatement
792     | |-IdExpression
793     | | `-UnqualifiedId
794     | |   `-x
795     | `-;
796     |-ExpressionStatement
797     | |-UnknownExpression
798     | | |-IdExpression
799     | | | `-UnqualifiedId
800     | | |   |-operator
801     | | |   `-+
802     | | |-(
803     | | |-IdExpression
804     | | | `-UnqualifiedId
805     | | |   `-x
806     | | |-,
807     | | |-IdExpression
808     | | | `-UnqualifiedId
809     | | |   `-x
810     | | `-)
811     | `-;
812     |-ExpressionStatement
813     | |-UnknownExpression
814     | | |-IdExpression
815     | | | `-UnqualifiedId
816     | | |   |-f
817     | | |   |-<
818     | | |   |-X
819     | | |   `->
820     | | |-(
821     | | |-IdExpression
822     | | | `-UnqualifiedId
823     | | |   `-x
824     | | `-)
825     | `-;
826     |-ExpressionStatement
827     | |-UnknownExpression
828     | | |-UnknownExpression
829     | | | |-IdExpression
830     | | | | `-UnqualifiedId
831     | | | |   `-x
832     | | | |-.
833     | | | |-operator
834     | | | `-int
835     | | |-(
836     | | `-)
837     | `-;
838     |-ExpressionStatement
839     | |-UnknownExpression
840     | | |-UnknownExpression
841     | | | |-IdExpression
842     | | | | `-UnqualifiedId
843     | | | |   `-x
844     | | | |-.
845     | | | |-~
846     | | | `-X
847     | | |-(
848     | | `-)
849     | `-;
850     `-}
851 )txt"));
852 }
853 
854 TEST_P(SyntaxTreeTest, UnqualifiedIdCxx11OrLater) {
855   if (!GetParam().isCXX11OrLater()) {
856     return;
857   }
858   EXPECT_TRUE(treeDumpEqual(
859       R"cpp(
860 struct X { };
861 unsigned operator "" _w(long long unsigned);
862 void test(X x) {
863   operator "" _w(1llu);   // literal-operator-id
864   // TODO: Expose `id-expression` from `MemberExpr`
865   x.~decltype(x)();       // ~decltype-specifier
866 }
867 )cpp",
868       R"txt(
869 *: TranslationUnit
870 |-SimpleDeclaration
871 | |-struct
872 | |-X
873 | |-{
874 | |-}
875 | `-;
876 |-SimpleDeclaration
877 | |-unsigned
878 | |-SimpleDeclarator
879 | | |-operator
880 | | |-""
881 | | |-_w
882 | | `-ParametersAndQualifiers
883 | |   |-(
884 | |   |-SimpleDeclaration
885 | |   | |-long
886 | |   | |-long
887 | |   | `-unsigned
888 | |   `-)
889 | `-;
890 `-SimpleDeclaration
891   |-void
892   |-SimpleDeclarator
893   | |-test
894   | `-ParametersAndQualifiers
895   |   |-(
896   |   |-SimpleDeclaration
897   |   | |-X
898   |   | `-SimpleDeclarator
899   |   |   `-x
900   |   `-)
901   `-CompoundStatement
902     |-{
903     |-ExpressionStatement
904     | |-UnknownExpression
905     | | |-IdExpression
906     | | | `-UnqualifiedId
907     | | |   |-operator
908     | | |   |-""
909     | | |   `-_w
910     | | |-(
911     | | |-IntegerLiteralExpression
912     | | | `-1llu
913     | | `-)
914     | `-;
915     |-ExpressionStatement
916     | |-UnknownExpression
917     | | |-UnknownExpression
918     | | | |-IdExpression
919     | | | | `-UnqualifiedId
920     | | | |   `-x
921     | | | |-.
922     | | | `-~
923     | | |-decltype
924     | | |-(
925     | | |-x
926     | | |-)
927     | | |-(
928     | | `-)
929     | `-;
930     `-}
931 )txt"));
932 }
933 
934 TEST_P(SyntaxTreeTest, QualifiedId) {
935   if (!GetParam().isCXX()) {
936     return;
937   }
938   EXPECT_TRUE(treeDumpEqual(
939       R"cpp(
940 namespace a {
941   struct S {
942     template<typename T>
943     static T f(){}
944   };
945 }
946 void test() {
947   ::              // global-namespace-specifier
948   a::             // namespace-specifier
949   S::             // type-name-specifier
950   f<int>();
951 }
952 )cpp",
953       R"txt(
954 *: TranslationUnit
955 |-NamespaceDefinition
956 | |-namespace
957 | |-a
958 | |-{
959 | |-SimpleDeclaration
960 | | |-struct
961 | | |-S
962 | | |-{
963 | | |-TemplateDeclaration
964 | | | |-template
965 | | | |-<
966 | | | |-UnknownDeclaration
967 | | | | |-typename
968 | | | | `-T
969 | | | |->
970 | | | `-SimpleDeclaration
971 | | |   |-static
972 | | |   |-T
973 | | |   |-SimpleDeclarator
974 | | |   | |-f
975 | | |   | `-ParametersAndQualifiers
976 | | |   |   |-(
977 | | |   |   `-)
978 | | |   `-CompoundStatement
979 | | |     |-{
980 | | |     `-}
981 | | |-}
982 | | `-;
983 | `-}
984 `-SimpleDeclaration
985   |-void
986   |-SimpleDeclarator
987   | |-test
988   | `-ParametersAndQualifiers
989   |   |-(
990   |   `-)
991   `-CompoundStatement
992     |-{
993     |-ExpressionStatement
994     | |-UnknownExpression
995     | | |-IdExpression
996     | | | |-NestedNameSpecifier
997     | | | | |-NameSpecifier
998     | | | | | `-::
999     | | | | |-NameSpecifier
1000     | | | | | |-a
1001     | | | | | `-::
1002     | | | | `-NameSpecifier
1003     | | | |   |-S
1004     | | | |   `-::
1005     | | | `-UnqualifiedId
1006     | | |   |-f
1007     | | |   |-<
1008     | | |   |-int
1009     | | |   `->
1010     | | |-(
1011     | | `-)
1012     | `-;
1013     `-}
1014 )txt"));
1015 }
1016 
1017 TEST_P(SyntaxTreeTest, QualifiedIdWithTemplateKeyword) {
1018   if (!GetParam().isCXX()) {
1019     return;
1020   }
1021   if (GetParam().hasDelayedTemplateParsing()) {
1022     // FIXME: Make this test work on Windows by generating the expected syntax
1023     // tree when `-fdelayed-template-parsing` is active.
1024     return;
1025   }
1026   EXPECT_TRUE(treeDumpEqual(
1027       R"cpp(
1028 struct X {
1029   template<int> static void f();
1030   template<int>
1031   struct Y {
1032     static void f();
1033   };
1034 };
1035 template<typename T> void test() {
1036   // TODO: Expose `id-expression` from `DependentScopeDeclRefExpr`
1037   T::template f<0>();     // nested-name-specifier template unqualified-id
1038   T::template Y<0>::f();  // nested-name-specifier template :: unqualified-id
1039 }
1040 )cpp",
1041       R"txt(
1042 *: TranslationUnit
1043 |-SimpleDeclaration
1044 | |-struct
1045 | |-X
1046 | |-{
1047 | |-TemplateDeclaration
1048 | | |-template
1049 | | |-<
1050 | | |-SimpleDeclaration
1051 | | | `-int
1052 | | |->
1053 | | `-SimpleDeclaration
1054 | |   |-static
1055 | |   |-void
1056 | |   |-SimpleDeclarator
1057 | |   | |-f
1058 | |   | `-ParametersAndQualifiers
1059 | |   |   |-(
1060 | |   |   `-)
1061 | |   `-;
1062 | |-TemplateDeclaration
1063 | | |-template
1064 | | |-<
1065 | | |-SimpleDeclaration
1066 | | | `-int
1067 | | |->
1068 | | `-SimpleDeclaration
1069 | |   |-struct
1070 | |   |-Y
1071 | |   |-{
1072 | |   |-SimpleDeclaration
1073 | |   | |-static
1074 | |   | |-void
1075 | |   | |-SimpleDeclarator
1076 | |   | | |-f
1077 | |   | | `-ParametersAndQualifiers
1078 | |   | |   |-(
1079 | |   | |   `-)
1080 | |   | `-;
1081 | |   |-}
1082 | |   `-;
1083 | |-}
1084 | `-;
1085 `-TemplateDeclaration
1086   |-template
1087   |-<
1088   |-UnknownDeclaration
1089   | |-typename
1090   | `-T
1091   |->
1092   `-SimpleDeclaration
1093     |-void
1094     |-SimpleDeclarator
1095     | |-test
1096     | `-ParametersAndQualifiers
1097     |   |-(
1098     |   `-)
1099     `-CompoundStatement
1100       |-{
1101       |-ExpressionStatement
1102       | |-UnknownExpression
1103       | | |-UnknownExpression
1104       | | | |-T
1105       | | | |-::
1106       | | | |-template
1107       | | | |-f
1108       | | | |-<
1109       | | | |-IntegerLiteralExpression
1110       | | | | `-0
1111       | | | `->
1112       | | |-(
1113       | | `-)
1114       | `-;
1115       |-ExpressionStatement
1116       | |-UnknownExpression
1117       | | |-UnknownExpression
1118       | | | |-T
1119       | | | |-::
1120       | | | |-template
1121       | | | |-Y
1122       | | | |-<
1123       | | | |-IntegerLiteralExpression
1124       | | | | `-0
1125       | | | |->
1126       | | | |-::
1127       | | | `-f
1128       | | |-(
1129       | | `-)
1130       | `-;
1131       `-}
1132 )txt"));
1133 }
1134 
1135 TEST_P(SyntaxTreeTest, QualifiedIdDecltype) {
1136   if (!GetParam().isCXX11OrLater()) {
1137     return;
1138   }
1139   EXPECT_TRUE(treeDumpEqual(
1140       R"cpp(
1141 struct S {
1142   static void f(){}
1143 };
1144 void test(S s) {
1145   decltype(s)::   // decltype-specifier
1146       f();
1147 }
1148 )cpp",
1149       R"txt(
1150 *: TranslationUnit
1151 |-SimpleDeclaration
1152 | |-struct
1153 | |-S
1154 | |-{
1155 | |-SimpleDeclaration
1156 | | |-static
1157 | | |-void
1158 | | |-SimpleDeclarator
1159 | | | |-f
1160 | | | `-ParametersAndQualifiers
1161 | | |   |-(
1162 | | |   `-)
1163 | | `-CompoundStatement
1164 | |   |-{
1165 | |   `-}
1166 | |-}
1167 | `-;
1168 `-SimpleDeclaration
1169   |-void
1170   |-SimpleDeclarator
1171   | |-test
1172   | `-ParametersAndQualifiers
1173   |   |-(
1174   |   |-SimpleDeclaration
1175   |   | |-S
1176   |   | `-SimpleDeclarator
1177   |   |   `-s
1178   |   `-)
1179   `-CompoundStatement
1180     |-{
1181     |-ExpressionStatement
1182     | |-UnknownExpression
1183     | | |-IdExpression
1184     | | | |-NestedNameSpecifier
1185     | | | | `-NameSpecifier
1186     | | | |   |-decltype
1187     | | | |   |-(
1188     | | | |   |-IdExpression
1189     | | | |   | `-UnqualifiedId
1190     | | | |   |   `-s
1191     | | | |   |-)
1192     | | | |   `-::
1193     | | | `-UnqualifiedId
1194     | | |   `-f
1195     | | |-(
1196     | | `-)
1197     | `-;
1198     `-}
1199 )txt"));
1200 }
1201 
1202 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) {
1203   if (!GetParam().isCXX11OrLater()) {
1204     return;
1205   }
1206   EXPECT_TRUE(treeDumpEqual(
1207       R"cpp(
1208 void test() {
1209   nullptr;
1210 }
1211 )cpp",
1212       R"txt(
1213 *: TranslationUnit
1214 `-SimpleDeclaration
1215   |-void
1216   |-SimpleDeclarator
1217   | |-test
1218   | `-ParametersAndQualifiers
1219   |   |-(
1220   |   `-)
1221   `-CompoundStatement
1222     |-{
1223     |-ExpressionStatement
1224     | |-CxxNullPtrExpression
1225     | | `-nullptr
1226     | `-;
1227     `-}
1228 )txt"));
1229 }
1230 
1231 TEST_P(SyntaxTreeTest, IntegerLiteral) {
1232   EXPECT_TRUE(treeDumpEqual(
1233       R"cpp(
1234 void test() {
1235   12;
1236   12u;
1237   12l;
1238   12ul;
1239   014;
1240   0XC;
1241 }
1242 )cpp",
1243       R"txt(
1244 *: TranslationUnit
1245 `-SimpleDeclaration
1246   |-void
1247   |-SimpleDeclarator
1248   | |-test
1249   | `-ParametersAndQualifiers
1250   |   |-(
1251   |   `-)
1252   `-CompoundStatement
1253     |-{
1254     |-ExpressionStatement
1255     | |-IntegerLiteralExpression
1256     | | `-12
1257     | `-;
1258     |-ExpressionStatement
1259     | |-IntegerLiteralExpression
1260     | | `-12u
1261     | `-;
1262     |-ExpressionStatement
1263     | |-IntegerLiteralExpression
1264     | | `-12l
1265     | `-;
1266     |-ExpressionStatement
1267     | |-IntegerLiteralExpression
1268     | | `-12ul
1269     | `-;
1270     |-ExpressionStatement
1271     | |-IntegerLiteralExpression
1272     | | `-014
1273     | `-;
1274     |-ExpressionStatement
1275     | |-IntegerLiteralExpression
1276     | | `-0XC
1277     | `-;
1278     `-}
1279 )txt"));
1280 }
1281 
1282 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) {
1283   if (!GetParam().isCXX11OrLater()) {
1284     return;
1285   }
1286   EXPECT_TRUE(treeDumpEqual(
1287       R"cpp(
1288 void test() {
1289   12ll;
1290   12ull;
1291 }
1292 )cpp",
1293       R"txt(
1294 *: TranslationUnit
1295 `-SimpleDeclaration
1296   |-void
1297   |-SimpleDeclarator
1298   | |-test
1299   | `-ParametersAndQualifiers
1300   |   |-(
1301   |   `-)
1302   `-CompoundStatement
1303     |-{
1304     |-ExpressionStatement
1305     | |-IntegerLiteralExpression
1306     | | `-12ll
1307     | `-;
1308     |-ExpressionStatement
1309     | |-IntegerLiteralExpression
1310     | | `-12ull
1311     | `-;
1312     `-}
1313 )txt"));
1314 }
1315 
1316 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) {
1317   if (!GetParam().isCXX14OrLater()) {
1318     return;
1319   }
1320   EXPECT_TRUE(treeDumpEqual(
1321       R"cpp(
1322 void test() {
1323   0b1100;
1324 }
1325 )cpp",
1326       R"txt(
1327 *: TranslationUnit
1328 `-SimpleDeclaration
1329   |-void
1330   |-SimpleDeclarator
1331   | |-test
1332   | `-ParametersAndQualifiers
1333   |   |-(
1334   |   `-)
1335   `-CompoundStatement
1336     |-{
1337     |-ExpressionStatement
1338     | |-IntegerLiteralExpression
1339     | | `-0b1100
1340     | `-;
1341     `-}
1342 )txt"));
1343 }
1344 
1345 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) {
1346   if (!GetParam().isCXX14OrLater()) {
1347     return;
1348   }
1349   EXPECT_TRUE(treeDumpEqual(
1350       R"cpp(
1351 void test() {
1352   1'2'0ull;
1353 }
1354 )cpp",
1355       R"txt(
1356 *: TranslationUnit
1357 `-SimpleDeclaration
1358   |-void
1359   |-SimpleDeclarator
1360   | |-test
1361   | `-ParametersAndQualifiers
1362   |   |-(
1363   |   `-)
1364   `-CompoundStatement
1365     |-{
1366     |-ExpressionStatement
1367     | |-IntegerLiteralExpression
1368     | | `-1'2'0ull
1369     | `-;
1370     `-}
1371 )txt"));
1372 }
1373 
1374 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) {
1375   EXPECT_TRUE(treeDumpEqual(
1376       R"cpp(
1377 void test(int a) {
1378   a++;
1379   a--;
1380 }
1381 )cpp",
1382       R"txt(
1383 *: TranslationUnit
1384 `-SimpleDeclaration
1385   |-void
1386   |-SimpleDeclarator
1387   | |-test
1388   | `-ParametersAndQualifiers
1389   |   |-(
1390   |   |-SimpleDeclaration
1391   |   | |-int
1392   |   | `-SimpleDeclarator
1393   |   |   `-a
1394   |   `-)
1395   `-CompoundStatement
1396     |-{
1397     |-ExpressionStatement
1398     | |-PostfixUnaryOperatorExpression
1399     | | |-IdExpression
1400     | | | `-UnqualifiedId
1401     | | |   `-a
1402     | | `-++
1403     | `-;
1404     |-ExpressionStatement
1405     | |-PostfixUnaryOperatorExpression
1406     | | |-IdExpression
1407     | | | `-UnqualifiedId
1408     | | |   `-a
1409     | | `---
1410     | `-;
1411     `-}
1412 )txt"));
1413 }
1414 
1415 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) {
1416   EXPECT_TRUE(treeDumpEqual(
1417       R"cpp(
1418 void test(int a, int *ap) {
1419   --a; ++a;
1420   ~a;
1421   -a;
1422   +a;
1423   &a;
1424   *ap;
1425   !a;
1426   __real a; __imag a;
1427 }
1428 )cpp",
1429       R"txt(
1430 *: TranslationUnit
1431 `-SimpleDeclaration
1432   |-void
1433   |-SimpleDeclarator
1434   | |-test
1435   | `-ParametersAndQualifiers
1436   |   |-(
1437   |   |-SimpleDeclaration
1438   |   | |-int
1439   |   | `-SimpleDeclarator
1440   |   |   `-a
1441   |   |-,
1442   |   |-SimpleDeclaration
1443   |   | |-int
1444   |   | `-SimpleDeclarator
1445   |   |   |-*
1446   |   |   `-ap
1447   |   `-)
1448   `-CompoundStatement
1449     |-{
1450     |-ExpressionStatement
1451     | |-PrefixUnaryOperatorExpression
1452     | | |---
1453     | | `-IdExpression
1454     | |   `-UnqualifiedId
1455     | |     `-a
1456     | `-;
1457     |-ExpressionStatement
1458     | |-PrefixUnaryOperatorExpression
1459     | | |-++
1460     | | `-IdExpression
1461     | |   `-UnqualifiedId
1462     | |     `-a
1463     | `-;
1464     |-ExpressionStatement
1465     | |-PrefixUnaryOperatorExpression
1466     | | |-~
1467     | | `-IdExpression
1468     | |   `-UnqualifiedId
1469     | |     `-a
1470     | `-;
1471     |-ExpressionStatement
1472     | |-PrefixUnaryOperatorExpression
1473     | | |--
1474     | | `-IdExpression
1475     | |   `-UnqualifiedId
1476     | |     `-a
1477     | `-;
1478     |-ExpressionStatement
1479     | |-PrefixUnaryOperatorExpression
1480     | | |-+
1481     | | `-IdExpression
1482     | |   `-UnqualifiedId
1483     | |     `-a
1484     | `-;
1485     |-ExpressionStatement
1486     | |-PrefixUnaryOperatorExpression
1487     | | |-&
1488     | | `-IdExpression
1489     | |   `-UnqualifiedId
1490     | |     `-a
1491     | `-;
1492     |-ExpressionStatement
1493     | |-PrefixUnaryOperatorExpression
1494     | | |-*
1495     | | `-IdExpression
1496     | |   `-UnqualifiedId
1497     | |     `-ap
1498     | `-;
1499     |-ExpressionStatement
1500     | |-PrefixUnaryOperatorExpression
1501     | | |-!
1502     | | `-IdExpression
1503     | |   `-UnqualifiedId
1504     | |     `-a
1505     | `-;
1506     |-ExpressionStatement
1507     | |-PrefixUnaryOperatorExpression
1508     | | |-__real
1509     | | `-IdExpression
1510     | |   `-UnqualifiedId
1511     | |     `-a
1512     | `-;
1513     |-ExpressionStatement
1514     | |-PrefixUnaryOperatorExpression
1515     | | |-__imag
1516     | | `-IdExpression
1517     | |   `-UnqualifiedId
1518     | |     `-a
1519     | `-;
1520     `-}
1521 )txt"));
1522 }
1523 
1524 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) {
1525   if (!GetParam().isCXX()) {
1526     return;
1527   }
1528   EXPECT_TRUE(treeDumpEqual(
1529       R"cpp(
1530 void test(int a, bool b) {
1531   compl a;
1532   not b;
1533 }
1534 )cpp",
1535       R"txt(
1536 *: TranslationUnit
1537 `-SimpleDeclaration
1538   |-void
1539   |-SimpleDeclarator
1540   | |-test
1541   | `-ParametersAndQualifiers
1542   |   |-(
1543   |   |-SimpleDeclaration
1544   |   | |-int
1545   |   | `-SimpleDeclarator
1546   |   |   `-a
1547   |   |-,
1548   |   |-SimpleDeclaration
1549   |   | |-bool
1550   |   | `-SimpleDeclarator
1551   |   |   `-b
1552   |   `-)
1553   `-CompoundStatement
1554     |-{
1555     |-ExpressionStatement
1556     | |-PrefixUnaryOperatorExpression
1557     | | |-compl
1558     | | `-IdExpression
1559     | |   `-UnqualifiedId
1560     | |     `-a
1561     | `-;
1562     |-ExpressionStatement
1563     | |-PrefixUnaryOperatorExpression
1564     | | |-not
1565     | | `-IdExpression
1566     | |   `-UnqualifiedId
1567     | |     `-b
1568     | `-;
1569     `-}
1570 )txt"));
1571 }
1572 
1573 TEST_P(SyntaxTreeTest, BinaryOperator) {
1574   EXPECT_TRUE(treeDumpEqual(
1575       R"cpp(
1576 void test(int a) {
1577   1 - 2;
1578   1 == 2;
1579   a = 1;
1580   a <<= 1;
1581   1 || 0;
1582   1 & 2;
1583   a ^= 3;
1584 }
1585 )cpp",
1586       R"txt(
1587 *: TranslationUnit
1588 `-SimpleDeclaration
1589   |-void
1590   |-SimpleDeclarator
1591   | |-test
1592   | `-ParametersAndQualifiers
1593   |   |-(
1594   |   |-SimpleDeclaration
1595   |   | |-int
1596   |   | `-SimpleDeclarator
1597   |   |   `-a
1598   |   `-)
1599   `-CompoundStatement
1600     |-{
1601     |-ExpressionStatement
1602     | |-BinaryOperatorExpression
1603     | | |-IntegerLiteralExpression
1604     | | | `-1
1605     | | |--
1606     | | `-IntegerLiteralExpression
1607     | |   `-2
1608     | `-;
1609     |-ExpressionStatement
1610     | |-BinaryOperatorExpression
1611     | | |-IntegerLiteralExpression
1612     | | | `-1
1613     | | |-==
1614     | | `-IntegerLiteralExpression
1615     | |   `-2
1616     | `-;
1617     |-ExpressionStatement
1618     | |-BinaryOperatorExpression
1619     | | |-IdExpression
1620     | | | `-UnqualifiedId
1621     | | |   `-a
1622     | | |-=
1623     | | `-IntegerLiteralExpression
1624     | |   `-1
1625     | `-;
1626     |-ExpressionStatement
1627     | |-BinaryOperatorExpression
1628     | | |-IdExpression
1629     | | | `-UnqualifiedId
1630     | | |   `-a
1631     | | |-<<=
1632     | | `-IntegerLiteralExpression
1633     | |   `-1
1634     | `-;
1635     |-ExpressionStatement
1636     | |-BinaryOperatorExpression
1637     | | |-IntegerLiteralExpression
1638     | | | `-1
1639     | | |-||
1640     | | `-IntegerLiteralExpression
1641     | |   `-0
1642     | `-;
1643     |-ExpressionStatement
1644     | |-BinaryOperatorExpression
1645     | | |-IntegerLiteralExpression
1646     | | | `-1
1647     | | |-&
1648     | | `-IntegerLiteralExpression
1649     | |   `-2
1650     | `-;
1651     |-ExpressionStatement
1652     | |-BinaryOperatorExpression
1653     | | |-IdExpression
1654     | | | `-UnqualifiedId
1655     | | |   `-a
1656     | | |-^=
1657     | | `-IntegerLiteralExpression
1658     | |   `-3
1659     | `-;
1660     `-}
1661 )txt"));
1662 }
1663 
1664 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) {
1665   if (!GetParam().isCXX()) {
1666     return;
1667   }
1668   EXPECT_TRUE(treeDumpEqual(
1669       R"cpp(
1670 void test(int a) {
1671   true || false;
1672   true or false;
1673   1 bitand 2;
1674   a xor_eq 3;
1675 }
1676 )cpp",
1677       R"txt(
1678 *: TranslationUnit
1679 `-SimpleDeclaration
1680   |-void
1681   |-SimpleDeclarator
1682   | |-test
1683   | `-ParametersAndQualifiers
1684   |   |-(
1685   |   |-SimpleDeclaration
1686   |   | |-int
1687   |   | `-SimpleDeclarator
1688   |   |   `-a
1689   |   `-)
1690   `-CompoundStatement
1691     |-{
1692     |-ExpressionStatement
1693     | |-BinaryOperatorExpression
1694     | | |-UnknownExpression
1695     | | | `-true
1696     | | |-||
1697     | | `-UnknownExpression
1698     | |   `-false
1699     | `-;
1700     |-ExpressionStatement
1701     | |-BinaryOperatorExpression
1702     | | |-UnknownExpression
1703     | | | `-true
1704     | | |-or
1705     | | `-UnknownExpression
1706     | |   `-false
1707     | `-;
1708     |-ExpressionStatement
1709     | |-BinaryOperatorExpression
1710     | | |-IntegerLiteralExpression
1711     | | | `-1
1712     | | |-bitand
1713     | | `-IntegerLiteralExpression
1714     | |   `-2
1715     | `-;
1716     |-ExpressionStatement
1717     | |-BinaryOperatorExpression
1718     | | |-IdExpression
1719     | | | `-UnqualifiedId
1720     | | |   `-a
1721     | | |-xor_eq
1722     | | `-IntegerLiteralExpression
1723     | |   `-3
1724     | `-;
1725     `-}
1726 )txt"));
1727 }
1728 
1729 TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
1730   EXPECT_TRUE(treeDumpEqual(
1731       R"cpp(
1732 void test(int a, int b) {
1733   (1 + 2) * (4 / 2);
1734   a + b + 42;
1735   a = b = 42;
1736   a + b * 4 + 2;
1737   a % 2 + b * 42;
1738 }
1739 )cpp",
1740       R"txt(
1741 *: TranslationUnit
1742 `-SimpleDeclaration
1743   |-void
1744   |-SimpleDeclarator
1745   | |-test
1746   | `-ParametersAndQualifiers
1747   |   |-(
1748   |   |-SimpleDeclaration
1749   |   | |-int
1750   |   | `-SimpleDeclarator
1751   |   |   `-a
1752   |   |-,
1753   |   |-SimpleDeclaration
1754   |   | |-int
1755   |   | `-SimpleDeclarator
1756   |   |   `-b
1757   |   `-)
1758   `-CompoundStatement
1759     |-{
1760     |-ExpressionStatement
1761     | |-BinaryOperatorExpression
1762     | | |-UnknownExpression
1763     | | | |-(
1764     | | | |-BinaryOperatorExpression
1765     | | | | |-IntegerLiteralExpression
1766     | | | | | `-1
1767     | | | | |-+
1768     | | | | `-IntegerLiteralExpression
1769     | | | |   `-2
1770     | | | `-)
1771     | | |-*
1772     | | `-UnknownExpression
1773     | |   |-(
1774     | |   |-BinaryOperatorExpression
1775     | |   | |-IntegerLiteralExpression
1776     | |   | | `-4
1777     | |   | |-/
1778     | |   | `-IntegerLiteralExpression
1779     | |   |   `-2
1780     | |   `-)
1781     | `-;
1782     |-ExpressionStatement
1783     | |-BinaryOperatorExpression
1784     | | |-BinaryOperatorExpression
1785     | | | |-IdExpression
1786     | | | | `-UnqualifiedId
1787     | | | |   `-a
1788     | | | |-+
1789     | | | `-IdExpression
1790     | | |   `-UnqualifiedId
1791     | | |     `-b
1792     | | |-+
1793     | | `-IntegerLiteralExpression
1794     | |   `-42
1795     | `-;
1796     |-ExpressionStatement
1797     | |-BinaryOperatorExpression
1798     | | |-IdExpression
1799     | | | `-UnqualifiedId
1800     | | |   `-a
1801     | | |-=
1802     | | `-BinaryOperatorExpression
1803     | |   |-IdExpression
1804     | |   | `-UnqualifiedId
1805     | |   |   `-b
1806     | |   |-=
1807     | |   `-IntegerLiteralExpression
1808     | |     `-42
1809     | `-;
1810     |-ExpressionStatement
1811     | |-BinaryOperatorExpression
1812     | | |-BinaryOperatorExpression
1813     | | | |-IdExpression
1814     | | | | `-UnqualifiedId
1815     | | | |   `-a
1816     | | | |-+
1817     | | | `-BinaryOperatorExpression
1818     | | |   |-IdExpression
1819     | | |   | `-UnqualifiedId
1820     | | |   |   `-b
1821     | | |   |-*
1822     | | |   `-IntegerLiteralExpression
1823     | | |     `-4
1824     | | |-+
1825     | | `-IntegerLiteralExpression
1826     | |   `-2
1827     | `-;
1828     |-ExpressionStatement
1829     | |-BinaryOperatorExpression
1830     | | |-BinaryOperatorExpression
1831     | | | |-IdExpression
1832     | | | | `-UnqualifiedId
1833     | | | |   `-a
1834     | | | |-%
1835     | | | `-IntegerLiteralExpression
1836     | | |   `-2
1837     | | |-+
1838     | | `-BinaryOperatorExpression
1839     | |   |-IdExpression
1840     | |   | `-UnqualifiedId
1841     | |   |   `-b
1842     | |   |-*
1843     | |   `-IntegerLiteralExpression
1844     | |     `-42
1845     | `-;
1846     `-}
1847 )txt"));
1848 }
1849 
1850 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
1851   if (!GetParam().isCXX()) {
1852     return;
1853   }
1854   EXPECT_TRUE(treeDumpEqual(
1855       R"cpp(
1856 struct X {
1857   X& operator=(const X&);
1858   friend X operator+(X, const X&);
1859   friend bool operator<(const X&, const X&);
1860 };
1861 void test(X x, X y) {
1862   x = y;
1863   x + y;
1864   x < y;
1865 }
1866 )cpp",
1867       R"txt(
1868 *: TranslationUnit
1869 |-SimpleDeclaration
1870 | |-struct
1871 | |-X
1872 | |-{
1873 | |-SimpleDeclaration
1874 | | |-X
1875 | | |-SimpleDeclarator
1876 | | | |-&
1877 | | | |-operator
1878 | | | |-=
1879 | | | `-ParametersAndQualifiers
1880 | | |   |-(
1881 | | |   |-SimpleDeclaration
1882 | | |   | |-const
1883 | | |   | |-X
1884 | | |   | `-SimpleDeclarator
1885 | | |   |   `-&
1886 | | |   `-)
1887 | | `-;
1888 | |-UnknownDeclaration
1889 | | `-SimpleDeclaration
1890 | |   |-friend
1891 | |   |-X
1892 | |   |-SimpleDeclarator
1893 | |   | |-operator
1894 | |   | |-+
1895 | |   | `-ParametersAndQualifiers
1896 | |   |   |-(
1897 | |   |   |-SimpleDeclaration
1898 | |   |   | `-X
1899 | |   |   |-,
1900 | |   |   |-SimpleDeclaration
1901 | |   |   | |-const
1902 | |   |   | |-X
1903 | |   |   | `-SimpleDeclarator
1904 | |   |   |   `-&
1905 | |   |   `-)
1906 | |   `-;
1907 | |-UnknownDeclaration
1908 | | `-SimpleDeclaration
1909 | |   |-friend
1910 | |   |-bool
1911 | |   |-SimpleDeclarator
1912 | |   | |-operator
1913 | |   | |-<
1914 | |   | `-ParametersAndQualifiers
1915 | |   |   |-(
1916 | |   |   |-SimpleDeclaration
1917 | |   |   | |-const
1918 | |   |   | |-X
1919 | |   |   | `-SimpleDeclarator
1920 | |   |   |   `-&
1921 | |   |   |-,
1922 | |   |   |-SimpleDeclaration
1923 | |   |   | |-const
1924 | |   |   | |-X
1925 | |   |   | `-SimpleDeclarator
1926 | |   |   |   `-&
1927 | |   |   `-)
1928 | |   `-;
1929 | |-}
1930 | `-;
1931 `-SimpleDeclaration
1932   |-void
1933   |-SimpleDeclarator
1934   | |-test
1935   | `-ParametersAndQualifiers
1936   |   |-(
1937   |   |-SimpleDeclaration
1938   |   | |-X
1939   |   | `-SimpleDeclarator
1940   |   |   `-x
1941   |   |-,
1942   |   |-SimpleDeclaration
1943   |   | |-X
1944   |   | `-SimpleDeclarator
1945   |   |   `-y
1946   |   `-)
1947   `-CompoundStatement
1948     |-{
1949     |-ExpressionStatement
1950     | |-BinaryOperatorExpression
1951     | | |-IdExpression
1952     | | | `-UnqualifiedId
1953     | | |   `-x
1954     | | |-IdExpression
1955     | | | `-UnqualifiedId
1956     | | |   `-=
1957     | | `-IdExpression
1958     | |   `-UnqualifiedId
1959     | |     `-y
1960     | `-;
1961     |-ExpressionStatement
1962     | |-BinaryOperatorExpression
1963     | | |-UnknownExpression
1964     | | | `-IdExpression
1965     | | |   `-UnqualifiedId
1966     | | |     `-x
1967     | | |-IdExpression
1968     | | | `-UnqualifiedId
1969     | | |   `-+
1970     | | `-IdExpression
1971     | |   `-UnqualifiedId
1972     | |     `-y
1973     | `-;
1974     |-ExpressionStatement
1975     | |-BinaryOperatorExpression
1976     | | |-IdExpression
1977     | | | `-UnqualifiedId
1978     | | |   `-x
1979     | | |-IdExpression
1980     | | | `-UnqualifiedId
1981     | | |   `-<
1982     | | `-IdExpression
1983     | |   `-UnqualifiedId
1984     | |     `-y
1985     | `-;
1986     `-}
1987 )txt"));
1988 }
1989 
1990 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
1991   EXPECT_TRUE(treeDumpEqual(
1992       R"cpp(
1993 int *a, b;
1994 int *c, d;
1995 )cpp",
1996       R"txt(
1997 *: TranslationUnit
1998 |-SimpleDeclaration
1999 | |-int
2000 | |-SimpleDeclarator
2001 | | |-*
2002 | | `-a
2003 | |-,
2004 | |-SimpleDeclarator
2005 | | `-b
2006 | `-;
2007 `-SimpleDeclaration
2008   |-int
2009   |-SimpleDeclarator
2010   | |-*
2011   | `-c
2012   |-,
2013   |-SimpleDeclarator
2014   | `-d
2015   `-;
2016 )txt"));
2017 }
2018 
2019 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2020   EXPECT_TRUE(treeDumpEqual(
2021       R"cpp(
2022 typedef int *a, b;
2023 )cpp",
2024       R"txt(
2025 *: TranslationUnit
2026 `-SimpleDeclaration
2027   |-typedef
2028   |-int
2029   |-SimpleDeclarator
2030   | |-*
2031   | `-a
2032   |-,
2033   |-SimpleDeclarator
2034   | `-b
2035   `-;
2036 )txt"));
2037 }
2038 
2039 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2040   EXPECT_TRUE(treeDumpEqual(
2041       R"cpp(
2042 void foo() {
2043   int *a, b;
2044   typedef int *ta, tb;
2045 }
2046 )cpp",
2047       R"txt(
2048 *: TranslationUnit
2049 `-SimpleDeclaration
2050   |-void
2051   |-SimpleDeclarator
2052   | |-foo
2053   | `-ParametersAndQualifiers
2054   |   |-(
2055   |   `-)
2056   `-CompoundStatement
2057     |-{
2058     |-DeclarationStatement
2059     | |-SimpleDeclaration
2060     | | |-int
2061     | | |-SimpleDeclarator
2062     | | | |-*
2063     | | | `-a
2064     | | |-,
2065     | | `-SimpleDeclarator
2066     | |   `-b
2067     | `-;
2068     |-DeclarationStatement
2069     | |-SimpleDeclaration
2070     | | |-typedef
2071     | | |-int
2072     | | |-SimpleDeclarator
2073     | | | |-*
2074     | | | `-ta
2075     | | |-,
2076     | | `-SimpleDeclarator
2077     | |   `-tb
2078     | `-;
2079     `-}
2080 )txt"));
2081 }
2082 
2083 TEST_P(SyntaxTreeTest, Namespaces) {
2084   if (!GetParam().isCXX()) {
2085     return;
2086   }
2087   EXPECT_TRUE(treeDumpEqual(
2088       R"cpp(
2089 namespace a { namespace b {} }
2090 namespace a::b {}
2091 namespace {}
2092 
2093 namespace foo = a;
2094 )cpp",
2095       R"txt(
2096 *: TranslationUnit
2097 |-NamespaceDefinition
2098 | |-namespace
2099 | |-a
2100 | |-{
2101 | |-NamespaceDefinition
2102 | | |-namespace
2103 | | |-b
2104 | | |-{
2105 | | `-}
2106 | `-}
2107 |-NamespaceDefinition
2108 | |-namespace
2109 | |-a
2110 | |-::
2111 | |-b
2112 | |-{
2113 | `-}
2114 |-NamespaceDefinition
2115 | |-namespace
2116 | |-{
2117 | `-}
2118 `-NamespaceAliasDefinition
2119   |-namespace
2120   |-foo
2121   |-=
2122   |-a
2123   `-;
2124 )txt"));
2125 }
2126 
2127 TEST_P(SyntaxTreeTest, UsingDirective) {
2128   if (!GetParam().isCXX()) {
2129     return;
2130   }
2131   EXPECT_TRUE(treeDumpEqual(
2132       R"cpp(
2133 namespace ns {}
2134 using namespace ::ns;
2135 )cpp",
2136       R"txt(
2137 *: TranslationUnit
2138 |-NamespaceDefinition
2139 | |-namespace
2140 | |-ns
2141 | |-{
2142 | `-}
2143 `-UsingNamespaceDirective
2144   |-using
2145   |-namespace
2146   |-::
2147   |-ns
2148   `-;
2149 )txt"));
2150 }
2151 
2152 TEST_P(SyntaxTreeTest, UsingDeclaration) {
2153   if (!GetParam().isCXX()) {
2154     return;
2155   }
2156   EXPECT_TRUE(treeDumpEqual(
2157       R"cpp(
2158 namespace ns { int a; }
2159 using ns::a;
2160 )cpp",
2161       R"txt(
2162 *: TranslationUnit
2163 |-NamespaceDefinition
2164 | |-namespace
2165 | |-ns
2166 | |-{
2167 | |-SimpleDeclaration
2168 | | |-int
2169 | | |-SimpleDeclarator
2170 | | | `-a
2171 | | `-;
2172 | `-}
2173 `-UsingDeclaration
2174   |-using
2175   |-ns
2176   |-::
2177   |-a
2178   `-;
2179 )txt"));
2180 }
2181 
2182 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
2183   // Free-standing classes, must live inside a SimpleDeclaration.
2184   EXPECT_TRUE(treeDumpEqual(
2185       R"cpp(
2186 struct X;
2187 struct X {};
2188 
2189 struct Y *y1;
2190 struct Y {} *y2;
2191 
2192 struct {} *a1;
2193 )cpp",
2194       R"txt(
2195 *: TranslationUnit
2196 |-SimpleDeclaration
2197 | |-struct
2198 | |-X
2199 | `-;
2200 |-SimpleDeclaration
2201 | |-struct
2202 | |-X
2203 | |-{
2204 | |-}
2205 | `-;
2206 |-SimpleDeclaration
2207 | |-struct
2208 | |-Y
2209 | |-SimpleDeclarator
2210 | | |-*
2211 | | `-y1
2212 | `-;
2213 |-SimpleDeclaration
2214 | |-struct
2215 | |-Y
2216 | |-{
2217 | |-}
2218 | |-SimpleDeclarator
2219 | | |-*
2220 | | `-y2
2221 | `-;
2222 `-SimpleDeclaration
2223   |-struct
2224   |-{
2225   |-}
2226   |-SimpleDeclarator
2227   | |-*
2228   | `-a1
2229   `-;
2230 )txt"));
2231 }
2232 
2233 TEST_P(SyntaxTreeTest, Templates) {
2234   if (!GetParam().isCXX()) {
2235     return;
2236   }
2237   if (GetParam().hasDelayedTemplateParsing()) {
2238     // FIXME: Make this test work on Windows by generating the expected syntax
2239     // tree when `-fdelayed-template-parsing` is active.
2240     return;
2241   }
2242   EXPECT_TRUE(treeDumpEqual(
2243       R"cpp(
2244 template <class T> struct cls {};
2245 template <class T> int var = 10;
2246 template <class T> int fun() {}
2247 )cpp",
2248       R"txt(
2249 *: TranslationUnit
2250 |-TemplateDeclaration
2251 | |-template
2252 | |-<
2253 | |-UnknownDeclaration
2254 | | |-class
2255 | | `-T
2256 | |->
2257 | `-SimpleDeclaration
2258 |   |-struct
2259 |   |-cls
2260 |   |-{
2261 |   |-}
2262 |   `-;
2263 |-TemplateDeclaration
2264 | |-template
2265 | |-<
2266 | |-UnknownDeclaration
2267 | | |-class
2268 | | `-T
2269 | |->
2270 | `-SimpleDeclaration
2271 |   |-int
2272 |   |-SimpleDeclarator
2273 |   | |-var
2274 |   | |-=
2275 |   | `-IntegerLiteralExpression
2276 |   |   `-10
2277 |   `-;
2278 `-TemplateDeclaration
2279   |-template
2280   |-<
2281   |-UnknownDeclaration
2282   | |-class
2283   | `-T
2284   |->
2285   `-SimpleDeclaration
2286     |-int
2287     |-SimpleDeclarator
2288     | |-fun
2289     | `-ParametersAndQualifiers
2290     |   |-(
2291     |   `-)
2292     `-CompoundStatement
2293       |-{
2294       `-}
2295 )txt"));
2296 }
2297 
2298 TEST_P(SyntaxTreeTest, NestedTemplates) {
2299   if (!GetParam().isCXX()) {
2300     return;
2301   }
2302   EXPECT_TRUE(treeDumpEqual(
2303       R"cpp(
2304 template <class T>
2305 struct X {
2306   template <class U>
2307   U foo();
2308 };
2309 )cpp",
2310       R"txt(
2311 *: TranslationUnit
2312 `-TemplateDeclaration
2313   |-template
2314   |-<
2315   |-UnknownDeclaration
2316   | |-class
2317   | `-T
2318   |->
2319   `-SimpleDeclaration
2320     |-struct
2321     |-X
2322     |-{
2323     |-TemplateDeclaration
2324     | |-template
2325     | |-<
2326     | |-UnknownDeclaration
2327     | | |-class
2328     | | `-U
2329     | |->
2330     | `-SimpleDeclaration
2331     |   |-U
2332     |   |-SimpleDeclarator
2333     |   | |-foo
2334     |   | `-ParametersAndQualifiers
2335     |   |   |-(
2336     |   |   `-)
2337     |   `-;
2338     |-}
2339     `-;
2340 )txt"));
2341 }
2342 
2343 TEST_P(SyntaxTreeTest, Templates2) {
2344   if (!GetParam().isCXX()) {
2345     return;
2346   }
2347   EXPECT_TRUE(treeDumpEqual(
2348       R"cpp(
2349 template <class T> struct X { struct Y; };
2350 template <class T> struct X<T>::Y {};
2351 )cpp",
2352       R"txt(
2353 *: TranslationUnit
2354 |-TemplateDeclaration
2355 | |-template
2356 | |-<
2357 | |-UnknownDeclaration
2358 | | |-class
2359 | | `-T
2360 | |->
2361 | `-SimpleDeclaration
2362 |   |-struct
2363 |   |-X
2364 |   |-{
2365 |   |-SimpleDeclaration
2366 |   | |-struct
2367 |   | |-Y
2368 |   | `-;
2369 |   |-}
2370 |   `-;
2371 `-TemplateDeclaration
2372   |-template
2373   |-<
2374   |-UnknownDeclaration
2375   | |-class
2376   | `-T
2377   |->
2378   `-SimpleDeclaration
2379     |-struct
2380     |-X
2381     |-<
2382     |-T
2383     |->
2384     |-::
2385     |-Y
2386     |-{
2387     |-}
2388     `-;
2389 )txt"));
2390 }
2391 
2392 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
2393   if (!GetParam().isCXX()) {
2394     return;
2395   }
2396   EXPECT_TRUE(treeDumpEqual(
2397       R"cpp(
2398 template <class T> struct X {
2399   using T::foo;
2400   using typename T::bar;
2401 };
2402 )cpp",
2403       R"txt(
2404 *: TranslationUnit
2405 `-TemplateDeclaration
2406   |-template
2407   |-<
2408   |-UnknownDeclaration
2409   | |-class
2410   | `-T
2411   |->
2412   `-SimpleDeclaration
2413     |-struct
2414     |-X
2415     |-{
2416     |-UsingDeclaration
2417     | |-using
2418     | |-T
2419     | |-::
2420     | |-foo
2421     | `-;
2422     |-UsingDeclaration
2423     | |-using
2424     | |-typename
2425     | |-T
2426     | |-::
2427     | |-bar
2428     | `-;
2429     |-}
2430     `-;
2431 )txt"));
2432 }
2433 
2434 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
2435   if (!GetParam().isCXX()) {
2436     return;
2437   }
2438   EXPECT_TRUE(treeDumpEqual(
2439       R"cpp(
2440 template <class T> struct X {};
2441 template <class T> struct X<T*> {};
2442 template <> struct X<int> {};
2443 
2444 template struct X<double>;
2445 extern template struct X<float>;
2446 )cpp",
2447       R"txt(
2448 *: TranslationUnit
2449 |-TemplateDeclaration
2450 | |-template
2451 | |-<
2452 | |-UnknownDeclaration
2453 | | |-class
2454 | | `-T
2455 | |->
2456 | `-SimpleDeclaration
2457 |   |-struct
2458 |   |-X
2459 |   |-{
2460 |   |-}
2461 |   `-;
2462 |-TemplateDeclaration
2463 | |-template
2464 | |-<
2465 | |-UnknownDeclaration
2466 | | |-class
2467 | | `-T
2468 | |->
2469 | `-SimpleDeclaration
2470 |   |-struct
2471 |   |-X
2472 |   |-<
2473 |   |-T
2474 |   |-*
2475 |   |->
2476 |   |-{
2477 |   |-}
2478 |   `-;
2479 |-TemplateDeclaration
2480 | |-template
2481 | |-<
2482 | |->
2483 | `-SimpleDeclaration
2484 |   |-struct
2485 |   |-X
2486 |   |-<
2487 |   |-int
2488 |   |->
2489 |   |-{
2490 |   |-}
2491 |   `-;
2492 |-ExplicitTemplateInstantiation
2493 | |-template
2494 | `-SimpleDeclaration
2495 |   |-struct
2496 |   |-X
2497 |   |-<
2498 |   |-double
2499 |   |->
2500 |   `-;
2501 `-ExplicitTemplateInstantiation
2502   |-extern
2503   |-template
2504   `-SimpleDeclaration
2505     |-struct
2506     |-X
2507     |-<
2508     |-float
2509     |->
2510     `-;
2511 )txt"));
2512 }
2513 
2514 TEST_P(SyntaxTreeTest, UsingType) {
2515   if (!GetParam().isCXX()) {
2516     return;
2517   }
2518   EXPECT_TRUE(treeDumpEqual(
2519       R"cpp(
2520 using type = int;
2521 )cpp",
2522       R"txt(
2523 *: TranslationUnit
2524 `-TypeAliasDeclaration
2525   |-using
2526   |-type
2527   |-=
2528   |-int
2529   `-;
2530 )txt"));
2531 }
2532 
2533 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
2534   EXPECT_TRUE(treeDumpEqual(
2535       R"cpp(
2536 ;
2537 )cpp",
2538       R"txt(
2539 *: TranslationUnit
2540 `-EmptyDeclaration
2541   `-;
2542 )txt"));
2543 }
2544 
2545 TEST_P(SyntaxTreeTest, StaticAssert) {
2546   if (!GetParam().isCXX11OrLater()) {
2547     return;
2548   }
2549   EXPECT_TRUE(treeDumpEqual(
2550       R"cpp(
2551 static_assert(true, "message");
2552 static_assert(true);
2553 )cpp",
2554       R"txt(
2555 *: TranslationUnit
2556 |-StaticAssertDeclaration
2557 | |-static_assert
2558 | |-(
2559 | |-UnknownExpression
2560 | | `-true
2561 | |-,
2562 | |-UnknownExpression
2563 | | `-"message"
2564 | |-)
2565 | `-;
2566 `-StaticAssertDeclaration
2567   |-static_assert
2568   |-(
2569   |-UnknownExpression
2570   | `-true
2571   |-)
2572   `-;
2573 )txt"));
2574 }
2575 
2576 TEST_P(SyntaxTreeTest, ExternC) {
2577   if (!GetParam().isCXX()) {
2578     return;
2579   }
2580   EXPECT_TRUE(treeDumpEqual(
2581       R"cpp(
2582 extern "C" int a;
2583 extern "C" { int b; int c; }
2584 )cpp",
2585       R"txt(
2586 *: TranslationUnit
2587 |-LinkageSpecificationDeclaration
2588 | |-extern
2589 | |-"C"
2590 | `-SimpleDeclaration
2591 |   |-int
2592 |   |-SimpleDeclarator
2593 |   | `-a
2594 |   `-;
2595 `-LinkageSpecificationDeclaration
2596   |-extern
2597   |-"C"
2598   |-{
2599   |-SimpleDeclaration
2600   | |-int
2601   | |-SimpleDeclarator
2602   | | `-b
2603   | `-;
2604   |-SimpleDeclaration
2605   | |-int
2606   | |-SimpleDeclarator
2607   | | `-c
2608   | `-;
2609   `-}
2610 )txt"));
2611 }
2612 
2613 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
2614   // Some nodes are non-modifiable, they are marked with 'I:'.
2615   EXPECT_TRUE(treeDumpEqual(
2616       R"cpp(
2617 #define HALF_IF if (1+
2618 #define HALF_IF_2 1) {}
2619 void test() {
2620   HALF_IF HALF_IF_2 else {}
2621 })cpp",
2622       R"txt(
2623 *: TranslationUnit
2624 `-SimpleDeclaration
2625   |-void
2626   |-SimpleDeclarator
2627   | |-test
2628   | `-ParametersAndQualifiers
2629   |   |-(
2630   |   `-)
2631   `-CompoundStatement
2632     |-{
2633     |-IfStatement
2634     | |-I: if
2635     | |-I: (
2636     | |-I: BinaryOperatorExpression
2637     | | |-I: IntegerLiteralExpression
2638     | | | `-I: 1
2639     | | |-I: +
2640     | | `-I: IntegerLiteralExpression
2641     | |   `-I: 1
2642     | |-I: )
2643     | |-I: CompoundStatement
2644     | | |-I: {
2645     | | `-I: }
2646     | |-else
2647     | `-CompoundStatement
2648     |   |-{
2649     |   `-}
2650     `-}
2651 )txt"));
2652 }
2653 
2654 TEST_P(SyntaxTreeTest, ModifiableNodes) {
2655   // All nodes can be mutated.
2656   EXPECT_TRUE(treeDumpEqual(
2657       R"cpp(
2658 #define OPEN {
2659 #define CLOSE }
2660 
2661 void test() {
2662   OPEN
2663     1;
2664   CLOSE
2665 
2666   OPEN
2667     2;
2668   }
2669 }
2670 )cpp",
2671       R"txt(
2672 *: TranslationUnit
2673 `-SimpleDeclaration
2674   |-void
2675   |-SimpleDeclarator
2676   | |-test
2677   | `-ParametersAndQualifiers
2678   |   |-(
2679   |   `-)
2680   `-CompoundStatement
2681     |-{
2682     |-CompoundStatement
2683     | |-{
2684     | |-ExpressionStatement
2685     | | |-IntegerLiteralExpression
2686     | | | `-1
2687     | | `-;
2688     | `-}
2689     |-CompoundStatement
2690     | |-{
2691     | |-ExpressionStatement
2692     | | |-IntegerLiteralExpression
2693     | | | `-2
2694     | | `-;
2695     | `-}
2696     `-}
2697 )txt"));
2698 }
2699 
2700 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
2701   EXPECT_TRUE(treeDumpEqual(
2702       R"cpp(
2703 int a[10];
2704 int b[1][2][3];
2705 int c[] = {1,2,3};
2706 )cpp",
2707       R"txt(
2708 *: TranslationUnit
2709 |-SimpleDeclaration
2710 | |-int
2711 | |-SimpleDeclarator
2712 | | |-a
2713 | | `-ArraySubscript
2714 | |   |-[
2715 | |   |-IntegerLiteralExpression
2716 | |   | `-10
2717 | |   `-]
2718 | `-;
2719 |-SimpleDeclaration
2720 | |-int
2721 | |-SimpleDeclarator
2722 | | |-b
2723 | | |-ArraySubscript
2724 | | | |-[
2725 | | | |-IntegerLiteralExpression
2726 | | | | `-1
2727 | | | `-]
2728 | | |-ArraySubscript
2729 | | | |-[
2730 | | | |-IntegerLiteralExpression
2731 | | | | `-2
2732 | | | `-]
2733 | | `-ArraySubscript
2734 | |   |-[
2735 | |   |-IntegerLiteralExpression
2736 | |   | `-3
2737 | |   `-]
2738 | `-;
2739 `-SimpleDeclaration
2740   |-int
2741   |-SimpleDeclarator
2742   | |-c
2743   | |-ArraySubscript
2744   | | |-[
2745   | | `-]
2746   | |-=
2747   | `-UnknownExpression
2748   |   `-UnknownExpression
2749   |     |-{
2750   |     |-IntegerLiteralExpression
2751   |     | `-1
2752   |     |-,
2753   |     |-IntegerLiteralExpression
2754   |     | `-2
2755   |     |-,
2756   |     |-IntegerLiteralExpression
2757   |     | `-3
2758   |     `-}
2759   `-;
2760 )txt"));
2761 }
2762 
2763 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
2764   if (!GetParam().isC99OrLater()) {
2765     return;
2766   }
2767   EXPECT_TRUE(treeDumpEqual(
2768       R"cpp(
2769 void f(int xs[static 10]);
2770 )cpp",
2771       R"txt(
2772 *: TranslationUnit
2773 `-SimpleDeclaration
2774   |-void
2775   |-SimpleDeclarator
2776   | |-f
2777   | `-ParametersAndQualifiers
2778   |   |-(
2779   |   |-SimpleDeclaration
2780   |   | |-int
2781   |   | `-SimpleDeclarator
2782   |   |   |-xs
2783   |   |   `-ArraySubscript
2784   |   |     |-[
2785   |   |     |-static
2786   |   |     |-IntegerLiteralExpression
2787   |   |     | `-10
2788   |   |     `-]
2789   |   `-)
2790   `-;
2791 )txt"));
2792 }
2793 
2794 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
2795   if (!GetParam().isCXX()) {
2796     return;
2797   }
2798   EXPECT_TRUE(treeDumpEqual(
2799       R"cpp(
2800 int func1();
2801 int func2a(int a);
2802 int func2b(int);
2803 int func3a(int *ap);
2804 int func3b(int *);
2805 int func4a(int a, float b);
2806 int func4b(int, float);
2807 )cpp",
2808       R"txt(
2809 *: TranslationUnit
2810 |-SimpleDeclaration
2811 | |-int
2812 | |-SimpleDeclarator
2813 | | |-func1
2814 | | `-ParametersAndQualifiers
2815 | |   |-(
2816 | |   `-)
2817 | `-;
2818 |-SimpleDeclaration
2819 | |-int
2820 | |-SimpleDeclarator
2821 | | |-func2a
2822 | | `-ParametersAndQualifiers
2823 | |   |-(
2824 | |   |-SimpleDeclaration
2825 | |   | |-int
2826 | |   | `-SimpleDeclarator
2827 | |   |   `-a
2828 | |   `-)
2829 | `-;
2830 |-SimpleDeclaration
2831 | |-int
2832 | |-SimpleDeclarator
2833 | | |-func2b
2834 | | `-ParametersAndQualifiers
2835 | |   |-(
2836 | |   |-SimpleDeclaration
2837 | |   | `-int
2838 | |   `-)
2839 | `-;
2840 |-SimpleDeclaration
2841 | |-int
2842 | |-SimpleDeclarator
2843 | | |-func3a
2844 | | `-ParametersAndQualifiers
2845 | |   |-(
2846 | |   |-SimpleDeclaration
2847 | |   | |-int
2848 | |   | `-SimpleDeclarator
2849 | |   |   |-*
2850 | |   |   `-ap
2851 | |   `-)
2852 | `-;
2853 |-SimpleDeclaration
2854 | |-int
2855 | |-SimpleDeclarator
2856 | | |-func3b
2857 | | `-ParametersAndQualifiers
2858 | |   |-(
2859 | |   |-SimpleDeclaration
2860 | |   | |-int
2861 | |   | `-SimpleDeclarator
2862 | |   |   `-*
2863 | |   `-)
2864 | `-;
2865 |-SimpleDeclaration
2866 | |-int
2867 | |-SimpleDeclarator
2868 | | |-func4a
2869 | | `-ParametersAndQualifiers
2870 | |   |-(
2871 | |   |-SimpleDeclaration
2872 | |   | |-int
2873 | |   | `-SimpleDeclarator
2874 | |   |   `-a
2875 | |   |-,
2876 | |   |-SimpleDeclaration
2877 | |   | |-float
2878 | |   | `-SimpleDeclarator
2879 | |   |   `-b
2880 | |   `-)
2881 | `-;
2882 `-SimpleDeclaration
2883   |-int
2884   |-SimpleDeclarator
2885   | |-func4b
2886   | `-ParametersAndQualifiers
2887   |   |-(
2888   |   |-SimpleDeclaration
2889   |   | `-int
2890   |   |-,
2891   |   |-SimpleDeclaration
2892   |   | `-float
2893   |   `-)
2894   `-;
2895 )txt"));
2896 }
2897 
2898 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
2899   if (!GetParam().isCXX()) {
2900     return;
2901   }
2902   EXPECT_TRUE(treeDumpEqual(
2903       R"cpp(
2904 int func1(const int a, volatile int b, const volatile int c);
2905 int func2(int& a);
2906 )cpp",
2907       R"txt(
2908 *: TranslationUnit
2909 |-SimpleDeclaration
2910 | |-int
2911 | |-SimpleDeclarator
2912 | | |-func1
2913 | | `-ParametersAndQualifiers
2914 | |   |-(
2915 | |   |-SimpleDeclaration
2916 | |   | |-const
2917 | |   | |-int
2918 | |   | `-SimpleDeclarator
2919 | |   |   `-a
2920 | |   |-,
2921 | |   |-SimpleDeclaration
2922 | |   | |-volatile
2923 | |   | |-int
2924 | |   | `-SimpleDeclarator
2925 | |   |   `-b
2926 | |   |-,
2927 | |   |-SimpleDeclaration
2928 | |   | |-const
2929 | |   | |-volatile
2930 | |   | |-int
2931 | |   | `-SimpleDeclarator
2932 | |   |   `-c
2933 | |   `-)
2934 | `-;
2935 `-SimpleDeclaration
2936   |-int
2937   |-SimpleDeclarator
2938   | |-func2
2939   | `-ParametersAndQualifiers
2940   |   |-(
2941   |   |-SimpleDeclaration
2942   |   | |-int
2943   |   | `-SimpleDeclarator
2944   |   |   |-&
2945   |   |   `-a
2946   |   `-)
2947   `-;
2948 )txt"));
2949 }
2950 
2951 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
2952   if (!GetParam().isCXX11OrLater()) {
2953     return;
2954   }
2955   EXPECT_TRUE(treeDumpEqual(
2956       R"cpp(
2957 int func1(int&& a);
2958 )cpp",
2959       R"txt(
2960 *: TranslationUnit
2961 `-SimpleDeclaration
2962   |-int
2963   |-SimpleDeclarator
2964   | |-func1
2965   | `-ParametersAndQualifiers
2966   |   |-(
2967   |   |-SimpleDeclaration
2968   |   | |-int
2969   |   | `-SimpleDeclarator
2970   |   |   |-&&
2971   |   |   `-a
2972   |   `-)
2973   `-;
2974 )txt"));
2975 }
2976 
2977 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
2978   if (!GetParam().isCXX()) {
2979     return;
2980   }
2981   EXPECT_TRUE(treeDumpEqual(
2982       R"cpp(
2983 struct Test {
2984   int a();
2985   int b() const;
2986   int c() volatile;
2987   int d() const volatile;
2988   int e() &;
2989   int f() &&;
2990 };
2991 )cpp",
2992       R"txt(
2993 *: TranslationUnit
2994 `-SimpleDeclaration
2995   |-struct
2996   |-Test
2997   |-{
2998   |-SimpleDeclaration
2999   | |-int
3000   | |-SimpleDeclarator
3001   | | |-a
3002   | | `-ParametersAndQualifiers
3003   | |   |-(
3004   | |   `-)
3005   | `-;
3006   |-SimpleDeclaration
3007   | |-int
3008   | |-SimpleDeclarator
3009   | | |-b
3010   | | `-ParametersAndQualifiers
3011   | |   |-(
3012   | |   |-)
3013   | |   `-const
3014   | `-;
3015   |-SimpleDeclaration
3016   | |-int
3017   | |-SimpleDeclarator
3018   | | |-c
3019   | | `-ParametersAndQualifiers
3020   | |   |-(
3021   | |   |-)
3022   | |   `-volatile
3023   | `-;
3024   |-SimpleDeclaration
3025   | |-int
3026   | |-SimpleDeclarator
3027   | | |-d
3028   | | `-ParametersAndQualifiers
3029   | |   |-(
3030   | |   |-)
3031   | |   |-const
3032   | |   `-volatile
3033   | `-;
3034   |-SimpleDeclaration
3035   | |-int
3036   | |-SimpleDeclarator
3037   | | |-e
3038   | | `-ParametersAndQualifiers
3039   | |   |-(
3040   | |   |-)
3041   | |   `-&
3042   | `-;
3043   |-SimpleDeclaration
3044   | |-int
3045   | |-SimpleDeclarator
3046   | | |-f
3047   | | `-ParametersAndQualifiers
3048   | |   |-(
3049   | |   |-)
3050   | |   `-&&
3051   | `-;
3052   |-}
3053   `-;
3054 )txt"));
3055 }
3056 
3057 TEST_P(SyntaxTreeTest, TrailingReturn) {
3058   if (!GetParam().isCXX11OrLater()) {
3059     return;
3060   }
3061   EXPECT_TRUE(treeDumpEqual(
3062       R"cpp(
3063 auto foo() -> int;
3064 )cpp",
3065       R"txt(
3066 *: TranslationUnit
3067 `-SimpleDeclaration
3068   |-auto
3069   |-SimpleDeclarator
3070   | |-foo
3071   | `-ParametersAndQualifiers
3072   |   |-(
3073   |   |-)
3074   |   `-TrailingReturnType
3075   |     |-->
3076   |     `-int
3077   `-;
3078 )txt"));
3079 }
3080 
3081 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
3082   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
3083     return;
3084   }
3085   EXPECT_TRUE(treeDumpEqual(
3086       R"cpp(
3087 struct MyException1 {};
3088 struct MyException2 {};
3089 int a() throw();
3090 int b() throw(...);
3091 int c() throw(MyException1);
3092 int d() throw(MyException1, MyException2);
3093 )cpp",
3094       R"txt(
3095 *: TranslationUnit
3096 |-SimpleDeclaration
3097 | |-struct
3098 | |-MyException1
3099 | |-{
3100 | |-}
3101 | `-;
3102 |-SimpleDeclaration
3103 | |-struct
3104 | |-MyException2
3105 | |-{
3106 | |-}
3107 | `-;
3108 |-SimpleDeclaration
3109 | |-int
3110 | |-SimpleDeclarator
3111 | | |-a
3112 | | `-ParametersAndQualifiers
3113 | |   |-(
3114 | |   |-)
3115 | |   |-throw
3116 | |   |-(
3117 | |   `-)
3118 | `-;
3119 |-SimpleDeclaration
3120 | |-int
3121 | |-SimpleDeclarator
3122 | | |-b
3123 | | `-ParametersAndQualifiers
3124 | |   |-(
3125 | |   |-)
3126 | |   |-throw
3127 | |   |-(
3128 | |   |-...
3129 | |   `-)
3130 | `-;
3131 |-SimpleDeclaration
3132 | |-int
3133 | |-SimpleDeclarator
3134 | | |-c
3135 | | `-ParametersAndQualifiers
3136 | |   |-(
3137 | |   |-)
3138 | |   |-throw
3139 | |   |-(
3140 | |   |-MyException1
3141 | |   `-)
3142 | `-;
3143 `-SimpleDeclaration
3144   |-int
3145   |-SimpleDeclarator
3146   | |-d
3147   | `-ParametersAndQualifiers
3148   |   |-(
3149   |   |-)
3150   |   |-throw
3151   |   |-(
3152   |   |-MyException1
3153   |   |-,
3154   |   |-MyException2
3155   |   `-)
3156   `-;
3157 )txt"));
3158 }
3159 
3160 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
3161   if (!GetParam().isCXX11OrLater()) {
3162     return;
3163   }
3164   EXPECT_TRUE(treeDumpEqual(
3165       R"cpp(
3166 int a() noexcept;
3167 int b() noexcept(true);
3168 )cpp",
3169       R"txt(
3170 *: TranslationUnit
3171 |-SimpleDeclaration
3172 | |-int
3173 | |-SimpleDeclarator
3174 | | |-a
3175 | | `-ParametersAndQualifiers
3176 | |   |-(
3177 | |   |-)
3178 | |   `-noexcept
3179 | `-;
3180 `-SimpleDeclaration
3181   |-int
3182   |-SimpleDeclarator
3183   | |-b
3184   | `-ParametersAndQualifiers
3185   |   |-(
3186   |   |-)
3187   |   |-noexcept
3188   |   |-(
3189   |   |-UnknownExpression
3190   |   | `-true
3191   |   `-)
3192   `-;
3193 )txt"));
3194 }
3195 
3196 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
3197   EXPECT_TRUE(treeDumpEqual(
3198       R"cpp(
3199 int (a);
3200 int *(b);
3201 int (*c)(int);
3202 int *(d)(int);
3203 )cpp",
3204       R"txt(
3205 *: TranslationUnit
3206 |-SimpleDeclaration
3207 | |-int
3208 | |-SimpleDeclarator
3209 | | `-ParenDeclarator
3210 | |   |-(
3211 | |   |-a
3212 | |   `-)
3213 | `-;
3214 |-SimpleDeclaration
3215 | |-int
3216 | |-SimpleDeclarator
3217 | | |-*
3218 | | `-ParenDeclarator
3219 | |   |-(
3220 | |   |-b
3221 | |   `-)
3222 | `-;
3223 |-SimpleDeclaration
3224 | |-int
3225 | |-SimpleDeclarator
3226 | | |-ParenDeclarator
3227 | | | |-(
3228 | | | |-*
3229 | | | |-c
3230 | | | `-)
3231 | | `-ParametersAndQualifiers
3232 | |   |-(
3233 | |   |-SimpleDeclaration
3234 | |   | `-int
3235 | |   `-)
3236 | `-;
3237 `-SimpleDeclaration
3238   |-int
3239   |-SimpleDeclarator
3240   | |-*
3241   | |-ParenDeclarator
3242   | | |-(
3243   | | |-d
3244   | | `-)
3245   | `-ParametersAndQualifiers
3246   |   |-(
3247   |   |-SimpleDeclaration
3248   |   | `-int
3249   |   `-)
3250   `-;
3251 )txt"));
3252 }
3253 
3254 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
3255   EXPECT_TRUE(treeDumpEqual(
3256       R"cpp(
3257 const int west = -1;
3258 int const east = 1;
3259 const int const universal = 0;
3260 const int const *const *volatile b;
3261 )cpp",
3262       R"txt(
3263 *: TranslationUnit
3264 |-SimpleDeclaration
3265 | |-const
3266 | |-int
3267 | |-SimpleDeclarator
3268 | | |-west
3269 | | |-=
3270 | | `-PrefixUnaryOperatorExpression
3271 | |   |--
3272 | |   `-IntegerLiteralExpression
3273 | |     `-1
3274 | `-;
3275 |-SimpleDeclaration
3276 | |-int
3277 | |-const
3278 | |-SimpleDeclarator
3279 | | |-east
3280 | | |-=
3281 | | `-IntegerLiteralExpression
3282 | |   `-1
3283 | `-;
3284 |-SimpleDeclaration
3285 | |-const
3286 | |-int
3287 | |-const
3288 | |-SimpleDeclarator
3289 | | |-universal
3290 | | |-=
3291 | | `-IntegerLiteralExpression
3292 | |   `-0
3293 | `-;
3294 `-SimpleDeclaration
3295   |-const
3296   |-int
3297   |-const
3298   |-SimpleDeclarator
3299   | |-*
3300   | |-const
3301   | |-*
3302   | |-volatile
3303   | `-b
3304   `-;
3305 )txt"));
3306 }
3307 
3308 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
3309   if (!GetParam().isCXX11OrLater()) {
3310     return;
3311   }
3312   EXPECT_TRUE(treeDumpEqual(
3313       R"cpp(
3314 auto foo() -> auto(*)(int) -> double*;
3315 )cpp",
3316       R"txt(
3317 *: TranslationUnit
3318 `-SimpleDeclaration
3319   |-auto
3320   |-SimpleDeclarator
3321   | |-foo
3322   | `-ParametersAndQualifiers
3323   |   |-(
3324   |   |-)
3325   |   `-TrailingReturnType
3326   |     |-->
3327   |     |-auto
3328   |     `-SimpleDeclarator
3329   |       |-ParenDeclarator
3330   |       | |-(
3331   |       | |-*
3332   |       | `-)
3333   |       `-ParametersAndQualifiers
3334   |         |-(
3335   |         |-SimpleDeclaration
3336   |         | `-int
3337   |         |-)
3338   |         `-TrailingReturnType
3339   |           |-->
3340   |           |-double
3341   |           `-SimpleDeclarator
3342   |             `-*
3343   `-;
3344 )txt"));
3345 }
3346 
3347 TEST_P(SyntaxTreeTest, MemberPointers) {
3348   if (!GetParam().isCXX()) {
3349     return;
3350   }
3351   EXPECT_TRUE(treeDumpEqual(
3352       R"cpp(
3353 struct X {};
3354 int X::* a;
3355 const int X::* b;
3356 )cpp",
3357       R"txt(
3358 *: TranslationUnit
3359 |-SimpleDeclaration
3360 | |-struct
3361 | |-X
3362 | |-{
3363 | |-}
3364 | `-;
3365 |-SimpleDeclaration
3366 | |-int
3367 | |-SimpleDeclarator
3368 | | |-MemberPointer
3369 | | | |-X
3370 | | | |-::
3371 | | | `-*
3372 | | `-a
3373 | `-;
3374 `-SimpleDeclaration
3375   |-const
3376   |-int
3377   |-SimpleDeclarator
3378   | |-MemberPointer
3379   | | |-X
3380   | | |-::
3381   | | `-*
3382   | `-b
3383   `-;
3384 )txt"));
3385 }
3386 
3387 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
3388   EXPECT_TRUE(treeDumpEqual(
3389       R"cpp(
3390 void x(char a, short (*b)(int));
3391 )cpp",
3392       R"txt(
3393 *: TranslationUnit
3394 `-SimpleDeclaration
3395   |-void
3396   |-SimpleDeclarator
3397   | |-x
3398   | `-ParametersAndQualifiers
3399   |   |-(
3400   |   |-SimpleDeclaration
3401   |   | |-char
3402   |   | `-SimpleDeclarator
3403   |   |   `-a
3404   |   |-,
3405   |   |-SimpleDeclaration
3406   |   | |-short
3407   |   | `-SimpleDeclarator
3408   |   |   |-ParenDeclarator
3409   |   |   | |-(
3410   |   |   | |-*
3411   |   |   | |-b
3412   |   |   | `-)
3413   |   |   `-ParametersAndQualifiers
3414   |   |     |-(
3415   |   |     |-SimpleDeclaration
3416   |   |     | `-int
3417   |   |     `-)
3418   |   `-)
3419   `-;
3420 )txt"));
3421 }
3422 
3423 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
3424   EXPECT_TRUE(treeDumpEqual(
3425       R"cpp(
3426 void x(char a, short (*b)(int), long (**c)(long long));
3427 )cpp",
3428       R"txt(
3429 *: TranslationUnit
3430 `-SimpleDeclaration
3431   |-void
3432   |-SimpleDeclarator
3433   | |-x
3434   | `-ParametersAndQualifiers
3435   |   |-(
3436   |   |-SimpleDeclaration
3437   |   | |-char
3438   |   | `-SimpleDeclarator
3439   |   |   `-a
3440   |   |-,
3441   |   |-SimpleDeclaration
3442   |   | |-short
3443   |   | `-SimpleDeclarator
3444   |   |   |-ParenDeclarator
3445   |   |   | |-(
3446   |   |   | |-*
3447   |   |   | |-b
3448   |   |   | `-)
3449   |   |   `-ParametersAndQualifiers
3450   |   |     |-(
3451   |   |     |-SimpleDeclaration
3452   |   |     | `-int
3453   |   |     `-)
3454   |   |-,
3455   |   |-SimpleDeclaration
3456   |   | |-long
3457   |   | `-SimpleDeclarator
3458   |   |   |-ParenDeclarator
3459   |   |   | |-(
3460   |   |   | |-*
3461   |   |   | |-*
3462   |   |   | |-c
3463   |   |   | `-)
3464   |   |   `-ParametersAndQualifiers
3465   |   |     |-(
3466   |   |     |-SimpleDeclaration
3467   |   |     | |-long
3468   |   |     | `-long
3469   |   |     `-)
3470   |   `-)
3471   `-;
3472 )txt"));
3473 }
3474 
3475 TEST_P(SyntaxTreeTest, Mutations) {
3476   if (!GetParam().isCXX11OrLater()) {
3477     return;
3478   }
3479 
3480   using Transformation = std::function<void(
3481       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
3482   auto CheckTransformation = [this](std::string Input, std::string Expected,
3483                                     Transformation Transform) -> void {
3484     llvm::Annotations Source(Input);
3485     auto *Root = buildTree(Source.code(), GetParam());
3486 
3487     Transform(Source, Root);
3488 
3489     auto Replacements = syntax::computeReplacements(*Arena, *Root);
3490     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
3491     if (!Output) {
3492       ADD_FAILURE() << "could not apply replacements: "
3493                     << llvm::toString(Output.takeError());
3494       return;
3495     }
3496 
3497     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
3498   };
3499 
3500   // Removes the selected statement. Input should have exactly one selected
3501   // range and it should correspond to a single statement.
3502   auto RemoveStatement = [this](const llvm::Annotations &Input,
3503                                 syntax::TranslationUnit *TU) {
3504     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
3505     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
3506     syntax::removeStatement(*Arena, S);
3507     EXPECT_TRUE(S->isDetached());
3508     EXPECT_FALSE(S->isOriginal())
3509         << "node removed from tree cannot be marked as original";
3510   };
3511 
3512   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
3513       Cases = {
3514           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
3515           {"void test() { if (true) [[{}]] else {} }",
3516            "void test() { if (true) ; else {} }"},
3517           {"void test() { [[;]] }", "void test() {  }"}};
3518   for (const auto &C : Cases)
3519     CheckTransformation(C.first, C.second, RemoveStatement);
3520 }
3521 
3522 TEST_P(SyntaxTreeTest, SynthesizedNodes) {
3523   buildTree("", GetParam());
3524 
3525   auto *C = syntax::createPunctuation(*Arena, tok::comma);
3526   ASSERT_NE(C, nullptr);
3527   EXPECT_EQ(C->token()->kind(), tok::comma);
3528   EXPECT_TRUE(C->canModify());
3529   EXPECT_FALSE(C->isOriginal());
3530   EXPECT_TRUE(C->isDetached());
3531 
3532   auto *S = syntax::createEmptyStatement(*Arena);
3533   ASSERT_NE(S, nullptr);
3534   EXPECT_TRUE(S->canModify());
3535   EXPECT_FALSE(S->isOriginal());
3536   EXPECT_TRUE(S->isDetached());
3537 }
3538 
3539 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
3540                         testing::ValuesIn(TestClangConfig::allConfigs()), );
3541 
3542 } // namespace
3543