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