xref: /openbsd-src/gnu/llvm/clang/tools/clang-import-test/clang-import-test.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===-- clang-import-test.cpp - ASTImporter/ExternalASTSource testbed -----===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "clang/AST/ASTContext.h"
10e5dd7070Spatrick #include "clang/AST/ASTImporter.h"
11e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
12e5dd7070Spatrick #include "clang/AST/ExternalASTMerger.h"
13e5dd7070Spatrick #include "clang/Basic/Builtins.h"
14ec727ea7Spatrick #include "clang/Basic/FileManager.h"
15e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
16e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
17e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
18e5dd7070Spatrick #include "clang/Basic/TargetOptions.h"
19e5dd7070Spatrick #include "clang/CodeGen/ModuleBuilder.h"
20e5dd7070Spatrick #include "clang/Driver/Types.h"
21e5dd7070Spatrick #include "clang/Frontend/ASTConsumers.h"
22e5dd7070Spatrick #include "clang/Frontend/CompilerInstance.h"
23e5dd7070Spatrick #include "clang/Frontend/MultiplexConsumer.h"
24e5dd7070Spatrick #include "clang/Frontend/TextDiagnosticBuffer.h"
25e5dd7070Spatrick #include "clang/Lex/Lexer.h"
26e5dd7070Spatrick #include "clang/Lex/Preprocessor.h"
27e5dd7070Spatrick #include "clang/Parse/ParseAST.h"
28e5dd7070Spatrick 
29e5dd7070Spatrick #include "llvm/IR/LLVMContext.h"
30e5dd7070Spatrick #include "llvm/IR/Module.h"
31e5dd7070Spatrick #include "llvm/Support/CommandLine.h"
32e5dd7070Spatrick #include "llvm/Support/Error.h"
33e5dd7070Spatrick #include "llvm/Support/Host.h"
34e5dd7070Spatrick #include "llvm/Support/Signals.h"
35e5dd7070Spatrick 
36e5dd7070Spatrick #include <memory>
37e5dd7070Spatrick #include <string>
38e5dd7070Spatrick 
39e5dd7070Spatrick using namespace clang;
40e5dd7070Spatrick 
41e5dd7070Spatrick static llvm::cl::opt<std::string> Expression(
42e5dd7070Spatrick     "expression", llvm::cl::Required,
43e5dd7070Spatrick     llvm::cl::desc("Path to a file containing the expression to parse"));
44e5dd7070Spatrick 
45e5dd7070Spatrick static llvm::cl::list<std::string>
46*12c85518Srobert     Imports("import",
47e5dd7070Spatrick             llvm::cl::desc("Path to a file containing declarations to import"));
48e5dd7070Spatrick 
49e5dd7070Spatrick static llvm::cl::opt<bool>
50e5dd7070Spatrick     Direct("direct", llvm::cl::Optional,
51e5dd7070Spatrick            llvm::cl::desc("Use the parsed declarations without indirection"));
52e5dd7070Spatrick 
53e5dd7070Spatrick static llvm::cl::opt<bool> UseOrigins(
54e5dd7070Spatrick     "use-origins", llvm::cl::Optional,
55e5dd7070Spatrick     llvm::cl::desc(
56e5dd7070Spatrick         "Use DeclContext origin information for more accurate lookups"));
57e5dd7070Spatrick 
58e5dd7070Spatrick static llvm::cl::list<std::string>
59*12c85518Srobert     ClangArgs("Xcc",
60e5dd7070Spatrick               llvm::cl::desc("Argument to pass to the CompilerInvocation"),
61e5dd7070Spatrick               llvm::cl::CommaSeparated);
62e5dd7070Spatrick 
63e5dd7070Spatrick static llvm::cl::opt<std::string>
64e5dd7070Spatrick     Input("x", llvm::cl::Optional,
65e5dd7070Spatrick           llvm::cl::desc("The language to parse (default: c++)"),
66e5dd7070Spatrick           llvm::cl::init("c++"));
67e5dd7070Spatrick 
68ec727ea7Spatrick static llvm::cl::opt<bool> ObjCARC("objc-arc", llvm::cl::init(false),
69ec727ea7Spatrick                                    llvm::cl::desc("Emable ObjC ARC"));
70ec727ea7Spatrick 
71e5dd7070Spatrick static llvm::cl::opt<bool> DumpAST("dump-ast", llvm::cl::init(false),
72e5dd7070Spatrick                                    llvm::cl::desc("Dump combined AST"));
73e5dd7070Spatrick 
74e5dd7070Spatrick static llvm::cl::opt<bool> DumpIR("dump-ir", llvm::cl::init(false),
75e5dd7070Spatrick                                   llvm::cl::desc("Dump IR from final parse"));
76e5dd7070Spatrick 
77e5dd7070Spatrick namespace init_convenience {
78e5dd7070Spatrick class TestDiagnosticConsumer : public DiagnosticConsumer {
79e5dd7070Spatrick private:
80e5dd7070Spatrick   std::unique_ptr<TextDiagnosticBuffer> Passthrough;
81e5dd7070Spatrick   const LangOptions *LangOpts = nullptr;
82e5dd7070Spatrick 
83e5dd7070Spatrick public:
TestDiagnosticConsumer()84e5dd7070Spatrick   TestDiagnosticConsumer()
85e5dd7070Spatrick       : Passthrough(std::make_unique<TextDiagnosticBuffer>()) {}
86e5dd7070Spatrick 
BeginSourceFile(const LangOptions & LangOpts,const Preprocessor * PP=nullptr)87*12c85518Srobert   void BeginSourceFile(const LangOptions &LangOpts,
88e5dd7070Spatrick                        const Preprocessor *PP = nullptr) override {
89e5dd7070Spatrick     this->LangOpts = &LangOpts;
90e5dd7070Spatrick     return Passthrough->BeginSourceFile(LangOpts, PP);
91e5dd7070Spatrick   }
92e5dd7070Spatrick 
EndSourceFile()93*12c85518Srobert   void EndSourceFile() override {
94e5dd7070Spatrick     this->LangOpts = nullptr;
95e5dd7070Spatrick     Passthrough->EndSourceFile();
96e5dd7070Spatrick   }
97e5dd7070Spatrick 
IncludeInDiagnosticCounts() const98*12c85518Srobert   bool IncludeInDiagnosticCounts() const override {
99e5dd7070Spatrick     return Passthrough->IncludeInDiagnosticCounts();
100e5dd7070Spatrick   }
101e5dd7070Spatrick 
102e5dd7070Spatrick private:
PrintSourceForLocation(const SourceLocation & Loc,SourceManager & SM)103e5dd7070Spatrick   static void PrintSourceForLocation(const SourceLocation &Loc,
104e5dd7070Spatrick                                      SourceManager &SM) {
105e5dd7070Spatrick     const char *LocData = SM.getCharacterData(Loc, /*Invalid=*/nullptr);
106e5dd7070Spatrick     unsigned LocColumn =
107e5dd7070Spatrick         SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1;
108e5dd7070Spatrick     FileID FID = SM.getFileID(Loc);
109a9ac8606Spatrick     llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, Loc);
110e5dd7070Spatrick 
111a9ac8606Spatrick     assert(LocData >= Buffer.getBufferStart() &&
112a9ac8606Spatrick            LocData < Buffer.getBufferEnd());
113e5dd7070Spatrick 
114e5dd7070Spatrick     const char *LineBegin = LocData - LocColumn;
115e5dd7070Spatrick 
116a9ac8606Spatrick     assert(LineBegin >= Buffer.getBufferStart());
117e5dd7070Spatrick 
118e5dd7070Spatrick     const char *LineEnd = nullptr;
119e5dd7070Spatrick 
120e5dd7070Spatrick     for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' &&
121a9ac8606Spatrick                               LineEnd < Buffer.getBufferEnd();
122e5dd7070Spatrick          ++LineEnd)
123e5dd7070Spatrick       ;
124e5dd7070Spatrick 
125e5dd7070Spatrick     llvm::StringRef LineString(LineBegin, LineEnd - LineBegin);
126e5dd7070Spatrick 
127e5dd7070Spatrick     llvm::errs() << LineString << '\n';
128e5dd7070Spatrick     llvm::errs().indent(LocColumn);
129e5dd7070Spatrick     llvm::errs() << '^';
130e5dd7070Spatrick     llvm::errs() << '\n';
131e5dd7070Spatrick   }
132e5dd7070Spatrick 
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)133*12c85518Srobert   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
134e5dd7070Spatrick                         const Diagnostic &Info) override {
135e5dd7070Spatrick     if (Info.hasSourceManager() && LangOpts) {
136e5dd7070Spatrick       SourceManager &SM = Info.getSourceManager();
137e5dd7070Spatrick 
138e5dd7070Spatrick       if (Info.getLocation().isValid()) {
139e5dd7070Spatrick         Info.getLocation().print(llvm::errs(), SM);
140e5dd7070Spatrick         llvm::errs() << ": ";
141e5dd7070Spatrick       }
142e5dd7070Spatrick 
143e5dd7070Spatrick       SmallString<16> DiagText;
144e5dd7070Spatrick       Info.FormatDiagnostic(DiagText);
145e5dd7070Spatrick       llvm::errs() << DiagText << '\n';
146e5dd7070Spatrick 
147e5dd7070Spatrick       if (Info.getLocation().isValid()) {
148e5dd7070Spatrick         PrintSourceForLocation(Info.getLocation(), SM);
149e5dd7070Spatrick       }
150e5dd7070Spatrick 
151e5dd7070Spatrick       for (const CharSourceRange &Range : Info.getRanges()) {
152e5dd7070Spatrick         bool Invalid = true;
153e5dd7070Spatrick         StringRef Ref = Lexer::getSourceText(Range, SM, *LangOpts, &Invalid);
154e5dd7070Spatrick         if (!Invalid) {
155e5dd7070Spatrick           llvm::errs() << Ref << '\n';
156e5dd7070Spatrick         }
157e5dd7070Spatrick       }
158e5dd7070Spatrick     }
159e5dd7070Spatrick     DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
160e5dd7070Spatrick   }
161e5dd7070Spatrick };
162e5dd7070Spatrick 
BuildCompilerInstance()163e5dd7070Spatrick std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
164e5dd7070Spatrick   auto Ins = std::make_unique<CompilerInstance>();
165e5dd7070Spatrick   auto DC = std::make_unique<TestDiagnosticConsumer>();
166e5dd7070Spatrick   const bool ShouldOwnClient = true;
167e5dd7070Spatrick   Ins->createDiagnostics(DC.release(), ShouldOwnClient);
168e5dd7070Spatrick 
169e5dd7070Spatrick   auto Inv = std::make_unique<CompilerInvocation>();
170e5dd7070Spatrick 
171e5dd7070Spatrick   std::vector<const char *> ClangArgv(ClangArgs.size());
172e5dd7070Spatrick   std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
173e5dd7070Spatrick                  [](const std::string &s) -> const char * { return s.data(); });
174e5dd7070Spatrick   CompilerInvocation::CreateFromArgs(*Inv, ClangArgv, Ins->getDiagnostics());
175e5dd7070Spatrick 
176e5dd7070Spatrick   {
177e5dd7070Spatrick     using namespace driver::types;
178e5dd7070Spatrick     ID Id = lookupTypeForTypeSpecifier(Input.c_str());
179e5dd7070Spatrick     assert(Id != TY_INVALID);
180e5dd7070Spatrick     if (isCXX(Id)) {
181e5dd7070Spatrick       Inv->getLangOpts()->CPlusPlus = true;
182e5dd7070Spatrick       Inv->getLangOpts()->CPlusPlus11 = true;
183e5dd7070Spatrick       Inv->getHeaderSearchOpts().UseLibcxx = true;
184e5dd7070Spatrick     }
185e5dd7070Spatrick     if (isObjC(Id)) {
186e5dd7070Spatrick       Inv->getLangOpts()->ObjC = 1;
187e5dd7070Spatrick     }
188e5dd7070Spatrick   }
189ec727ea7Spatrick   Inv->getLangOpts()->ObjCAutoRefCount = ObjCARC;
190ec727ea7Spatrick 
191e5dd7070Spatrick   Inv->getLangOpts()->Bool = true;
192e5dd7070Spatrick   Inv->getLangOpts()->WChar = true;
193e5dd7070Spatrick   Inv->getLangOpts()->Blocks = true;
194e5dd7070Spatrick   Inv->getLangOpts()->DebuggerSupport = true;
195e5dd7070Spatrick   Inv->getLangOpts()->SpellChecking = false;
196e5dd7070Spatrick   Inv->getLangOpts()->ThreadsafeStatics = false;
197e5dd7070Spatrick   Inv->getLangOpts()->AccessControl = false;
198e5dd7070Spatrick   Inv->getLangOpts()->DollarIdents = true;
199e5dd7070Spatrick   Inv->getLangOpts()->Exceptions = true;
200e5dd7070Spatrick   Inv->getLangOpts()->CXXExceptions = true;
201e5dd7070Spatrick   // Needed for testing dynamic_cast.
202e5dd7070Spatrick   Inv->getLangOpts()->RTTI = true;
203e5dd7070Spatrick   Inv->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
204e5dd7070Spatrick   Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
205e5dd7070Spatrick 
206e5dd7070Spatrick   Ins->setInvocation(std::move(Inv));
207e5dd7070Spatrick 
208e5dd7070Spatrick   TargetInfo *TI = TargetInfo::CreateTargetInfo(
209e5dd7070Spatrick       Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
210e5dd7070Spatrick   Ins->setTarget(TI);
211a9ac8606Spatrick   Ins->getTarget().adjust(Ins->getDiagnostics(), Ins->getLangOpts());
212e5dd7070Spatrick   Ins->createFileManager();
213e5dd7070Spatrick   Ins->createSourceManager(Ins->getFileManager());
214e5dd7070Spatrick   Ins->createPreprocessor(TU_Complete);
215e5dd7070Spatrick 
216e5dd7070Spatrick   return Ins;
217e5dd7070Spatrick }
218e5dd7070Spatrick 
219e5dd7070Spatrick std::unique_ptr<ASTContext>
BuildASTContext(CompilerInstance & CI,SelectorTable & ST,Builtin::Context & BC)220e5dd7070Spatrick BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) {
221a9ac8606Spatrick   auto &PP = CI.getPreprocessor();
222e5dd7070Spatrick   auto AST = std::make_unique<ASTContext>(
223e5dd7070Spatrick       CI.getLangOpts(), CI.getSourceManager(),
224a9ac8606Spatrick       PP.getIdentifierTable(), ST, BC, PP.TUKind);
225e5dd7070Spatrick   AST->InitBuiltinTypes(CI.getTarget());
226e5dd7070Spatrick   return AST;
227e5dd7070Spatrick }
228e5dd7070Spatrick 
BuildCodeGen(CompilerInstance & CI,llvm::LLVMContext & LLVMCtx)229e5dd7070Spatrick std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
230e5dd7070Spatrick                                             llvm::LLVMContext &LLVMCtx) {
231e5dd7070Spatrick   StringRef ModuleName("$__module");
232e5dd7070Spatrick   return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
233*12c85518Srobert       CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(),
234*12c85518Srobert       CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
235*12c85518Srobert       LLVMCtx));
236e5dd7070Spatrick }
237e5dd7070Spatrick } // namespace init_convenience
238e5dd7070Spatrick 
239e5dd7070Spatrick namespace {
240e5dd7070Spatrick 
241e5dd7070Spatrick /// A container for a CompilerInstance (possibly with an ExternalASTMerger
242e5dd7070Spatrick /// attached to its ASTContext).
243e5dd7070Spatrick ///
244e5dd7070Spatrick /// Provides an accessor for the DeclContext origins associated with the
245e5dd7070Spatrick /// ExternalASTMerger (or an empty list of origins if no ExternalASTMerger is
246e5dd7070Spatrick /// attached).
247e5dd7070Spatrick ///
248e5dd7070Spatrick /// This is the main unit of parsed source code maintained by clang-import-test.
249e5dd7070Spatrick struct CIAndOrigins {
250e5dd7070Spatrick   using OriginMap = clang::ExternalASTMerger::OriginMap;
251e5dd7070Spatrick   std::unique_ptr<CompilerInstance> CI;
252e5dd7070Spatrick 
getASTContext__anon379746ce0211::CIAndOrigins253e5dd7070Spatrick   ASTContext &getASTContext() { return CI->getASTContext(); }
getFileManager__anon379746ce0211::CIAndOrigins254e5dd7070Spatrick   FileManager &getFileManager() { return CI->getFileManager(); }
getOriginMap__anon379746ce0211::CIAndOrigins255e5dd7070Spatrick   const OriginMap &getOriginMap() {
256e5dd7070Spatrick     static const OriginMap EmptyOriginMap{};
257e5dd7070Spatrick     if (ExternalASTSource *Source = CI->getASTContext().getExternalSource())
258e5dd7070Spatrick       return static_cast<ExternalASTMerger *>(Source)->GetOrigins();
259e5dd7070Spatrick     return EmptyOriginMap;
260e5dd7070Spatrick   }
getDiagnosticClient__anon379746ce0211::CIAndOrigins261e5dd7070Spatrick   DiagnosticConsumer &getDiagnosticClient() {
262e5dd7070Spatrick     return CI->getDiagnosticClient();
263e5dd7070Spatrick   }
getCompilerInstance__anon379746ce0211::CIAndOrigins264e5dd7070Spatrick   CompilerInstance &getCompilerInstance() { return *CI; }
265e5dd7070Spatrick };
266e5dd7070Spatrick 
AddExternalSource(CIAndOrigins & CI,llvm::MutableArrayRef<CIAndOrigins> Imports)267e5dd7070Spatrick void AddExternalSource(CIAndOrigins &CI,
268e5dd7070Spatrick                        llvm::MutableArrayRef<CIAndOrigins> Imports) {
269e5dd7070Spatrick   ExternalASTMerger::ImporterTarget Target(
270e5dd7070Spatrick       {CI.getASTContext(), CI.getFileManager()});
271e5dd7070Spatrick   llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
272e5dd7070Spatrick   for (CIAndOrigins &Import : Imports)
273e5dd7070Spatrick     Sources.emplace_back(Import.getASTContext(), Import.getFileManager(),
274e5dd7070Spatrick                          Import.getOriginMap());
275e5dd7070Spatrick   auto ES = std::make_unique<ExternalASTMerger>(Target, Sources);
276e5dd7070Spatrick   CI.getASTContext().setExternalSource(ES.release());
277e5dd7070Spatrick   CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
278e5dd7070Spatrick }
279e5dd7070Spatrick 
BuildIndirect(CIAndOrigins & CI)280e5dd7070Spatrick CIAndOrigins BuildIndirect(CIAndOrigins &CI) {
281e5dd7070Spatrick   CIAndOrigins IndirectCI{init_convenience::BuildCompilerInstance()};
282e5dd7070Spatrick   auto ST = std::make_unique<SelectorTable>();
283e5dd7070Spatrick   auto BC = std::make_unique<Builtin::Context>();
284e5dd7070Spatrick   std::unique_ptr<ASTContext> AST = init_convenience::BuildASTContext(
285e5dd7070Spatrick       IndirectCI.getCompilerInstance(), *ST, *BC);
286e5dd7070Spatrick   IndirectCI.getCompilerInstance().setASTContext(AST.release());
287e5dd7070Spatrick   AddExternalSource(IndirectCI, CI);
288e5dd7070Spatrick   return IndirectCI;
289e5dd7070Spatrick }
290e5dd7070Spatrick 
ParseSource(const std::string & Path,CompilerInstance & CI,ASTConsumer & Consumer)291e5dd7070Spatrick llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI,
292e5dd7070Spatrick                         ASTConsumer &Consumer) {
293e5dd7070Spatrick   SourceManager &SM = CI.getSourceManager();
294a9ac8606Spatrick   auto FE = CI.getFileManager().getFileRef(Path);
295e5dd7070Spatrick   if (!FE) {
296a9ac8606Spatrick     llvm::consumeError(FE.takeError());
297e5dd7070Spatrick     return llvm::make_error<llvm::StringError>(
298a9ac8606Spatrick         llvm::Twine("No such file or directory: ", Path), std::error_code());
299e5dd7070Spatrick   }
300e5dd7070Spatrick   SM.setMainFileID(SM.createFileID(*FE, SourceLocation(), SrcMgr::C_User));
301e5dd7070Spatrick   ParseAST(CI.getPreprocessor(), &Consumer, CI.getASTContext());
302e5dd7070Spatrick   return llvm::Error::success();
303e5dd7070Spatrick }
304e5dd7070Spatrick 
Parse(const std::string & Path,llvm::MutableArrayRef<CIAndOrigins> Imports,bool ShouldDumpAST,bool ShouldDumpIR)305e5dd7070Spatrick llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
306e5dd7070Spatrick                                    llvm::MutableArrayRef<CIAndOrigins> Imports,
307e5dd7070Spatrick                                    bool ShouldDumpAST, bool ShouldDumpIR) {
308e5dd7070Spatrick   CIAndOrigins CI{init_convenience::BuildCompilerInstance()};
309e5dd7070Spatrick   auto ST = std::make_unique<SelectorTable>();
310e5dd7070Spatrick   auto BC = std::make_unique<Builtin::Context>();
311e5dd7070Spatrick   std::unique_ptr<ASTContext> AST =
312e5dd7070Spatrick       init_convenience::BuildASTContext(CI.getCompilerInstance(), *ST, *BC);
313e5dd7070Spatrick   CI.getCompilerInstance().setASTContext(AST.release());
314e5dd7070Spatrick   if (Imports.size())
315e5dd7070Spatrick     AddExternalSource(CI, Imports);
316e5dd7070Spatrick 
317e5dd7070Spatrick   std::vector<std::unique_ptr<ASTConsumer>> ASTConsumers;
318e5dd7070Spatrick 
319e5dd7070Spatrick   auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
320e5dd7070Spatrick   ASTConsumers.push_back(
321e5dd7070Spatrick       init_convenience::BuildCodeGen(CI.getCompilerInstance(), *LLVMCtx));
322e5dd7070Spatrick   auto &CG = *static_cast<CodeGenerator *>(ASTConsumers.back().get());
323e5dd7070Spatrick 
324e5dd7070Spatrick   if (ShouldDumpAST)
325ec727ea7Spatrick     ASTConsumers.push_back(CreateASTDumper(nullptr /*Dump to stdout.*/, "",
326ec727ea7Spatrick                                            true, false, false, false,
327e5dd7070Spatrick                                            clang::ADOF_Default));
328e5dd7070Spatrick 
329e5dd7070Spatrick   CI.getDiagnosticClient().BeginSourceFile(
330e5dd7070Spatrick       CI.getCompilerInstance().getLangOpts(),
331e5dd7070Spatrick       &CI.getCompilerInstance().getPreprocessor());
332e5dd7070Spatrick   MultiplexConsumer Consumers(std::move(ASTConsumers));
333e5dd7070Spatrick   Consumers.Initialize(CI.getASTContext());
334e5dd7070Spatrick 
335e5dd7070Spatrick   if (llvm::Error PE = ParseSource(Path, CI.getCompilerInstance(), Consumers))
336e5dd7070Spatrick     return std::move(PE);
337e5dd7070Spatrick   CI.getDiagnosticClient().EndSourceFile();
338e5dd7070Spatrick   if (ShouldDumpIR)
339e5dd7070Spatrick     CG.GetModule()->print(llvm::outs(), nullptr);
340e5dd7070Spatrick   if (CI.getDiagnosticClient().getNumErrors())
341e5dd7070Spatrick     return llvm::make_error<llvm::StringError>(
342e5dd7070Spatrick         "Errors occurred while parsing the expression.", std::error_code());
343e5dd7070Spatrick   return std::move(CI);
344e5dd7070Spatrick }
345e5dd7070Spatrick 
Forget(CIAndOrigins & CI,llvm::MutableArrayRef<CIAndOrigins> Imports)346e5dd7070Spatrick void Forget(CIAndOrigins &CI, llvm::MutableArrayRef<CIAndOrigins> Imports) {
347e5dd7070Spatrick   llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
348e5dd7070Spatrick   for (CIAndOrigins &Import : Imports)
349e5dd7070Spatrick     Sources.push_back({Import.getASTContext(), Import.getFileManager(),
350e5dd7070Spatrick                        Import.getOriginMap()});
351e5dd7070Spatrick   ExternalASTSource *Source = CI.CI->getASTContext().getExternalSource();
352e5dd7070Spatrick   auto *Merger = static_cast<ExternalASTMerger *>(Source);
353e5dd7070Spatrick   Merger->RemoveSources(Sources);
354e5dd7070Spatrick }
355e5dd7070Spatrick 
356e5dd7070Spatrick } // end namespace
357e5dd7070Spatrick 
main(int argc,const char ** argv)358e5dd7070Spatrick int main(int argc, const char **argv) {
359e5dd7070Spatrick   const bool DisableCrashReporting = true;
360e5dd7070Spatrick   llvm::sys::PrintStackTraceOnErrorSignal(argv[0], DisableCrashReporting);
361e5dd7070Spatrick   llvm::cl::ParseCommandLineOptions(argc, argv);
362e5dd7070Spatrick   std::vector<CIAndOrigins> ImportCIs;
363e5dd7070Spatrick   for (auto I : Imports) {
364e5dd7070Spatrick     llvm::Expected<CIAndOrigins> ImportCI = Parse(I, {}, false, false);
365e5dd7070Spatrick     if (auto E = ImportCI.takeError()) {
366a9ac8606Spatrick       llvm::errs() << "error: " << llvm::toString(std::move(E)) << "\n";
367e5dd7070Spatrick       exit(-1);
368e5dd7070Spatrick     }
369e5dd7070Spatrick     ImportCIs.push_back(std::move(*ImportCI));
370e5dd7070Spatrick   }
371e5dd7070Spatrick   std::vector<CIAndOrigins> IndirectCIs;
372e5dd7070Spatrick   if (!Direct || UseOrigins) {
373e5dd7070Spatrick     for (auto &ImportCI : ImportCIs) {
374e5dd7070Spatrick       CIAndOrigins IndirectCI = BuildIndirect(ImportCI);
375e5dd7070Spatrick       IndirectCIs.push_back(std::move(IndirectCI));
376e5dd7070Spatrick     }
377e5dd7070Spatrick   }
378e5dd7070Spatrick   if (UseOrigins)
379e5dd7070Spatrick     for (auto &ImportCI : ImportCIs)
380e5dd7070Spatrick       IndirectCIs.push_back(std::move(ImportCI));
381e5dd7070Spatrick   llvm::Expected<CIAndOrigins> ExpressionCI =
382e5dd7070Spatrick       Parse(Expression, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs,
383e5dd7070Spatrick             DumpAST, DumpIR);
384e5dd7070Spatrick   if (auto E = ExpressionCI.takeError()) {
385a9ac8606Spatrick     llvm::errs() << "error: " << llvm::toString(std::move(E)) << "\n";
386e5dd7070Spatrick     exit(-1);
387e5dd7070Spatrick   }
388e5dd7070Spatrick   Forget(*ExpressionCI, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs);
389e5dd7070Spatrick   return 0;
390e5dd7070Spatrick }
391