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