1===============================
2ASTImporter: Merging Clang ASTs
3===============================
4
5The ``ASTImporter`` class is part of Clang's core library, the AST library.
6It imports nodes of an ``ASTContext`` into another ``ASTContext``.
7
8In this document, we assume basic knowledge about the Clang AST.  See the :doc:`Introduction
9to the Clang AST <IntroductionToTheClangAST>` if you want to learn more
10about how the AST is structured.
11Knowledge about :doc:`matching the Clang AST <LibASTMatchers>` and the `reference for the matchers <https://clang.llvm.org/docs/LibASTMatchersReference.html>`_ are also useful.
12
13.. contents::
14   :local:
15
16Introduction
17------------
18
19``ASTContext`` holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic analysis of a file.
20In some cases it is preferable to work with more than one ``ASTContext``.
21For example, we'd like to parse multiple different files inside the same Clang tool.
22It may be convenient if we could view the set of the resulting ASTs as if they were one AST resulting from the parsing of each file together.
23``ASTImporter`` provides the way to copy types or declarations from one ``ASTContext`` to another.
24We refer to the context from which we import as the **"from" context** or *source context*; and the context into which we import as the **"to" context** or *destination context*.
25
26Existing clients of the ``ASTImporter`` library are Cross Translation Unit (CTU) static analysis and the LLDB expression parser.
27CTU static analysis imports a definition of a function if its definition is found in another translation unit (TU).
28This way the analysis can breach out from the single TU limitation.
29LLDB's ``expr`` command parses a user-defined expression, creates an ``ASTContext`` for that and then imports the missing definitions from the AST what we got from the debug information (DWARF, etc).
30
31Algorithm of the import
32-----------------------
33
34Importing one AST node copies that node into the destination ``ASTContext``.
35Why do we have to copy the node?
36Isn't enough to insert the pointer to that node into the destination context?
37One reason is that the "from" context may outlive the "to" context.
38Also, the Clang AST consider nodes (or certain properties of nodes) equivalent if they have the same address!
39
40The import algorithm has to ensure that the structurally equivalent nodes in the different translation units are not getting duplicated in the merged AST.
41E.g. if we include the definition of the vector template (``#include <vector>``) in two translation units, then their merged AST should have only one node which represents the template.
42Also, we have to discover *one definition rule* (ODR) violations.
43For instance, if there is a class definition with the same name in both translation units, but one of the definition contains a different number of fields.
44So, we look up existing definitions, and then we check the structural equivalency on those nodes.
45The following pseudo-code demonstrates the basics of the import mechanism:
46
47.. code-block:: cpp
48
49  // Pseudo-code(!) of import:
50  ErrorOrDecl Import(Decl *FromD) {
51    Decl *ToDecl = nullptr;
52    FoundDeclsList = Look up all Decls in the "to" Ctx with the same name of FromD;
53    for (auto FoundDecl : FoundDeclsList) {
54      if (StructurallyEquivalentDecls(FoundDecl, FromD)) {
55        ToDecl = FoundDecl;
56        Mark FromD as imported;
57        break;
58      } else {
59        Report ODR violation;
60        return error;
61      }
62    }
63    if (FoundDeclsList is empty) {
64      Import dependent declarations and types of ToDecl;
65      ToDecl = create a new AST node in "to" Ctx;
66      Mark FromD as imported;
67    }
68    return ToDecl;
69  }
70
71Two AST nodes are *structurally equivalent* if they are
72
73- builtin types and refer to the same type, e.g. ``int`` and ``int`` are structurally equivalent,
74- function types and all their parameters have structurally equivalent types,
75- record types and all their fields in order of their definition have the same identifier names and structurally equivalent types,
76- variable or function declarations and they have the same identifier name and their types are structurally equivalent.
77
78We could extend the definition of structural equivalency to templates similarly.
79
80If A and B are AST nodes and *A depends on B*, then we say that A is a **dependant** of B and B is a **dependency** of A.
81The words "dependant" and "dependency" are nouns in British English.
82Unfortunately, in American English, the adjective "dependent" is used for both meanings.
83In this document, with the "dependent" adjective we always address the dependencies, the B node in the example.
84
85API
86---
87
88Let's create a tool which uses the ASTImporter class!
89First, we build two ASTs from virtual files; the content of the virtual files are synthesized from string literals:
90
91.. code-block:: cpp
92
93  std::unique_ptr<ASTUnit> ToUnit = buildASTFromCode(
94      "", "to.cc"); // empty file
95  std::unique_ptr<ASTUnit> FromUnit = buildASTFromCode(
96      R"(
97      class MyClass {
98        int m1;
99        int m2;
100      };
101      )",
102      "from.cc");
103
104The first AST corresponds to the destination ("to") context - which is empty - and the second for the source ("from") context.
105Next, we define a matcher to match ``MyClass`` in the "from" context:
106
107.. code-block:: cpp
108
109  auto Matcher = cxxRecordDecl(hasName("MyClass"));
110  auto *From = getFirstDecl<CXXRecordDecl>(Matcher, FromUnit);
111
112Now we create the Importer and do the import:
113
114.. code-block:: cpp
115
116  ASTImporter Importer(ToUnit->getASTContext(), ToUnit->getFileManager(),
117                       FromUnit->getASTContext(), FromUnit->getFileManager(),
118                       /*MinimalImport=*/true);
119  llvm::Expected<Decl *> ImportedOrErr = Importer.Import(From);
120
121The ``Import`` call returns with ``llvm::Expected``, so, we must check for any error.
122Please refer to the `error handling <https://llvm.org/docs/ProgrammersManual.html#recoverable-errors>`_ documentation for details.
123
124.. code-block:: cpp
125
126  if (!ImportedOrErr) {
127    llvm::Error Err = ImportedOrErr.takeError();
128    llvm::errs() << "ERROR: " << Err << "\n";
129    consumeError(std::move(Err));
130    return 1;
131  }
132
133If there's no error then we can get the underlying value.
134In this example we will print the AST of the "to" context.
135
136.. code-block:: cpp
137
138  Decl *Imported = *ImportedOrErr;
139  Imported->getTranslationUnitDecl()->dump();
140
141Since we set **minimal import** in the constructor of the importer, the AST will not contain the declaration of the members (once we run the test tool).
142
143.. code-block:: bash
144
145  TranslationUnitDecl 0x68b9a8 <<invalid sloc>> <invalid sloc>
146  `-CXXRecordDecl 0x6c7e30 <line:2:7, col:13> col:13 class MyClass definition
147    `-DefinitionData pass_in_registers standard_layout trivially_copyable trivial literal
148      |-DefaultConstructor exists trivial needs_implicit
149      |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
150      |-MoveConstructor exists simple trivial needs_implicit
151      |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
152      |-MoveAssignment exists simple trivial needs_implicit
153      `-Destructor simple irrelevant trivial needs_implicit
154
155We'd like to get the members too, so, we use ``ImportDefinition`` to copy the whole definition of ``MyClass`` into the "to" context.
156Then we dump the AST again.
157
158.. code-block:: cpp
159
160  if (llvm::Error Err = Importer.ImportDefinition(From)) {
161    llvm::errs() << "ERROR: " << Err << "\n";
162    consumeError(std::move(Err));
163    return 1;
164  }
165  llvm::errs() << "Imported definition.\n";
166  Imported->getTranslationUnitDecl()->dump();
167
168This time the AST is going to contain the members too.
169
170.. code-block:: bash
171
172  TranslationUnitDecl 0x68b9a8 <<invalid sloc>> <invalid sloc>
173  `-CXXRecordDecl 0x6c7e30 <line:2:7, col:13> col:13 class MyClass definition
174    |-DefinitionData pass_in_registers standard_layout trivially_copyable trivial literal
175    | |-DefaultConstructor exists trivial needs_implicit
176    | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
177    | |-MoveConstructor exists simple trivial needs_implicit
178    | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
179    | |-MoveAssignment exists simple trivial needs_implicit
180    | `-Destructor simple irrelevant trivial needs_implicit
181    |-CXXRecordDecl 0x6c7f48 <col:7, col:13> col:13 implicit class MyClass
182    |-FieldDecl 0x6c7ff0 <line:3:9, col:13> col:13 m1 'int'
183    `-FieldDecl 0x6c8058 <line:4:9, col:13> col:13 m2 'int'
184
185We can spare the call for ``ImportDefinition`` if we set up the importer to do a "normal" (not minimal) import.
186
187.. code-block:: cpp
188
189  ASTImporter Importer( ....  /*MinimalImport=*/false);
190
191With **normal import**, all dependent declarations are imported normally.
192However, with minimal import, the dependent Decls are imported without definition, and we have to import their definition for each if we later need that.
193
194Putting this all together here is how the source of the tool looks like:
195
196.. code-block:: cpp
197
198  #include "clang/AST/ASTImporter.h"
199  #include "clang/ASTMatchers/ASTMatchFinder.h"
200  #include "clang/ASTMatchers/ASTMatchers.h"
201  #include "clang/Tooling/Tooling.h"
202
203  using namespace clang;
204  using namespace tooling;
205  using namespace ast_matchers;
206
207  template <typename Node, typename Matcher>
208  Node *getFirstDecl(Matcher M, const std::unique_ptr<ASTUnit> &Unit) {
209    auto MB = M.bind("bindStr"); // Bind the to-be-matched node to a string key.
210    auto MatchRes = match(MB, Unit->getASTContext());
211    // We should have at least one match.
212    assert(MatchRes.size() >= 1);
213    // Get the first matched and bound node.
214    Node *Result =
215        const_cast<Node *>(MatchRes[0].template getNodeAs<Node>("bindStr"));
216    assert(Result);
217    return Result;
218  }
219
220  int main() {
221    std::unique_ptr<ASTUnit> ToUnit = buildASTFromCode(
222        "", "to.cc");
223    std::unique_ptr<ASTUnit> FromUnit = buildASTFromCode(
224        R"(
225        class MyClass {
226          int m1;
227          int m2;
228        };
229        )",
230        "from.cc");
231    auto Matcher = cxxRecordDecl(hasName("MyClass"));
232    auto *From = getFirstDecl<CXXRecordDecl>(Matcher, FromUnit);
233
234    ASTImporter Importer(ToUnit->getASTContext(), ToUnit->getFileManager(),
235                         FromUnit->getASTContext(), FromUnit->getFileManager(),
236                         /*MinimalImport=*/true);
237    llvm::Expected<Decl *> ImportedOrErr = Importer.Import(From);
238    if (!ImportedOrErr) {
239      llvm::Error Err = ImportedOrErr.takeError();
240      llvm::errs() << "ERROR: " << Err << "\n";
241      consumeError(std::move(Err));
242      return 1;
243    }
244    Decl *Imported = *ImportedOrErr;
245    Imported->getTranslationUnitDecl()->dump();
246
247    if (llvm::Error Err = Importer.ImportDefinition(From)) {
248      llvm::errs() << "ERROR: " << Err << "\n";
249      consumeError(std::move(Err));
250      return 1;
251    }
252    llvm::errs() << "Imported definition.\n";
253    Imported->getTranslationUnitDecl()->dump();
254
255    return 0;
256  };
257
258We may extend the ``CMakeLists.txt`` under let's say ``clang/tools`` with the build and link instructions:
259
260.. code-block:: bash
261
262  add_clang_executable(astimporter-demo ASTImporterDemo.cpp)
263  clang_target_link_libraries(astimporter-demo
264    PRIVATE
265    LLVMSupport
266    clangAST
267    clangASTMatchers
268    clangBasic
269    clangFrontend
270    clangSerialization
271    clangTooling
272    )
273
274Then we can build and execute the new tool.
275
276.. code-block:: bash
277
278  $ ninja astimporter-demo && ./bin/astimporter-demo
279
280Errors during the import process
281^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
282
283Normally, either the source or the destination context contains the definition of a declaration.
284However, there may be cases when both of the contexts have a definition for a given symbol.
285If these definitions differ, then we have a name conflict, in C++ it is known as ODR (one definition rule) violation.
286Let's modify the previous tool we had written and try to import a ``ClassTemplateSpecializationDecl`` with a conflicting definition:
287
288.. code-block:: cpp
289
290  int main() {
291    std::unique_ptr<ASTUnit> ToUnit = buildASTFromCode(
292        R"(
293        // primary template
294        template <typename T>
295        struct X {};
296        // explicit specialization
297        template<>
298        struct X<int> { int i; };
299        )",
300        "to.cc");
301    ToUnit->enableSourceFileDiagnostics();
302    std::unique_ptr<ASTUnit> FromUnit = buildASTFromCode(
303        R"(
304        // primary template
305        template <typename T>
306        struct X {};
307        // explicit specialization
308        template<>
309        struct X<int> { int i2; };
310        // field mismatch:  ^^
311        )",
312        "from.cc");
313    FromUnit->enableSourceFileDiagnostics();
314    auto Matcher = classTemplateSpecializationDecl(hasName("X"));
315    auto *From = getFirstDecl<ClassTemplateSpecializationDecl>(Matcher, FromUnit);
316    auto *To = getFirstDecl<ClassTemplateSpecializationDecl>(Matcher, ToUnit);
317
318    ASTImporter Importer(ToUnit->getASTContext(), ToUnit->getFileManager(),
319                         FromUnit->getASTContext(), FromUnit->getFileManager(),
320                         /*MinimalImport=*/false);
321    llvm::Expected<Decl *> ImportedOrErr = Importer.Import(From);
322    if (!ImportedOrErr) {
323      llvm::Error Err = ImportedOrErr.takeError();
324      llvm::errs() << "ERROR: " << Err << "\n";
325      consumeError(std::move(Err));
326      To->getTranslationUnitDecl()->dump();
327      return 1;
328    }
329    return 0;
330  };
331
332When we run the tool we have the following warning:
333
334.. code-block:: bash
335
336  to.cc:7:14: warning: type 'X<int>' has incompatible definitions in different translation units [-Wodr]
337        struct X<int> { int i; };
338               ^
339  to.cc:7:27: note: field has name 'i' here
340        struct X<int> { int i; };
341                            ^
342  from.cc:7:27: note: field has name 'i2' here
343        struct X<int> { int i2; };
344                          ^
345
346Note, because of these diagnostics we had to call ``enableSourceFileDiagnostics`` on the ``ASTUnit`` objects.
347
348Since we could not import the specified declaration (``From``), we get an error in the return value.
349The AST does not contain the conflicting definition, so we are left with the original AST.
350
351.. code-block:: bash
352
353  ERROR: NameConflict
354  TranslationUnitDecl 0xe54a48 <<invalid sloc>> <invalid sloc>
355  |-ClassTemplateDecl 0xe91020 <to.cc:3:7, line:4:17> col:14 X
356  | |-TemplateTypeParmDecl 0xe90ed0 <line:3:17, col:26> col:26 typename depth 0 index 0 T
357  | |-CXXRecordDecl 0xe90f90 <line:4:7, col:17> col:14 struct X definition
358  | | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
359  | | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
360  | | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
361  | | | |-MoveConstructor exists simple trivial needs_implicit
362  | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
363  | | | |-MoveAssignment exists simple trivial needs_implicit
364  | | | `-Destructor simple irrelevant trivial needs_implicit
365  | | `-CXXRecordDecl 0xe91270 <col:7, col:14> col:14 implicit struct X
366  | `-ClassTemplateSpecialization 0xe91340 'X'
367  `-ClassTemplateSpecializationDecl 0xe91340 <line:6:7, line:7:30> col:14 struct X definition
368    |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
369    | |-DefaultConstructor exists trivial needs_implicit
370    | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
371    | |-MoveConstructor exists simple trivial needs_implicit
372    | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
373    | |-MoveAssignment exists simple trivial needs_implicit
374    | `-Destructor simple irrelevant trivial needs_implicit
375    |-TemplateArgument type 'int'
376    |-CXXRecordDecl 0xe91558 <col:7, col:14> col:14 implicit struct X
377    `-FieldDecl 0xe91600 <col:23, col:27> col:27 i 'int'
378
379Error propagation
380"""""""""""""""""
381
382If there is a dependent node we have to import before we could import a given node then the import error associated to the dependency propagates to the dependant node.
383Let's modify the previous example and import a ``FieldDecl`` instead of the ``ClassTemplateSpecializationDecl``.
384
385.. code-block:: cpp
386
387  auto Matcher = fieldDecl(hasName("i2"));
388  auto *From = getFirstDecl<FieldDecl>(Matcher, FromUnit);
389
390In this case we can see that an error is associated (``getImportDeclErrorIfAny``) to the specialization also, not just to the field:
391
392.. code-block:: cpp
393
394  llvm::Expected<Decl *> ImportedOrErr = Importer.Import(From);
395  if (!ImportedOrErr) {
396    llvm::Error Err = ImportedOrErr.takeError();
397    consumeError(std::move(Err));
398
399    // check that the ClassTemplateSpecializationDecl is also marked as
400    // erroneous.
401    auto *FromSpec = getFirstDecl<ClassTemplateSpecializationDecl>(
402        classTemplateSpecializationDecl(hasName("X")), FromUnit);
403    assert(Importer.getImportDeclErrorIfAny(FromSpec));
404    // Btw, the error is also set for the FieldDecl.
405    assert(Importer.getImportDeclErrorIfAny(From));
406    return 1;
407  }
408
409Polluted AST
410""""""""""""
411
412We may recognize an error during the import of a dependent node. However, by that time, we had already created the dependant.
413In these cases we do not remove the existing erroneous node from the "to" context, rather we associate an error to that node.
414Let's extend the previous example with another class ``Y``.
415This class has a forward definition in the "to" context, but its definition is in the "from" context.
416We'd like to import the definition, but it contains a member whose type conflicts with the type in the "to" context:
417
418.. code-block:: cpp
419
420  std::unique_ptr<ASTUnit> ToUnit = buildASTFromCode(
421      R"(
422      // primary template
423      template <typename T>
424      struct X {};
425      // explicit specialization
426      template<>
427      struct X<int> { int i; };
428
429      class Y;
430      )",
431      "to.cc");
432  ToUnit->enableSourceFileDiagnostics();
433  std::unique_ptr<ASTUnit> FromUnit = buildASTFromCode(
434      R"(
435      // primary template
436      template <typename T>
437      struct X {};
438      // explicit specialization
439      template<>
440      struct X<int> { int i2; };
441      // field mismatch:  ^^
442
443      class Y { void f() { X<int> xi; } };
444      )",
445      "from.cc");
446  FromUnit->enableSourceFileDiagnostics();
447  auto Matcher = cxxRecordDecl(hasName("Y"));
448  auto *From = getFirstDecl<CXXRecordDecl>(Matcher, FromUnit);
449  auto *To = getFirstDecl<CXXRecordDecl>(Matcher, ToUnit);
450
451This time we create a shared_ptr for ``ASTImporterSharedState`` which owns the associated errors for the "to" context.
452Note, there may be several different ASTImporter objects which import into the same "to" context but from different "from" contexts; they should share the same ``ASTImporterSharedState``.
453(Also note, we have to include the corresponding ``ASTImporterSharedState.h`` header file.)
454
455.. code-block:: cpp
456
457  auto ImporterState = std::make_shared<ASTImporterSharedState>();
458  ASTImporter Importer(ToUnit->getASTContext(), ToUnit->getFileManager(),
459                       FromUnit->getASTContext(), FromUnit->getFileManager(),
460                       /*MinimalImport=*/false, ImporterState);
461  llvm::Expected<Decl *> ImportedOrErr = Importer.Import(From);
462  if (!ImportedOrErr) {
463    llvm::Error Err = ImportedOrErr.takeError();
464    consumeError(std::move(Err));
465
466    // ... but the node had been created.
467    auto *ToYDef = getFirstDecl<CXXRecordDecl>(
468        cxxRecordDecl(hasName("Y"), isDefinition()), ToUnit);
469    ToYDef->dump();
470    // An error is set for "ToYDef" in the shared state.
471    Optional<ImportError> OptErr =
472        ImporterState->getImportDeclErrorIfAny(ToYDef);
473    assert(OptErr);
474
475    return 1;
476  }
477
478If we take a look at the AST, then we can see that the Decl with the definition is created, but the field is missing.
479
480.. code-block:: bash
481
482  |-CXXRecordDecl 0xf66678 <line:9:7, col:13> col:13 class Y
483  `-CXXRecordDecl 0xf66730 prev 0xf66678 <:10:7, col:13> col:13 class Y definition
484    |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
485    | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
486    | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
487    | |-MoveConstructor exists simple trivial needs_implicit
488    | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
489    | |-MoveAssignment exists simple trivial needs_implicit
490    | `-Destructor simple irrelevant trivial needs_implicit
491    `-CXXRecordDecl 0xf66828 <col:7, col:13> col:13 implicit class Y
492
493We do not remove the erroneous nodes because by the time when we recognize the error it is too late to remove the node, there may be additional references to that already in the AST.
494This is aligned with the overall `design principle of the Clang AST <InternalsManual.html#immutability>`_: Clang AST nodes (types, declarations, statements, expressions, and so on) are generally designed to be **immutable once created**.
495Thus, clients of the ASTImporter library should always check if there is any associated error for the node which they inspect in the destination context.
496We recommend skipping the processing of those nodes which have an error associated with them.
497
498Using the ``-ast-merge`` Clang front-end action
499-----------------------------------------------
500
501The ``-ast-merge <pch-file>`` command-line switch can be used to merge from the given serialized AST file.
502This file represents the source context.
503When this switch is present then each top-level AST node of the source context is being merged into the destination context.
504If the merge was successful then ``ASTConsumer::HandleTopLevelDecl`` is called for the Decl.
505This results that we can execute the original front-end action on the extended AST.
506
507Example for C
508^^^^^^^^^^^^^
509
510Let's consider the following three files:
511
512.. code-block:: c
513
514  // bar.h
515  #ifndef BAR_H
516  #define BAR_H
517  int bar();
518  #endif /* BAR_H */
519
520  // bar.c
521  #include "bar.h"
522  int bar() {
523    return 41;
524  }
525
526  // main.c
527  #include "bar.h"
528  int main() {
529      return bar();
530  }
531
532Let's generate the AST files for the two source files:
533
534.. code-block:: bash
535
536  $ clang -cc1 -emit-pch -o bar.ast bar.c
537  $ clang -cc1 -emit-pch -o main.ast main.c
538
539Then, let's check how the merged AST would look like if we consider only the ``bar()`` function:
540
541.. code-block:: bash
542
543  $ clang -cc1 -ast-merge bar.ast -ast-merge main.ast /dev/null -ast-dump
544  TranslationUnitDecl 0x12b0738 <<invalid sloc>> <invalid sloc>
545  |-FunctionDecl 0x12b1470 </path/bar.h:4:1, col:9> col:5 used bar 'int ()'
546  |-FunctionDecl 0x12b1538 prev 0x12b1470 </path/bar.c:3:1, line:5:1> line:3:5 used bar 'int ()'
547  | `-CompoundStmt 0x12b1608 <col:11, line:5:1>
548  |   `-ReturnStmt 0x12b15f8 <line:4:3, col:10>
549  |     `-IntegerLiteral 0x12b15d8 <col:10> 'int' 41
550  |-FunctionDecl 0x12b1648 prev 0x12b1538 </path/bar.h:4:1, col:9> col:5 used bar 'int ()'
551
552We can inspect that the prototype of the function and the definition of it is merged into the same redeclaration chain.
553What's more there is a third prototype declaration merged to the chain.
554The functions are merged in a way that prototypes are added to the redecl chain if they refer to the same type, but we can have only one definition.
555The first two declarations are from ``bar.ast``, the third is from ``main.ast``.
556
557Now, let's create an object file from the merged AST:
558
559.. code-block:: bash
560
561  $ clang -cc1 -ast-merge bar.ast -ast-merge main.ast /dev/null -emit-obj -o main.o
562
563Next, we may call the linker and execute the created binary file.
564
565.. code-block:: bash
566
567  $ clang -o a.out main.o
568  $ ./a.out
569  $ echo $?
570  41
571  $
572
573Example for C++
574^^^^^^^^^^^^^^^
575
576In the case of C++, the generation of the AST files and the way how we invoke the front-end is a bit different.
577Assuming we have these three files:
578
579.. code-block:: cpp
580
581  // foo.h
582  #ifndef FOO_H
583  #define FOO_H
584  struct foo {
585      virtual int fun();
586  };
587  #endif /* FOO_H */
588
589  // foo.cpp
590  #include "foo.h"
591  int foo::fun() {
592    return 42;
593  }
594
595  // main.cpp
596  #include "foo.h"
597  int main() {
598      return foo().fun();
599  }
600
601We shall generate the AST files, merge them, create the executable and then run it:
602
603.. code-block:: bash
604
605  $ clang++ -x c++-header -o foo.ast foo.cpp
606  $ clang++ -x c++-header -o main.ast main.cpp
607  $ clang++ -cc1 -x c++ -ast-merge foo.ast -ast-merge main.ast /dev/null -ast-dump
608  $ clang++ -cc1 -x c++ -ast-merge foo.ast -ast-merge main.ast /dev/null -emit-obj -o main.o
609  $ clang++ -o a.out main.o
610  $ ./a.out
611  $ echo $?
612  42
613  $
614