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