xref: /llvm-project/clang/tools/clang-import-test/clang-import-test.cpp (revision df9a14d7bbf1180e4f1474254c9d7ed6bcb4ce55)
1524b3c18SFangrui Song //===-- clang-import-test.cpp - ASTImporter/ExternalASTSource testbed -----===//
27d982509SSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67d982509SSean Callanan //
77d982509SSean Callanan //===----------------------------------------------------------------------===//
87d982509SSean Callanan 
97d982509SSean Callanan #include "clang/AST/ASTContext.h"
107d982509SSean Callanan #include "clang/AST/ASTImporter.h"
11b7160ca4SSean Callanan #include "clang/AST/DeclObjC.h"
12b7160ca4SSean Callanan #include "clang/AST/ExternalASTMerger.h"
137d982509SSean Callanan #include "clang/Basic/Builtins.h"
14e08464fbSReid Kleckner #include "clang/Basic/FileManager.h"
157d982509SSean Callanan #include "clang/Basic/IdentifierTable.h"
167d982509SSean Callanan #include "clang/Basic/SourceLocation.h"
177d982509SSean Callanan #include "clang/Basic/TargetInfo.h"
187d982509SSean Callanan #include "clang/Basic/TargetOptions.h"
197d982509SSean Callanan #include "clang/CodeGen/ModuleBuilder.h"
201eac879dSSean Callanan #include "clang/Driver/Types.h"
2119e07e13SLang Hames #include "clang/Frontend/ASTConsumers.h"
227d982509SSean Callanan #include "clang/Frontend/CompilerInstance.h"
2319e07e13SLang Hames #include "clang/Frontend/MultiplexConsumer.h"
247d982509SSean Callanan #include "clang/Frontend/TextDiagnosticBuffer.h"
257d982509SSean Callanan #include "clang/Lex/Lexer.h"
267d982509SSean Callanan #include "clang/Lex/Preprocessor.h"
277d982509SSean Callanan #include "clang/Parse/ParseAST.h"
287d982509SSean Callanan 
297d982509SSean Callanan #include "llvm/IR/LLVMContext.h"
302b3a54baSSean Callanan #include "llvm/IR/Module.h"
317d982509SSean Callanan #include "llvm/Support/CommandLine.h"
327d982509SSean Callanan #include "llvm/Support/Error.h"
337d982509SSean Callanan #include "llvm/Support/Signals.h"
34*df9a14d7SKadir Cetinkaya #include "llvm/Support/VirtualFileSystem.h"
35d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
367d982509SSean Callanan 
377d982509SSean Callanan #include <memory>
387d982509SSean Callanan #include <string>
397d982509SSean Callanan 
407d982509SSean Callanan using namespace clang;
417d982509SSean Callanan 
427d982509SSean Callanan static llvm::cl::opt<std::string> Expression(
437d982509SSean Callanan     "expression", llvm::cl::Required,
447d982509SSean Callanan     llvm::cl::desc("Path to a file containing the expression to parse"));
457d982509SSean Callanan 
467d982509SSean Callanan static llvm::cl::list<std::string>
47d86a206fSFangrui Song     Imports("import",
487d982509SSean Callanan             llvm::cl::desc("Path to a file containing declarations to import"));
497d982509SSean Callanan 
509092d479SSean Callanan static llvm::cl::opt<bool>
519092d479SSean Callanan     Direct("direct", llvm::cl::Optional,
529092d479SSean Callanan            llvm::cl::desc("Use the parsed declarations without indirection"));
539092d479SSean Callanan 
543df7258eSVedant Kumar static llvm::cl::opt<bool> UseOrigins(
553df7258eSVedant Kumar     "use-origins", llvm::cl::Optional,
563df7258eSVedant Kumar     llvm::cl::desc(
573df7258eSVedant Kumar         "Use DeclContext origin information for more accurate lookups"));
58967d4384SSean Callanan 
597d982509SSean Callanan static llvm::cl::list<std::string>
60d86a206fSFangrui Song     ClangArgs("Xcc",
617d982509SSean Callanan               llvm::cl::desc("Argument to pass to the CompilerInvocation"),
627d982509SSean Callanan               llvm::cl::CommaSeparated);
637d982509SSean Callanan 
641eac879dSSean Callanan static llvm::cl::opt<std::string>
651eac879dSSean Callanan     Input("x", llvm::cl::Optional,
661eac879dSSean Callanan           llvm::cl::desc("The language to parse (default: c++)"),
671eac879dSSean Callanan           llvm::cl::init("c++"));
681eac879dSSean Callanan 
6940568fecSAkira Hatanaka static llvm::cl::opt<bool> ObjCARC("objc-arc", llvm::cl::init(false),
7040568fecSAkira Hatanaka                                    llvm::cl::desc("Emable ObjC ARC"));
7140568fecSAkira Hatanaka 
72967d4384SSean Callanan static llvm::cl::opt<bool> DumpAST("dump-ast", llvm::cl::init(false),
7319e07e13SLang Hames                                    llvm::cl::desc("Dump combined AST"));
7419e07e13SLang Hames 
75967d4384SSean Callanan static llvm::cl::opt<bool> DumpIR("dump-ir", llvm::cl::init(false),
762b3a54baSSean Callanan                                   llvm::cl::desc("Dump IR from final parse"));
772b3a54baSSean Callanan 
787d982509SSean Callanan namespace init_convenience {
797d982509SSean Callanan class TestDiagnosticConsumer : public DiagnosticConsumer {
807d982509SSean Callanan private:
817d982509SSean Callanan   std::unique_ptr<TextDiagnosticBuffer> Passthrough;
827d982509SSean Callanan   const LangOptions *LangOpts = nullptr;
837d982509SSean Callanan 
847d982509SSean Callanan public:
857d982509SSean Callanan   TestDiagnosticConsumer()
862b3d49b6SJonas Devlieghere       : Passthrough(std::make_unique<TextDiagnosticBuffer>()) {}
877d982509SSean Callanan 
88a210f404SKazu Hirata   void BeginSourceFile(const LangOptions &LangOpts,
897d982509SSean Callanan                        const Preprocessor *PP = nullptr) override {
907d982509SSean Callanan     this->LangOpts = &LangOpts;
917d982509SSean Callanan     return Passthrough->BeginSourceFile(LangOpts, PP);
927d982509SSean Callanan   }
937d982509SSean Callanan 
94a210f404SKazu Hirata   void EndSourceFile() override {
957d982509SSean Callanan     this->LangOpts = nullptr;
967d982509SSean Callanan     Passthrough->EndSourceFile();
977d982509SSean Callanan   }
987d982509SSean Callanan 
99a210f404SKazu Hirata   bool IncludeInDiagnosticCounts() const override {
1007d982509SSean Callanan     return Passthrough->IncludeInDiagnosticCounts();
1017d982509SSean Callanan   }
1027d982509SSean Callanan 
1037d982509SSean Callanan private:
1047d982509SSean Callanan   static void PrintSourceForLocation(const SourceLocation &Loc,
1057d982509SSean Callanan                                      SourceManager &SM) {
1067d982509SSean Callanan     const char *LocData = SM.getCharacterData(Loc, /*Invalid=*/nullptr);
1077d982509SSean Callanan     unsigned LocColumn =
1087d982509SSean Callanan         SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1;
1097d982509SSean Callanan     FileID FID = SM.getFileID(Loc);
11000651981SDuncan P. N. Exon Smith     llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, Loc);
1117d982509SSean Callanan 
11200651981SDuncan P. N. Exon Smith     assert(LocData >= Buffer.getBufferStart() &&
11300651981SDuncan P. N. Exon Smith            LocData < Buffer.getBufferEnd());
1147d982509SSean Callanan 
1157d982509SSean Callanan     const char *LineBegin = LocData - LocColumn;
1167d982509SSean Callanan 
11700651981SDuncan P. N. Exon Smith     assert(LineBegin >= Buffer.getBufferStart());
1187d982509SSean Callanan 
1197d982509SSean Callanan     const char *LineEnd = nullptr;
1207d982509SSean Callanan 
1217d982509SSean Callanan     for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' &&
12200651981SDuncan P. N. Exon Smith                               LineEnd < Buffer.getBufferEnd();
1237d982509SSean Callanan          ++LineEnd)
1247d982509SSean Callanan       ;
1257d982509SSean Callanan 
1267d982509SSean Callanan     llvm::StringRef LineString(LineBegin, LineEnd - LineBegin);
1277d982509SSean Callanan 
1287d982509SSean Callanan     llvm::errs() << LineString << '\n';
1297d982509SSean Callanan     llvm::errs().indent(LocColumn);
1307d982509SSean Callanan     llvm::errs() << '^';
1311eac879dSSean Callanan     llvm::errs() << '\n';
1327d982509SSean Callanan   }
1337d982509SSean Callanan 
134a210f404SKazu Hirata   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1357d982509SSean Callanan                         const Diagnostic &Info) override {
1367d982509SSean Callanan     if (Info.hasSourceManager() && LangOpts) {
1377d982509SSean Callanan       SourceManager &SM = Info.getSourceManager();
1387d982509SSean Callanan 
1397d982509SSean Callanan       if (Info.getLocation().isValid()) {
1407d982509SSean Callanan         Info.getLocation().print(llvm::errs(), SM);
1417d982509SSean Callanan         llvm::errs() << ": ";
1427d982509SSean Callanan       }
1437d982509SSean Callanan 
1447d982509SSean Callanan       SmallString<16> DiagText;
1457d982509SSean Callanan       Info.FormatDiagnostic(DiagText);
1467d982509SSean Callanan       llvm::errs() << DiagText << '\n';
1477d982509SSean Callanan 
1487d982509SSean Callanan       if (Info.getLocation().isValid()) {
1497d982509SSean Callanan         PrintSourceForLocation(Info.getLocation(), SM);
1507d982509SSean Callanan       }
1517d982509SSean Callanan 
1527d982509SSean Callanan       for (const CharSourceRange &Range : Info.getRanges()) {
1537d982509SSean Callanan         bool Invalid = true;
1547d982509SSean Callanan         StringRef Ref = Lexer::getSourceText(Range, SM, *LangOpts, &Invalid);
1557d982509SSean Callanan         if (!Invalid) {
1567d982509SSean Callanan           llvm::errs() << Ref << '\n';
1577d982509SSean Callanan         }
1587d982509SSean Callanan       }
1597d982509SSean Callanan     }
1607d982509SSean Callanan     DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
1617d982509SSean Callanan   }
1627d982509SSean Callanan };
1637d982509SSean Callanan 
164967d4384SSean Callanan std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
1652b3d49b6SJonas Devlieghere   auto Ins = std::make_unique<CompilerInstance>();
1662b3d49b6SJonas Devlieghere   auto DC = std::make_unique<TestDiagnosticConsumer>();
1677d982509SSean Callanan   const bool ShouldOwnClient = true;
168*df9a14d7SKadir Cetinkaya   Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(),
169*df9a14d7SKadir Cetinkaya                          ShouldOwnClient);
1707d982509SSean Callanan 
1712b3d49b6SJonas Devlieghere   auto Inv = std::make_unique<CompilerInvocation>();
1727d982509SSean Callanan 
1731eac879dSSean Callanan   std::vector<const char *> ClangArgv(ClangArgs.size());
1741eac879dSSean Callanan   std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
1751eac879dSSean Callanan                  [](const std::string &s) -> const char * { return s.data(); });
1761fac68b0SDmitri Gribenko   CompilerInvocation::CreateFromArgs(*Inv, ClangArgv, Ins->getDiagnostics());
1777d982509SSean Callanan 
1781eac879dSSean Callanan   {
1791eac879dSSean Callanan     using namespace driver::types;
1801eac879dSSean Callanan     ID Id = lookupTypeForTypeSpecifier(Input.c_str());
1811eac879dSSean Callanan     assert(Id != TY_INVALID);
1821eac879dSSean Callanan     if (isCXX(Id)) {
1835746002eSJan Svoboda       Inv->getLangOpts().CPlusPlus = true;
1845746002eSJan Svoboda       Inv->getLangOpts().CPlusPlus11 = true;
1857d982509SSean Callanan       Inv->getHeaderSearchOpts().UseLibcxx = true;
1861eac879dSSean Callanan     }
1871eac879dSSean Callanan     if (isObjC(Id)) {
1885746002eSJan Svoboda       Inv->getLangOpts().ObjC = 1;
1891eac879dSSean Callanan     }
1901eac879dSSean Callanan   }
1915746002eSJan Svoboda   Inv->getLangOpts().ObjCAutoRefCount = ObjCARC;
19240568fecSAkira Hatanaka 
1935746002eSJan Svoboda   Inv->getLangOpts().Bool = true;
1945746002eSJan Svoboda   Inv->getLangOpts().WChar = true;
1955746002eSJan Svoboda   Inv->getLangOpts().Blocks = true;
1965746002eSJan Svoboda   Inv->getLangOpts().DebuggerSupport = true;
1975746002eSJan Svoboda   Inv->getLangOpts().SpellChecking = false;
1985746002eSJan Svoboda   Inv->getLangOpts().ThreadsafeStatics = false;
1995746002eSJan Svoboda   Inv->getLangOpts().AccessControl = false;
2005746002eSJan Svoboda   Inv->getLangOpts().DollarIdents = true;
2015746002eSJan Svoboda   Inv->getLangOpts().Exceptions = true;
2025746002eSJan Svoboda   Inv->getLangOpts().CXXExceptions = true;
203c705bb84SRaphael Isemann   // Needed for testing dynamic_cast.
2045746002eSJan Svoboda   Inv->getLangOpts().RTTI = true;
205ab49747fSKiran Chandramohan   Inv->getCodeGenOpts().setDebugInfo(llvm::codegenoptions::FullDebugInfo);
2067d982509SSean Callanan   Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
2077d982509SSean Callanan 
208ea4395ebSDavid Blaikie   Ins->setInvocation(std::move(Inv));
2097d982509SSean Callanan 
2107d982509SSean Callanan   TargetInfo *TI = TargetInfo::CreateTargetInfo(
2117d982509SSean Callanan       Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
2127d982509SSean Callanan   Ins->setTarget(TI);
213aaba3718SMelanie Blower   Ins->getTarget().adjust(Ins->getDiagnostics(), Ins->getLangOpts());
2147d982509SSean Callanan   Ins->createFileManager();
2157d982509SSean Callanan   Ins->createSourceManager(Ins->getFileManager());
2167d982509SSean Callanan   Ins->createPreprocessor(TU_Complete);
2177d982509SSean Callanan 
2187d982509SSean Callanan   return Ins;
2197d982509SSean Callanan }
2207d982509SSean Callanan 
2217d982509SSean Callanan std::unique_ptr<ASTContext>
2227d982509SSean Callanan BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) {
22311b47c10SVassil Vassilev   auto &PP = CI.getPreprocessor();
2242b3d49b6SJonas Devlieghere   auto AST = std::make_unique<ASTContext>(
2257d982509SSean Callanan       CI.getLangOpts(), CI.getSourceManager(),
22611b47c10SVassil Vassilev       PP.getIdentifierTable(), ST, BC, PP.TUKind);
2277d982509SSean Callanan   AST->InitBuiltinTypes(CI.getTarget());
2287d982509SSean Callanan   return AST;
2297d982509SSean Callanan }
2307d982509SSean Callanan 
2317d982509SSean Callanan std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
2327d982509SSean Callanan                                             llvm::LLVMContext &LLVMCtx) {
2337d982509SSean Callanan   StringRef ModuleName("$__module");
2347d982509SSean Callanan   return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
2358dfaecc4SArgyrios Kyrtzidis       CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(),
2368dfaecc4SArgyrios Kyrtzidis       CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
2378dfaecc4SArgyrios Kyrtzidis       LLVMCtx));
2387d982509SSean Callanan }
2393df7258eSVedant Kumar } // namespace init_convenience
2407d982509SSean Callanan 
2417d982509SSean Callanan namespace {
2427d982509SSean Callanan 
243967d4384SSean Callanan /// A container for a CompilerInstance (possibly with an ExternalASTMerger
244967d4384SSean Callanan /// attached to its ASTContext).
245967d4384SSean Callanan ///
246967d4384SSean Callanan /// Provides an accessor for the DeclContext origins associated with the
247967d4384SSean Callanan /// ExternalASTMerger (or an empty list of origins if no ExternalASTMerger is
248967d4384SSean Callanan /// attached).
249967d4384SSean Callanan ///
250967d4384SSean Callanan /// This is the main unit of parsed source code maintained by clang-import-test.
251967d4384SSean Callanan struct CIAndOrigins {
252967d4384SSean Callanan   using OriginMap = clang::ExternalASTMerger::OriginMap;
253967d4384SSean Callanan   std::unique_ptr<CompilerInstance> CI;
254967d4384SSean Callanan 
255967d4384SSean Callanan   ASTContext &getASTContext() { return CI->getASTContext(); }
256967d4384SSean Callanan   FileManager &getFileManager() { return CI->getFileManager(); }
257967d4384SSean Callanan   const OriginMap &getOriginMap() {
258034c0f24SPavel Labath     static const OriginMap EmptyOriginMap{};
259967d4384SSean Callanan     if (ExternalASTSource *Source = CI->getASTContext().getExternalSource())
260967d4384SSean Callanan       return static_cast<ExternalASTMerger *>(Source)->GetOrigins();
261967d4384SSean Callanan     return EmptyOriginMap;
262b7160ca4SSean Callanan   }
263967d4384SSean Callanan   DiagnosticConsumer &getDiagnosticClient() {
264967d4384SSean Callanan     return CI->getDiagnosticClient();
265967d4384SSean Callanan   }
266967d4384SSean Callanan   CompilerInstance &getCompilerInstance() { return *CI; }
267967d4384SSean Callanan };
268967d4384SSean Callanan 
269967d4384SSean Callanan void AddExternalSource(CIAndOrigins &CI,
270967d4384SSean Callanan                        llvm::MutableArrayRef<CIAndOrigins> Imports) {
271967d4384SSean Callanan   ExternalASTMerger::ImporterTarget Target(
272967d4384SSean Callanan       {CI.getASTContext(), CI.getFileManager()});
273967d4384SSean Callanan   llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
274967d4384SSean Callanan   for (CIAndOrigins &Import : Imports)
275cf628714SRaphael Isemann     Sources.emplace_back(Import.getASTContext(), Import.getFileManager(),
276cf628714SRaphael Isemann                          Import.getOriginMap());
2772b3d49b6SJonas Devlieghere   auto ES = std::make_unique<ExternalASTMerger>(Target, Sources);
278b7160ca4SSean Callanan   CI.getASTContext().setExternalSource(ES.release());
279b7160ca4SSean Callanan   CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
2807d982509SSean Callanan }
2817d982509SSean Callanan 
282967d4384SSean Callanan CIAndOrigins BuildIndirect(CIAndOrigins &CI) {
283967d4384SSean Callanan   CIAndOrigins IndirectCI{init_convenience::BuildCompilerInstance()};
2842b3d49b6SJonas Devlieghere   auto ST = std::make_unique<SelectorTable>();
2852b3d49b6SJonas Devlieghere   auto BC = std::make_unique<Builtin::Context>();
286967d4384SSean Callanan   std::unique_ptr<ASTContext> AST = init_convenience::BuildASTContext(
287967d4384SSean Callanan       IndirectCI.getCompilerInstance(), *ST, *BC);
288967d4384SSean Callanan   IndirectCI.getCompilerInstance().setASTContext(AST.release());
289967d4384SSean Callanan   AddExternalSource(IndirectCI, CI);
2909092d479SSean Callanan   return IndirectCI;
2919092d479SSean Callanan }
2929092d479SSean Callanan 
2937d982509SSean Callanan llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI,
29419e07e13SLang Hames                         ASTConsumer &Consumer) {
2957d982509SSean Callanan   SourceManager &SM = CI.getSourceManager();
2968c86197dSDuncan P. N. Exon Smith   auto FE = CI.getFileManager().getFileRef(Path);
2977d982509SSean Callanan   if (!FE) {
298e095959eSDuncan P. N. Exon Smith     llvm::consumeError(FE.takeError());
2997d982509SSean Callanan     return llvm::make_error<llvm::StringError>(
300e095959eSDuncan P. N. Exon Smith         llvm::Twine("No such file or directory: ", Path), std::error_code());
3017d982509SSean Callanan   }
3028d323d15SHarlan Haskins   SM.setMainFileID(SM.createFileID(*FE, SourceLocation(), SrcMgr::C_User));
30319e07e13SLang Hames   ParseAST(CI.getPreprocessor(), &Consumer, CI.getASTContext());
3047d982509SSean Callanan   return llvm::Error::success();
3057d982509SSean Callanan }
3067d982509SSean Callanan 
307967d4384SSean Callanan llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
308967d4384SSean Callanan                                    llvm::MutableArrayRef<CIAndOrigins> Imports,
3092b3a54baSSean Callanan                                    bool ShouldDumpAST, bool ShouldDumpIR) {
310967d4384SSean Callanan   CIAndOrigins CI{init_convenience::BuildCompilerInstance()};
3112b3d49b6SJonas Devlieghere   auto ST = std::make_unique<SelectorTable>();
3122b3d49b6SJonas Devlieghere   auto BC = std::make_unique<Builtin::Context>();
3137d982509SSean Callanan   std::unique_ptr<ASTContext> AST =
314967d4384SSean Callanan       init_convenience::BuildASTContext(CI.getCompilerInstance(), *ST, *BC);
315967d4384SSean Callanan   CI.getCompilerInstance().setASTContext(AST.release());
3169092d479SSean Callanan   if (Imports.size())
317967d4384SSean Callanan     AddExternalSource(CI, Imports);
3187d982509SSean Callanan 
31919e07e13SLang Hames   std::vector<std::unique_ptr<ASTConsumer>> ASTConsumers;
32019e07e13SLang Hames 
3212b3d49b6SJonas Devlieghere   auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
322967d4384SSean Callanan   ASTConsumers.push_back(
323967d4384SSean Callanan       init_convenience::BuildCodeGen(CI.getCompilerInstance(), *LLVMCtx));
3242b3a54baSSean Callanan   auto &CG = *static_cast<CodeGenerator *>(ASTConsumers.back().get());
32519e07e13SLang Hames 
32619e07e13SLang Hames   if (ShouldDumpAST)
327e135cf8aSRichard Smith     ASTConsumers.push_back(CreateASTDumper(nullptr /*Dump to stdout.*/, "",
328e135cf8aSRichard Smith                                            true, false, false, false,
3292ce598a4SAaron Ballman                                            clang::ADOF_Default));
3307d982509SSean Callanan 
331967d4384SSean Callanan   CI.getDiagnosticClient().BeginSourceFile(
332967d4384SSean Callanan       CI.getCompilerInstance().getLangOpts(),
333967d4384SSean Callanan       &CI.getCompilerInstance().getPreprocessor());
33419e07e13SLang Hames   MultiplexConsumer Consumers(std::move(ASTConsumers));
335967d4384SSean Callanan   Consumers.Initialize(CI.getASTContext());
33619e07e13SLang Hames 
337967d4384SSean Callanan   if (llvm::Error PE = ParseSource(Path, CI.getCompilerInstance(), Consumers))
3387d982509SSean Callanan     return std::move(PE);
339967d4384SSean Callanan   CI.getDiagnosticClient().EndSourceFile();
3402b3a54baSSean Callanan   if (ShouldDumpIR)
3412b3a54baSSean Callanan     CG.GetModule()->print(llvm::outs(), nullptr);
342967d4384SSean Callanan   if (CI.getDiagnosticClient().getNumErrors())
3437d982509SSean Callanan     return llvm::make_error<llvm::StringError>(
34451d3fb04SMalcolm Parsons         "Errors occurred while parsing the expression.", std::error_code());
3457d982509SSean Callanan   return std::move(CI);
3467d982509SSean Callanan }
347967d4384SSean Callanan 
348967d4384SSean Callanan void Forget(CIAndOrigins &CI, llvm::MutableArrayRef<CIAndOrigins> Imports) {
349967d4384SSean Callanan   llvm::SmallVector<ExternalASTMerger::ImporterSource, 3> Sources;
350967d4384SSean Callanan   for (CIAndOrigins &Import : Imports)
3513df7258eSVedant Kumar     Sources.push_back({Import.getASTContext(), Import.getFileManager(),
3523df7258eSVedant Kumar                        Import.getOriginMap()});
353967d4384SSean Callanan   ExternalASTSource *Source = CI.CI->getASTContext().getExternalSource();
354967d4384SSean Callanan   auto *Merger = static_cast<ExternalASTMerger *>(Source);
355967d4384SSean Callanan   Merger->RemoveSources(Sources);
3567d982509SSean Callanan }
357b7160ca4SSean Callanan 
3587d982509SSean Callanan } // end namespace
3597d982509SSean Callanan 
3607d982509SSean Callanan int main(int argc, const char **argv) {
3617d982509SSean Callanan   const bool DisableCrashReporting = true;
3627d982509SSean Callanan   llvm::sys::PrintStackTraceOnErrorSignal(argv[0], DisableCrashReporting);
3637d982509SSean Callanan   llvm::cl::ParseCommandLineOptions(argc, argv);
364967d4384SSean Callanan   std::vector<CIAndOrigins> ImportCIs;
3657d982509SSean Callanan   for (auto I : Imports) {
366967d4384SSean Callanan     llvm::Expected<CIAndOrigins> ImportCI = Parse(I, {}, false, false);
3677d982509SSean Callanan     if (auto E = ImportCI.takeError()) {
3688c86197dSDuncan P. N. Exon Smith       llvm::errs() << "error: " << llvm::toString(std::move(E)) << "\n";
3697d982509SSean Callanan       exit(-1);
370967d4384SSean Callanan     }
3717d982509SSean Callanan     ImportCIs.push_back(std::move(*ImportCI));
3727d982509SSean Callanan   }
373967d4384SSean Callanan   std::vector<CIAndOrigins> IndirectCIs;
374967d4384SSean Callanan   if (!Direct || UseOrigins) {
3759092d479SSean Callanan     for (auto &ImportCI : ImportCIs) {
376967d4384SSean Callanan       CIAndOrigins IndirectCI = BuildIndirect(ImportCI);
3776d565025SSean Callanan       IndirectCIs.push_back(std::move(IndirectCI));
3789092d479SSean Callanan     }
3799092d479SSean Callanan   }
380967d4384SSean Callanan   if (UseOrigins)
381967d4384SSean Callanan     for (auto &ImportCI : ImportCIs)
382967d4384SSean Callanan       IndirectCIs.push_back(std::move(ImportCI));
383967d4384SSean Callanan   llvm::Expected<CIAndOrigins> ExpressionCI =
384967d4384SSean Callanan       Parse(Expression, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs,
385967d4384SSean Callanan             DumpAST, DumpIR);
3867d982509SSean Callanan   if (auto E = ExpressionCI.takeError()) {
3878c86197dSDuncan P. N. Exon Smith     llvm::errs() << "error: " << llvm::toString(std::move(E)) << "\n";
3887d982509SSean Callanan     exit(-1);
389967d4384SSean Callanan   }
390967d4384SSean Callanan   Forget(*ExpressionCI, (Direct && !UseOrigins) ? ImportCIs : IndirectCIs);
3917d982509SSean Callanan   return 0;
3927d982509SSean Callanan }
393