1636404a3SDaniel Dunbar //===--- CompilerInstance.cpp ---------------------------------------------===// 2636404a3SDaniel Dunbar // 3636404a3SDaniel Dunbar // The LLVM Compiler Infrastructure 4636404a3SDaniel Dunbar // 5636404a3SDaniel Dunbar // This file is distributed under the University of Illinois Open Source 6636404a3SDaniel Dunbar // License. See LICENSE.TXT for details. 7636404a3SDaniel Dunbar // 8636404a3SDaniel Dunbar //===----------------------------------------------------------------------===// 9636404a3SDaniel Dunbar 10636404a3SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h" 110e93f017SDouglas Gregor #include "clang/Sema/Sema.h" 1256d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h" 13df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h" 14636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h" 15546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h" 16546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h" 17636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h" 184f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h" 19aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h" 20aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h" 21aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.h" 228b00dcb0SDavid Blaikie #include "clang/Frontend/ChainedDiagnosticConsumer.h" 234f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h" 24faeb1d46SDouglas Gregor #include "clang/Frontend/FrontendActions.h" 25f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h" 262083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h" 274610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h" 287d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h" 2969609dceSDavid Blaikie #include "clang/Frontend/VerifyDiagnosticConsumer.h" 30aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h" 31f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h" 32f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h" 33f6efe58dSMichael J. Spencer #include "llvm/Support/FileSystem.h" 34409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h" 357d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 36171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h" 375505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h" 388aaf4995SMichael J. Spencer #include "llvm/Support/Host.h" 398aaf4995SMichael J. Spencer #include "llvm/Support/Path.h" 408aaf4995SMichael J. Spencer #include "llvm/Support/Program.h" 418aaf4995SMichael J. Spencer #include "llvm/Support/Signals.h" 42f25faaafSMichael J. Spencer #include "llvm/Support/system_error.h" 4351e0b541SDouglas Gregor #include "llvm/Support/CrashRecoveryContext.h" 44321cdb85SDylan Noblesmith #include "llvm/Config/config.h" 4554a88810SDouglas Gregor 4654a88810SDouglas Gregor // Support for FileLockManager 4754a88810SDouglas Gregor #include <fstream> 4854a88810SDouglas Gregor #include <sys/types.h> 4954a88810SDouglas Gregor #include <sys/stat.h> 5054a88810SDouglas Gregor 51a04a46e8SDouglas Gregor #if LLVM_ON_WIN32 52a04a46e8SDouglas Gregor #include <windows.h> 53a04a46e8SDouglas Gregor #endif 5454a88810SDouglas Gregor #if LLVM_ON_UNIX 5554a88810SDouglas Gregor #include <unistd.h> 5654a88810SDouglas Gregor #endif 5754a88810SDouglas Gregor 58636404a3SDaniel Dunbar using namespace clang; 59636404a3SDaniel Dunbar 60e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance() 61925296b4SDouglas Gregor : Invocation(new CompilerInvocation()), ModuleManager(0) { 62636404a3SDaniel Dunbar } 63636404a3SDaniel Dunbar 64636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() { 65e922d9bdSDaniel Dunbar } 66e922d9bdSDaniel Dunbar 6768242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) { 685e14d39aSTed Kremenek Invocation = Value; 6968242254SDaniel Dunbar } 7068242254SDaniel Dunbar 719c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) { 727f95d26eSDouglas Gregor Diagnostics = Value; 73e01dc86dSDaniel Dunbar } 74e01dc86dSDaniel Dunbar 75e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) { 765e14d39aSTed Kremenek Target = Value; 77e01dc86dSDaniel Dunbar } 78e01dc86dSDaniel Dunbar 79e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) { 805e14d39aSTed Kremenek FileMgr = Value; 81e01dc86dSDaniel Dunbar } 82e01dc86dSDaniel Dunbar 83e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) { 845e14d39aSTed Kremenek SourceMgr = Value; 85e01dc86dSDaniel Dunbar } 86e01dc86dSDaniel Dunbar 875e14d39aSTed Kremenek void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; } 88e01dc86dSDaniel Dunbar 895e14d39aSTed Kremenek void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; } 90e01dc86dSDaniel Dunbar 910e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) { 920e93f017SDouglas Gregor TheSema.reset(S); 930e93f017SDouglas Gregor } 940e93f017SDouglas Gregor 9556d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 9656d9c293SDaniel Dunbar Consumer.reset(Value); 9756d9c293SDaniel Dunbar } 9856d9c293SDaniel Dunbar 99e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 100e01dc86dSDaniel Dunbar CompletionConsumer.reset(Value); 101e01dc86dSDaniel Dunbar } 102e01dc86dSDaniel Dunbar 1037d75afc5SDaniel Dunbar // Diagnostics 1047d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 10589c31490SAxel Naumann unsigned argc, const char* const *argv, 1069c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 1077d75afc5SDaniel Dunbar std::string ErrorInfo; 1080e62c1ccSChris Lattner llvm::OwningPtr<raw_ostream> OS( 109eeed0cc3SKovarththanan Rajaratnam new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo)); 1107d75afc5SDaniel Dunbar if (!ErrorInfo.empty()) { 1114a94ba56SKovarththanan Rajaratnam Diags.Report(diag::err_fe_unable_to_open_logfile) 1124a94ba56SKovarththanan Rajaratnam << DiagOpts.DumpBuildInformation << ErrorInfo; 1137d75afc5SDaniel Dunbar return; 1147d75afc5SDaniel Dunbar } 1157d75afc5SDaniel Dunbar 116520d1e6cSDaniel Dunbar (*OS) << "clang -cc1 command line arguments: "; 1177d75afc5SDaniel Dunbar for (unsigned i = 0; i != argc; ++i) 1187d75afc5SDaniel Dunbar (*OS) << argv[i] << ' '; 1197d75afc5SDaniel Dunbar (*OS) << '\n'; 1207d75afc5SDaniel Dunbar 1217d75afc5SDaniel Dunbar // Chain in a diagnostic client which will log the diagnostics. 122e2eefaecSDavid Blaikie DiagnosticConsumer *Logger = 123eeed0cc3SKovarththanan Rajaratnam new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true); 1248b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1257d75afc5SDaniel Dunbar } 1267d75afc5SDaniel Dunbar 1272083c32fSDaniel Dunbar static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, 1287b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts, 1299c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 1302083c32fSDaniel Dunbar std::string ErrorInfo; 1312083c32fSDaniel Dunbar bool OwnsStream = false; 1320e62c1ccSChris Lattner raw_ostream *OS = &llvm::errs(); 1332083c32fSDaniel Dunbar if (DiagOpts.DiagnosticLogFile != "-") { 1342083c32fSDaniel Dunbar // Create the output stream. 1352083c32fSDaniel Dunbar llvm::raw_fd_ostream *FileOS( 1362083c32fSDaniel Dunbar new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(), 13744d9ef78SDaniel Dunbar ErrorInfo, llvm::raw_fd_ostream::F_Append)); 1382083c32fSDaniel Dunbar if (!ErrorInfo.empty()) { 1392083c32fSDaniel Dunbar Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) 1402083c32fSDaniel Dunbar << DiagOpts.DumpBuildInformation << ErrorInfo; 1412083c32fSDaniel Dunbar } else { 1422083c32fSDaniel Dunbar FileOS->SetUnbuffered(); 1432083c32fSDaniel Dunbar FileOS->SetUseAtomicWrites(true); 1442083c32fSDaniel Dunbar OS = FileOS; 1452083c32fSDaniel Dunbar OwnsStream = true; 1462083c32fSDaniel Dunbar } 1472083c32fSDaniel Dunbar } 1482083c32fSDaniel Dunbar 1492083c32fSDaniel Dunbar // Chain in the diagnostic client which will log the diagnostics. 1507b83306dSDaniel Dunbar LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, 1512083c32fSDaniel Dunbar OwnsStream); 1527b83306dSDaniel Dunbar if (CodeGenOpts) 1537b83306dSDaniel Dunbar Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); 1548b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1552083c32fSDaniel Dunbar } 1562083c32fSDaniel Dunbar 1574610ea2bSTed Kremenek static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts, 1584610ea2bSTed Kremenek DiagnosticsEngine &Diags, 1594610ea2bSTed Kremenek StringRef OutputFile) { 1604610ea2bSTed Kremenek std::string ErrorInfo; 1614610ea2bSTed Kremenek llvm::OwningPtr<llvm::raw_fd_ostream> OS; 1624610ea2bSTed Kremenek OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, 1634610ea2bSTed Kremenek llvm::raw_fd_ostream::F_Binary)); 1644610ea2bSTed Kremenek 1654610ea2bSTed Kremenek if (!ErrorInfo.empty()) { 1664610ea2bSTed Kremenek Diags.Report(diag::warn_fe_serialized_diag_failure) 1674610ea2bSTed Kremenek << OutputFile << ErrorInfo; 1684610ea2bSTed Kremenek return; 1694610ea2bSTed Kremenek } 1704610ea2bSTed Kremenek 1714610ea2bSTed Kremenek DiagnosticConsumer *SerializedConsumer = 1724610ea2bSTed Kremenek clang::serialized_diags::create(OS.take(), Diags); 1734610ea2bSTed Kremenek 1744610ea2bSTed Kremenek 1754610ea2bSTed Kremenek Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), 1764610ea2bSTed Kremenek SerializedConsumer)); 1774610ea2bSTed Kremenek } 1784610ea2bSTed Kremenek 17944c6ee77SDouglas Gregor void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, 180e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 181d0e9e3a6SDouglas Gregor bool ShouldOwnClient, 182d0e9e3a6SDouglas Gregor bool ShouldCloneClient) { 1837b83306dSDaniel Dunbar Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client, 184d0e9e3a6SDouglas Gregor ShouldOwnClient, ShouldCloneClient, 185d0e9e3a6SDouglas Gregor &getCodeGenOpts()); 1867d75afc5SDaniel Dunbar } 1877d75afc5SDaniel Dunbar 1889c902b55SDavid Blaikie llvm::IntrusiveRefCntPtr<DiagnosticsEngine> 1897f95d26eSDouglas Gregor CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 19044c6ee77SDouglas Gregor int Argc, const char* const *Argv, 191e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 1922b9b4642SDouglas Gregor bool ShouldOwnClient, 193d0e9e3a6SDouglas Gregor bool ShouldCloneClient, 1947b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts) { 195d0040648SArgyrios Kyrtzidis llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 1969c902b55SDavid Blaikie llvm::IntrusiveRefCntPtr<DiagnosticsEngine> 1979c902b55SDavid Blaikie Diags(new DiagnosticsEngine(DiagID)); 1981b39a2edSDaniel Dunbar 1997d75afc5SDaniel Dunbar // Create the diagnostic client for reporting errors or for 2007d75afc5SDaniel Dunbar // implementing -verify. 201d0e9e3a6SDouglas Gregor if (Client) { 202d0e9e3a6SDouglas Gregor if (ShouldCloneClient) 203d0e9e3a6SDouglas Gregor Diags->setClient(Client->clone(*Diags), ShouldOwnClient); 20444c6ee77SDouglas Gregor else 205d0e9e3a6SDouglas Gregor Diags->setClient(Client, ShouldOwnClient); 206d0e9e3a6SDouglas Gregor } else 2072dd19f1dSDouglas Gregor Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); 20850ec0da0SDaniel Dunbar 20950ec0da0SDaniel Dunbar // Chain in -verify checker, if requested. 21050ec0da0SDaniel Dunbar if (Opts.VerifyDiagnostics) 21169609dceSDavid Blaikie Diags->setClient(new VerifyDiagnosticConsumer(*Diags)); 2127d75afc5SDaniel Dunbar 2132083c32fSDaniel Dunbar // Chain in -diagnostic-log-file dumper, if requested. 2142083c32fSDaniel Dunbar if (!Opts.DiagnosticLogFile.empty()) 2157b83306dSDaniel Dunbar SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags); 2162083c32fSDaniel Dunbar 2177d75afc5SDaniel Dunbar if (!Opts.DumpBuildInformation.empty()) 2184a94ba56SKovarththanan Rajaratnam SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); 2197d75afc5SDaniel Dunbar 2204610ea2bSTed Kremenek if (!Opts.DiagnosticSerializationFile.empty()) 2214610ea2bSTed Kremenek SetupSerializedDiagnostics(Opts, *Diags, 2224610ea2bSTed Kremenek Opts.DiagnosticSerializationFile); 2234610ea2bSTed Kremenek 2247d75afc5SDaniel Dunbar // Configure our handling of diagnostics. 2259ff84d9cSKovarththanan Rajaratnam ProcessWarningOptions(*Diags, Opts); 2267d75afc5SDaniel Dunbar 2277f95d26eSDouglas Gregor return Diags; 2287d75afc5SDaniel Dunbar } 2297d75afc5SDaniel Dunbar 2307d75afc5SDaniel Dunbar // File Manager 2317d75afc5SDaniel Dunbar 232546a676aSDaniel Dunbar void CompilerInstance::createFileManager() { 2335e14d39aSTed Kremenek FileMgr = new FileManager(getFileSystemOpts()); 234546a676aSDaniel Dunbar } 235546a676aSDaniel Dunbar 2367d75afc5SDaniel Dunbar // Source Manager 2377d75afc5SDaniel Dunbar 2385159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) { 2395e14d39aSTed Kremenek SourceMgr = new SourceManager(getDiagnostics(), FileMgr); 240546a676aSDaniel Dunbar } 241aaa148fdSDaniel Dunbar 2427d75afc5SDaniel Dunbar // Preprocessor 2437d75afc5SDaniel Dunbar 244aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() { 24508142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 246aaa148fdSDaniel Dunbar 247aaa148fdSDaniel Dunbar // Create a PTH manager if we are using some form of a token cache. 248aaa148fdSDaniel Dunbar PTHManager *PTHMgr = 0; 249d6ea9028SDaniel Dunbar if (!PPOpts.TokenCache.empty()) 25008142534SDouglas Gregor PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics()); 251aaa148fdSDaniel Dunbar 252aaa148fdSDaniel Dunbar // Create the Preprocessor. 253197ac203SDouglas Gregor HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(), 254197ac203SDouglas Gregor getDiagnostics()); 25583297dfcSDouglas Gregor PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(), 25608142534SDouglas Gregor getSourceManager(), *HeaderInfo, *this, PTHMgr, 257aaa148fdSDaniel Dunbar /*OwnsHeaderSearch=*/true); 258aaa148fdSDaniel Dunbar 259aaa148fdSDaniel Dunbar // Note that this is different then passing PTHMgr to Preprocessor's ctor. 260aaa148fdSDaniel Dunbar // That argument is used as the IdentifierInfoLookup argument to 261aaa148fdSDaniel Dunbar // IdentifierTable's ctor. 262aaa148fdSDaniel Dunbar if (PTHMgr) { 26308142534SDouglas Gregor PTHMgr->setPreprocessor(&*PP); 264aaa148fdSDaniel Dunbar PP->setPTHManager(PTHMgr); 265aaa148fdSDaniel Dunbar } 266aaa148fdSDaniel Dunbar 2677f6d60dcSDouglas Gregor if (PPOpts.DetailedRecord) 268998caeadSDouglas Gregor PP->createPreprocessingRecord( 269de81fc85SChandler Carruth PPOpts.DetailedRecordIncludesNestedMacroExpansions); 2707f6d60dcSDouglas Gregor 27108142534SDouglas Gregor InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts()); 272aaa148fdSDaniel Dunbar 2731735f4e7SDouglas Gregor // Set up the module path, including the hash for the 2741735f4e7SDouglas Gregor // module-creation options. 2751735f4e7SDouglas Gregor llvm::SmallString<256> SpecificModuleCache( 2761735f4e7SDouglas Gregor getHeaderSearchOpts().ModuleCachePath); 2771735f4e7SDouglas Gregor if (!getHeaderSearchOpts().DisableModuleHash) 2781735f4e7SDouglas Gregor llvm::sys::path::append(SpecificModuleCache, 2791735f4e7SDouglas Gregor getInvocation().getModuleHash()); 28097eec24bSDouglas Gregor PP->getHeaderSearchInfo().configureModules(SpecificModuleCache, 2817d106e42SDouglas Gregor getLangOpts().CurrentModule); 2821735f4e7SDouglas Gregor 283aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested. 28408142534SDouglas Gregor const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); 285aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty()) 286aaa148fdSDaniel Dunbar AttachDependencyFileGen(*PP, DepOpts); 287aaa148fdSDaniel Dunbar 28827734fdbSDaniel Dunbar // Handle generating header include information, if requested. 28927734fdbSDaniel Dunbar if (DepOpts.ShowHeaderIncludes) 29027734fdbSDaniel Dunbar AttachHeaderIncludeGen(*PP); 2911af1d275SDaniel Dunbar if (!DepOpts.HeaderIncludeOutputFile.empty()) { 2920e62c1ccSChris Lattner StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; 2931af1d275SDaniel Dunbar if (OutputPath == "-") 2941af1d275SDaniel Dunbar OutputPath = ""; 295fe908a80SDaniel Dunbar AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, 296fe908a80SDaniel Dunbar /*ShowDepth=*/false); 2971af1d275SDaniel Dunbar } 298aaa148fdSDaniel Dunbar } 299df3e30c4SDaniel Dunbar 300df3e30c4SDaniel Dunbar // ASTContext 301df3e30c4SDaniel Dunbar 302df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() { 303df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor(); 3045e14d39aSTed Kremenek Context = new ASTContext(getLangOpts(), PP.getSourceManager(), 305e8bbc121SDouglas Gregor &getTarget(), PP.getIdentifierTable(), 306df3e30c4SDaniel Dunbar PP.getSelectorTable(), PP.getBuiltinInfo(), 3075e14d39aSTed Kremenek /*size_reserve=*/ 0); 308df3e30c4SDaniel Dunbar } 309599313efSDaniel Dunbar 310599313efSDaniel Dunbar // ExternalASTSource 311599313efSDaniel Dunbar 3120e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path, 31307a89a83SSebastian Redl bool DisablePCHValidation, 314606c4ac3SDouglas Gregor bool DisableStatCache, 31507a89a83SSebastian Redl void *DeserializationListener){ 316599313efSDaniel Dunbar llvm::OwningPtr<ExternalASTSource> Source; 317009e7f20SSebastian Redl bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; 318599313efSDaniel Dunbar Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 319ce3a8293SDouglas Gregor DisablePCHValidation, 320606c4ac3SDouglas Gregor DisableStatCache, 32107a89a83SSebastian Redl getPreprocessor(), getASTContext(), 322009e7f20SSebastian Redl DeserializationListener, 323009e7f20SSebastian Redl Preamble)); 324925296b4SDouglas Gregor ModuleManager = static_cast<ASTReader*>(Source.get()); 325599313efSDaniel Dunbar getASTContext().setExternalSource(Source); 326599313efSDaniel Dunbar } 327599313efSDaniel Dunbar 328599313efSDaniel Dunbar ExternalASTSource * 3290e62c1ccSChris Lattner CompilerInstance::createPCHExternalASTSource(StringRef Path, 330599313efSDaniel Dunbar const std::string &Sysroot, 331ce3a8293SDouglas Gregor bool DisablePCHValidation, 332606c4ac3SDouglas Gregor bool DisableStatCache, 333599313efSDaniel Dunbar Preprocessor &PP, 33407a89a83SSebastian Redl ASTContext &Context, 335009e7f20SSebastian Redl void *DeserializationListener, 336009e7f20SSebastian Redl bool Preamble) { 3372c499f65SSebastian Redl llvm::OwningPtr<ASTReader> Reader; 3388835e03cSDouglas Gregor Reader.reset(new ASTReader(PP, Context, 339c567ba26SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 340606c4ac3SDouglas Gregor DisablePCHValidation, DisableStatCache)); 341599313efSDaniel Dunbar 34207a89a83SSebastian Redl Reader->setDeserializationListener( 3433e31c724SSebastian Redl static_cast<ASTDeserializationListener *>(DeserializationListener)); 344009e7f20SSebastian Redl switch (Reader->ReadAST(Path, 345a6895d8aSDouglas Gregor Preamble ? serialization::MK_Preamble 346a6895d8aSDouglas Gregor : serialization::MK_PCH)) { 3472c499f65SSebastian Redl case ASTReader::Success: 348599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the 349599313efSDaniel Dunbar // predefines buffer will be empty. 350599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines()); 351599313efSDaniel Dunbar return Reader.take(); 352599313efSDaniel Dunbar 3532c499f65SSebastian Redl case ASTReader::Failure: 354599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file. 355599313efSDaniel Dunbar break; 356599313efSDaniel Dunbar 3572c499f65SSebastian Redl case ASTReader::IgnorePCH: 358599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error. 359599313efSDaniel Dunbar break; 360599313efSDaniel Dunbar } 361599313efSDaniel Dunbar 362599313efSDaniel Dunbar return 0; 363599313efSDaniel Dunbar } 364f7093b5aSDaniel Dunbar 365f7093b5aSDaniel Dunbar // Code Completion 366f7093b5aSDaniel Dunbar 3678e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP, 3688e984da8SDouglas Gregor const std::string &Filename, 3698e984da8SDouglas Gregor unsigned Line, 3708e984da8SDouglas Gregor unsigned Column) { 3718e984da8SDouglas Gregor // Tell the source manager to chop off the given file at a specific 3728e984da8SDouglas Gregor // line and column. 3735159f616SChris Lattner const FileEntry *Entry = PP.getFileManager().getFile(Filename); 3748e984da8SDouglas Gregor if (!Entry) { 3758e984da8SDouglas Gregor PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 3768e984da8SDouglas Gregor << Filename; 3778e984da8SDouglas Gregor return true; 3788e984da8SDouglas Gregor } 3798e984da8SDouglas Gregor 3808e984da8SDouglas Gregor // Truncate the named file at the given line/column. 3818e984da8SDouglas Gregor PP.SetCodeCompletionPoint(Entry, Line, Column); 3828e984da8SDouglas Gregor return false; 3838e984da8SDouglas Gregor } 3848e984da8SDouglas Gregor 385f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() { 386f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 3878e984da8SDouglas Gregor if (!CompletionConsumer) { 388f7093b5aSDaniel Dunbar CompletionConsumer.reset( 389f7093b5aSDaniel Dunbar createCodeCompletionConsumer(getPreprocessor(), 390f7093b5aSDaniel Dunbar Loc.FileName, Loc.Line, Loc.Column, 391f7093b5aSDaniel Dunbar getFrontendOpts().ShowMacrosInCodeCompletion, 392f64acca2SDouglas Gregor getFrontendOpts().ShowCodePatternsInCodeCompletion, 39339982197SDouglas Gregor getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, 394f7093b5aSDaniel Dunbar llvm::outs())); 39500a0cf70SDouglas Gregor if (!CompletionConsumer) 39600a0cf70SDouglas Gregor return; 3978e984da8SDouglas Gregor } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName, 3988e984da8SDouglas Gregor Loc.Line, Loc.Column)) { 3998e984da8SDouglas Gregor CompletionConsumer.reset(); 4008e984da8SDouglas Gregor return; 4018e984da8SDouglas Gregor } 402f09935f1SDouglas Gregor 403f09935f1SDouglas Gregor if (CompletionConsumer->isOutputBinary() && 404f09935f1SDouglas Gregor llvm::sys::Program::ChangeStdoutToBinary()) { 405f09935f1SDouglas Gregor getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 406f09935f1SDouglas Gregor CompletionConsumer.reset(); 407f09935f1SDouglas Gregor } 408f7093b5aSDaniel Dunbar } 409f7093b5aSDaniel Dunbar 4105505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() { 4115505dff8SKovarththanan Rajaratnam FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 4125505dff8SKovarththanan Rajaratnam } 4135505dff8SKovarththanan Rajaratnam 414f7093b5aSDaniel Dunbar CodeCompleteConsumer * 415f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 416f7093b5aSDaniel Dunbar const std::string &Filename, 417f7093b5aSDaniel Dunbar unsigned Line, 418f7093b5aSDaniel Dunbar unsigned Column, 419f7093b5aSDaniel Dunbar bool ShowMacros, 420f64acca2SDouglas Gregor bool ShowCodePatterns, 42139982197SDouglas Gregor bool ShowGlobals, 4220e62c1ccSChris Lattner raw_ostream &OS) { 4238e984da8SDouglas Gregor if (EnableCodeCompletion(PP, Filename, Line, Column)) 424f7093b5aSDaniel Dunbar return 0; 425f7093b5aSDaniel Dunbar 426f7093b5aSDaniel Dunbar // Set up the creation routine for code-completion. 42739982197SDouglas Gregor return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, 42839982197SDouglas Gregor ShowGlobals, OS); 429f7093b5aSDaniel Dunbar } 430566eeb2dSDaniel Dunbar 43169f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind, 4320e93f017SDouglas Gregor CodeCompleteConsumer *CompletionConsumer) { 4330e93f017SDouglas Gregor TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(), 43469f74f80SDouglas Gregor TUKind, CompletionConsumer)); 4350e93f017SDouglas Gregor } 4360e93f017SDouglas Gregor 437566eeb2dSDaniel Dunbar // Output Files 438566eeb2dSDaniel Dunbar 439d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) { 440d0599970SArgyrios Kyrtzidis assert(OutFile.OS && "Attempt to add empty stream to output list!"); 441d0599970SArgyrios Kyrtzidis OutputFiles.push_back(OutFile); 442566eeb2dSDaniel Dunbar } 443566eeb2dSDaniel Dunbar 4441c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) { 445d0599970SArgyrios Kyrtzidis for (std::list<OutputFile>::iterator 446566eeb2dSDaniel Dunbar it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 447d0599970SArgyrios Kyrtzidis delete it->OS; 448d0599970SArgyrios Kyrtzidis if (!it->TempFilename.empty()) { 449b5c356a4SAnders Carlsson if (EraseFiles) { 450b5c356a4SAnders Carlsson bool existed; 451b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 452b5c356a4SAnders Carlsson } else { 453b5c356a4SAnders Carlsson llvm::SmallString<128> NewOutFile(it->Filename); 454b5c356a4SAnders Carlsson 45571731d6bSArgyrios Kyrtzidis // If '-working-directory' was passed, the output filename should be 45671731d6bSArgyrios Kyrtzidis // relative to that. 4579ba8fb1eSAnders Carlsson FileMgr->FixupRelativePath(NewOutFile); 458b5c356a4SAnders Carlsson if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, 459b5c356a4SAnders Carlsson NewOutFile.str())) { 460d0599970SArgyrios Kyrtzidis getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) 461b5c356a4SAnders Carlsson << it->TempFilename << it->Filename << ec.message(); 462b5c356a4SAnders Carlsson 463b5c356a4SAnders Carlsson bool existed; 464b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 465d0599970SArgyrios Kyrtzidis } 466d0599970SArgyrios Kyrtzidis } 467d0599970SArgyrios Kyrtzidis } else if (!it->Filename.empty() && EraseFiles) 468d0599970SArgyrios Kyrtzidis llvm::sys::Path(it->Filename).eraseFromDisk(); 469d0599970SArgyrios Kyrtzidis 470566eeb2dSDaniel Dunbar } 471566eeb2dSDaniel Dunbar OutputFiles.clear(); 472566eeb2dSDaniel Dunbar } 473566eeb2dSDaniel Dunbar 474420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 475420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary, 4760e62c1ccSChris Lattner StringRef InFile, 4770e62c1ccSChris Lattner StringRef Extension) { 478420b0f1bSDaniel Dunbar return createOutputFile(getFrontendOpts().OutputFile, Binary, 479e326f9bbSDaniel Dunbar /*RemoveFileOnSignal=*/true, InFile, Extension); 480420b0f1bSDaniel Dunbar } 481420b0f1bSDaniel Dunbar 482420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 4830e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 484e326f9bbSDaniel Dunbar bool Binary, bool RemoveFileOnSignal, 4850e62c1ccSChris Lattner StringRef InFile, 48608a2bfd2SArgyrios Kyrtzidis StringRef Extension, 48708a2bfd2SArgyrios Kyrtzidis bool UseTemporary) { 488d0599970SArgyrios Kyrtzidis std::string Error, OutputPathName, TempPathName; 489420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 490e326f9bbSDaniel Dunbar RemoveFileOnSignal, 491420b0f1bSDaniel Dunbar InFile, Extension, 49208a2bfd2SArgyrios Kyrtzidis UseTemporary, 493d0599970SArgyrios Kyrtzidis &OutputPathName, 494d0599970SArgyrios Kyrtzidis &TempPathName); 495420b0f1bSDaniel Dunbar if (!OS) { 4967554699aSDaniel Dunbar getDiagnostics().Report(diag::err_fe_unable_to_open_output) 4977554699aSDaniel Dunbar << OutputPath << Error; 4987554699aSDaniel Dunbar return 0; 499420b0f1bSDaniel Dunbar } 500420b0f1bSDaniel Dunbar 501420b0f1bSDaniel Dunbar // Add the output file -- but don't try to remove "-", since this means we are 502420b0f1bSDaniel Dunbar // using stdin. 503d0599970SArgyrios Kyrtzidis addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", 504d0599970SArgyrios Kyrtzidis TempPathName, OS)); 505420b0f1bSDaniel Dunbar 506420b0f1bSDaniel Dunbar return OS; 507420b0f1bSDaniel Dunbar } 508420b0f1bSDaniel Dunbar 509420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 5100e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 511420b0f1bSDaniel Dunbar std::string &Error, 512420b0f1bSDaniel Dunbar bool Binary, 513e326f9bbSDaniel Dunbar bool RemoveFileOnSignal, 5140e62c1ccSChris Lattner StringRef InFile, 5150e62c1ccSChris Lattner StringRef Extension, 51608a2bfd2SArgyrios Kyrtzidis bool UseTemporary, 517d0599970SArgyrios Kyrtzidis std::string *ResultPathName, 518d0599970SArgyrios Kyrtzidis std::string *TempPathName) { 519d0599970SArgyrios Kyrtzidis std::string OutFile, TempFile; 520420b0f1bSDaniel Dunbar if (!OutputPath.empty()) { 521420b0f1bSDaniel Dunbar OutFile = OutputPath; 522420b0f1bSDaniel Dunbar } else if (InFile == "-") { 523420b0f1bSDaniel Dunbar OutFile = "-"; 524420b0f1bSDaniel Dunbar } else if (!Extension.empty()) { 525420b0f1bSDaniel Dunbar llvm::sys::Path Path(InFile); 526420b0f1bSDaniel Dunbar Path.eraseSuffix(); 527420b0f1bSDaniel Dunbar Path.appendSuffix(Extension); 528420b0f1bSDaniel Dunbar OutFile = Path.str(); 529420b0f1bSDaniel Dunbar } else { 530420b0f1bSDaniel Dunbar OutFile = "-"; 531420b0f1bSDaniel Dunbar } 532420b0f1bSDaniel Dunbar 53308a2bfd2SArgyrios Kyrtzidis llvm::OwningPtr<llvm::raw_fd_ostream> OS; 53408a2bfd2SArgyrios Kyrtzidis std::string OSFile; 53508a2bfd2SArgyrios Kyrtzidis 53608a2bfd2SArgyrios Kyrtzidis if (UseTemporary && OutFile != "-") { 537d0599970SArgyrios Kyrtzidis llvm::sys::Path OutPath(OutFile); 538d0599970SArgyrios Kyrtzidis // Only create the temporary if we can actually write to OutPath, otherwise 539d0599970SArgyrios Kyrtzidis // we want to fail early. 540f6efe58dSMichael J. Spencer bool Exists; 541f6efe58dSMichael J. Spencer if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) || 542d0599970SArgyrios Kyrtzidis (OutPath.isRegularFile() && OutPath.canWrite())) { 543d0599970SArgyrios Kyrtzidis // Create a temporary file. 54408a2bfd2SArgyrios Kyrtzidis llvm::SmallString<128> TempPath; 54508a2bfd2SArgyrios Kyrtzidis TempPath = OutFile; 54608a2bfd2SArgyrios Kyrtzidis TempPath += "-%%%%%%%%"; 54708a2bfd2SArgyrios Kyrtzidis int fd; 54808a2bfd2SArgyrios Kyrtzidis if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, 54908a2bfd2SArgyrios Kyrtzidis /*makeAbsolute=*/false) == llvm::errc::success) { 55008a2bfd2SArgyrios Kyrtzidis OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); 55108a2bfd2SArgyrios Kyrtzidis OSFile = TempFile = TempPath.str(); 55208a2bfd2SArgyrios Kyrtzidis } 553d0599970SArgyrios Kyrtzidis } 554d0599970SArgyrios Kyrtzidis } 555d0599970SArgyrios Kyrtzidis 55608a2bfd2SArgyrios Kyrtzidis if (!OS) { 55708a2bfd2SArgyrios Kyrtzidis OSFile = OutFile; 55808a2bfd2SArgyrios Kyrtzidis OS.reset( 559d0599970SArgyrios Kyrtzidis new llvm::raw_fd_ostream(OSFile.c_str(), Error, 5602eaef18eSDaniel Dunbar (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 5612eaef18eSDaniel Dunbar if (!Error.empty()) 562420b0f1bSDaniel Dunbar return 0; 56308a2bfd2SArgyrios Kyrtzidis } 564420b0f1bSDaniel Dunbar 565d0599970SArgyrios Kyrtzidis // Make sure the out stream file gets removed if we crash. 566e326f9bbSDaniel Dunbar if (RemoveFileOnSignal) 567d0599970SArgyrios Kyrtzidis llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); 568d0599970SArgyrios Kyrtzidis 569420b0f1bSDaniel Dunbar if (ResultPathName) 570420b0f1bSDaniel Dunbar *ResultPathName = OutFile; 571d0599970SArgyrios Kyrtzidis if (TempPathName) 572d0599970SArgyrios Kyrtzidis *TempPathName = TempFile; 573420b0f1bSDaniel Dunbar 5742eaef18eSDaniel Dunbar return OS.take(); 575420b0f1bSDaniel Dunbar } 576409e890fSDaniel Dunbar 577409e890fSDaniel Dunbar // Initialization Utilities 578409e890fSDaniel Dunbar 5790e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile) { 580409e890fSDaniel Dunbar return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(), 581409e890fSDaniel Dunbar getSourceManager(), getFrontendOpts()); 582409e890fSDaniel Dunbar } 583409e890fSDaniel Dunbar 5840e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile, 5859c902b55SDavid Blaikie DiagnosticsEngine &Diags, 586409e890fSDaniel Dunbar FileManager &FileMgr, 587409e890fSDaniel Dunbar SourceManager &SourceMgr, 588409e890fSDaniel Dunbar const FrontendOptions &Opts) { 5897c06d866SArgyrios Kyrtzidis // Figure out where to get and map in the main file. 5907c06d866SArgyrios Kyrtzidis if (InputFile != "-") { 5915159f616SChris Lattner const FileEntry *File = FileMgr.getFile(InputFile); 59252765215SDan Gohman if (!File) { 593409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile; 594409e890fSDaniel Dunbar return false; 595409e890fSDaniel Dunbar } 59652765215SDan Gohman SourceMgr.createMainFileID(File); 597409e890fSDaniel Dunbar } else { 598d9da7a1fSMichael J. Spencer llvm::OwningPtr<llvm::MemoryBuffer> SB; 599d9da7a1fSMichael J. Spencer if (llvm::MemoryBuffer::getSTDIN(SB)) { 600f25faaafSMichael J. Spencer // FIXME: Give ec.message() in this diag. 601409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading_stdin); 602409e890fSDaniel Dunbar return false; 603409e890fSDaniel Dunbar } 6042f76cd75SDan Gohman const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), 6055159f616SChris Lattner SB->getBufferSize(), 0); 6062f76cd75SDan Gohman SourceMgr.createMainFileID(File); 607d9da7a1fSMichael J. Spencer SourceMgr.overrideFileContents(File, SB.take()); 608409e890fSDaniel Dunbar } 609409e890fSDaniel Dunbar 61052765215SDan Gohman assert(!SourceMgr.getMainFileID().isInvalid() && 61152765215SDan Gohman "Couldn't establish MainFileID!"); 612409e890fSDaniel Dunbar return true; 613409e890fSDaniel Dunbar } 6144f2bc55dSDaniel Dunbar 6154f2bc55dSDaniel Dunbar // High-Level Operations 6164f2bc55dSDaniel Dunbar 6174f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 6184f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 6194f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 6204f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 6214f2bc55dSDaniel Dunbar 6224f2bc55dSDaniel Dunbar // FIXME: Take this as an argument, once all the APIs we used have moved to 6234f2bc55dSDaniel Dunbar // taking it as an input instead of hard-coding llvm::errs. 6240e62c1ccSChris Lattner raw_ostream &OS = llvm::errs(); 6254f2bc55dSDaniel Dunbar 6264f2bc55dSDaniel Dunbar // Create the target instance. 6274f2bc55dSDaniel Dunbar setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 6284f2bc55dSDaniel Dunbar if (!hasTarget()) 6294f2bc55dSDaniel Dunbar return false; 6304f2bc55dSDaniel Dunbar 6314f2bc55dSDaniel Dunbar // Inform the target of the language options. 6324f2bc55dSDaniel Dunbar // 6334f2bc55dSDaniel Dunbar // FIXME: We shouldn't need to do this, the target should be immutable once 6344f2bc55dSDaniel Dunbar // created. This complexity should be lifted elsewhere. 6354f2bc55dSDaniel Dunbar getTarget().setForcedLangOptions(getLangOpts()); 6364f2bc55dSDaniel Dunbar 6374f2bc55dSDaniel Dunbar // Validate/process some options. 6384f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose) 6394f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING 6404f2bc55dSDaniel Dunbar << " based upon " << PACKAGE_STRING 6418188c8a1SSebastian Pop << " default target " << llvm::sys::getDefaultTargetTriple() << "\n"; 6424f2bc55dSDaniel Dunbar 6434f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowTimers) 6444f2bc55dSDaniel Dunbar createFrontendTimer(); 6454f2bc55dSDaniel Dunbar 646171b780cSDouglas Gregor if (getFrontendOpts().ShowStats) 647171b780cSDouglas Gregor llvm::EnableStatistics(); 648171b780cSDouglas Gregor 6494f2bc55dSDaniel Dunbar for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 650ac42ec6fSDouglas Gregor const std::string &InFile = getFrontendOpts().Inputs[i].second; 6514f2bc55dSDaniel Dunbar 6524f2bc55dSDaniel Dunbar // Reset the ID tables if we are reusing the SourceManager. 653aed46fcbSDaniel Dunbar if (hasSourceManager()) 6544f2bc55dSDaniel Dunbar getSourceManager().clearIDTables(); 6554f2bc55dSDaniel Dunbar 656ac42ec6fSDouglas Gregor if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) { 6574f2bc55dSDaniel Dunbar Act.Execute(); 6584f2bc55dSDaniel Dunbar Act.EndSourceFile(); 6594f2bc55dSDaniel Dunbar } 6604f2bc55dSDaniel Dunbar } 6614f2bc55dSDaniel Dunbar 662198cb4dfSChris Lattner if (getDiagnosticOpts().ShowCarets) { 663c79346a5SArgyrios Kyrtzidis // We can have multiple diagnostics sharing one diagnostic client. 664c79346a5SArgyrios Kyrtzidis // Get the total number of warnings/errors from the client. 665c79346a5SArgyrios Kyrtzidis unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); 666c79346a5SArgyrios Kyrtzidis unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); 667198cb4dfSChris Lattner 668198cb4dfSChris Lattner if (NumWarnings) 669198cb4dfSChris Lattner OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); 670198cb4dfSChris Lattner if (NumWarnings && NumErrors) 671198cb4dfSChris Lattner OS << " and "; 672198cb4dfSChris Lattner if (NumErrors) 673198cb4dfSChris Lattner OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); 674198cb4dfSChris Lattner if (NumWarnings || NumErrors) 675198cb4dfSChris Lattner OS << " generated.\n"; 676198cb4dfSChris Lattner } 6774f2bc55dSDaniel Dunbar 678aed46fcbSDaniel Dunbar if (getFrontendOpts().ShowStats && hasFileManager()) { 6794f2bc55dSDaniel Dunbar getFileManager().PrintStats(); 6804f2bc55dSDaniel Dunbar OS << "\n"; 6814f2bc55dSDaniel Dunbar } 6824f2bc55dSDaniel Dunbar 683bc467933SArgyrios Kyrtzidis return !getDiagnostics().getClient()->getNumErrors(); 6844f2bc55dSDaniel Dunbar } 6854f2bc55dSDaniel Dunbar 686faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language 687faeb1d46SDouglas Gregor /// options. 688faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { 689faeb1d46SDouglas Gregor if (LangOpts.OpenCL) 690faeb1d46SDouglas Gregor return IK_OpenCL; 691faeb1d46SDouglas Gregor if (LangOpts.CUDA) 692faeb1d46SDouglas Gregor return IK_CUDA; 693faeb1d46SDouglas Gregor if (LangOpts.ObjC1) 694faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC; 695faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_CXX : IK_C; 696faeb1d46SDouglas Gregor } 697faeb1d46SDouglas Gregor 69851e0b541SDouglas Gregor namespace { 69951e0b541SDouglas Gregor struct CompileModuleData { 70051e0b541SDouglas Gregor CompilerInstance &Instance; 701ac42ec6fSDouglas Gregor GeneratePCHAction &CreateModuleAction; 70251e0b541SDouglas Gregor }; 70351e0b541SDouglas Gregor } 70451e0b541SDouglas Gregor 70551e0b541SDouglas Gregor /// \brief Helper function that executes the module-generating action under 70651e0b541SDouglas Gregor /// a crash recovery context. 70751e0b541SDouglas Gregor static void doCompileModule(void *UserData) { 70851e0b541SDouglas Gregor CompileModuleData &Data = *reinterpret_cast<CompileModuleData *>(UserData); 70951e0b541SDouglas Gregor Data.Instance.ExecuteAction(Data.CreateModuleAction); 71051e0b541SDouglas Gregor } 71151e0b541SDouglas Gregor 71254a88810SDouglas Gregor namespace { 713*514b636aSDouglas Gregor struct CompileModuleMapData { 714*514b636aSDouglas Gregor CompilerInstance &Instance; 715*514b636aSDouglas Gregor GenerateModuleAction &CreateModuleAction; 716*514b636aSDouglas Gregor }; 717*514b636aSDouglas Gregor } 718*514b636aSDouglas Gregor 719*514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under 720*514b636aSDouglas Gregor /// a crash recovery context. 721*514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) { 722*514b636aSDouglas Gregor CompileModuleMapData &Data 723*514b636aSDouglas Gregor = *reinterpret_cast<CompileModuleMapData *>(UserData); 724*514b636aSDouglas Gregor Data.Instance.ExecuteAction(Data.CreateModuleAction); 725*514b636aSDouglas Gregor } 726*514b636aSDouglas Gregor 727*514b636aSDouglas Gregor namespace { 72854a88810SDouglas Gregor /// \brief Class that manages the creation of a lock file to aid 72954a88810SDouglas Gregor /// implicit coordination between different processes. 73054a88810SDouglas Gregor /// 73154a88810SDouglas Gregor /// The implicit coordination works by creating a ".lock" file alongside 73254a88810SDouglas Gregor /// the file that we're coordinating for, using the atomicity of the file 73354a88810SDouglas Gregor /// system to ensure that only a single process can create that ".lock" file. 73454a88810SDouglas Gregor /// When the lock file is removed, the owning process has finished the 73554a88810SDouglas Gregor /// operation. 73654a88810SDouglas Gregor class LockFileManager { 73754a88810SDouglas Gregor public: 73854a88810SDouglas Gregor /// \brief Describes the state of a lock file. 73954a88810SDouglas Gregor enum LockFileState { 74054a88810SDouglas Gregor /// \brief The lock file has been created and is owned by this instance 74154a88810SDouglas Gregor /// of the object. 74254a88810SDouglas Gregor LFS_Owned, 74354a88810SDouglas Gregor /// \brief The lock file already exists and is owned by some other 74454a88810SDouglas Gregor /// instance. 74554a88810SDouglas Gregor LFS_Shared, 74654a88810SDouglas Gregor /// \brief An error occurred while trying to create or find the lock 74754a88810SDouglas Gregor /// file. 74854a88810SDouglas Gregor LFS_Error 74954a88810SDouglas Gregor }; 75054a88810SDouglas Gregor 75154a88810SDouglas Gregor private: 75254a88810SDouglas Gregor llvm::SmallString<128> LockFileName; 75354a88810SDouglas Gregor llvm::SmallString<128> UniqueLockFileName; 75454a88810SDouglas Gregor 75554a88810SDouglas Gregor llvm::Optional<std::pair<std::string, int> > Owner; 75654a88810SDouglas Gregor llvm::Optional<llvm::error_code> Error; 75754a88810SDouglas Gregor 75854a88810SDouglas Gregor LockFileManager(const LockFileManager &); 75954a88810SDouglas Gregor LockFileManager &operator=(const LockFileManager &); 76054a88810SDouglas Gregor 76154a88810SDouglas Gregor static llvm::Optional<std::pair<std::string, int> > 76254a88810SDouglas Gregor readLockFile(StringRef LockFileName); 76354a88810SDouglas Gregor 76454a88810SDouglas Gregor static bool processStillExecuting(StringRef Hostname, int PID); 76554a88810SDouglas Gregor 76654a88810SDouglas Gregor public: 76754a88810SDouglas Gregor 76854a88810SDouglas Gregor LockFileManager(StringRef FileName); 76954a88810SDouglas Gregor ~LockFileManager(); 77054a88810SDouglas Gregor 77154a88810SDouglas Gregor /// \brief Determine the state of the lock file. 77254a88810SDouglas Gregor LockFileState getState() const; 77354a88810SDouglas Gregor 77454a88810SDouglas Gregor operator LockFileState() const { return getState(); } 77554a88810SDouglas Gregor 77654a88810SDouglas Gregor /// \brief For a shared lock, wait until the owner releases the lock. 77754a88810SDouglas Gregor void waitForUnlock(); 77854a88810SDouglas Gregor }; 77954a88810SDouglas Gregor } 78054a88810SDouglas Gregor 78154a88810SDouglas Gregor /// \brief Attempt to read the lock file with the given name, if it exists. 78254a88810SDouglas Gregor /// 78354a88810SDouglas Gregor /// \param LockFileName The name of the lock file to read. 78454a88810SDouglas Gregor /// 78554a88810SDouglas Gregor /// \returns The process ID of the process that owns this lock file 78654a88810SDouglas Gregor llvm::Optional<std::pair<std::string, int> > 78754a88810SDouglas Gregor LockFileManager::readLockFile(StringRef LockFileName) { 78854a88810SDouglas Gregor // Check whether the lock file exists. If not, clearly there's nothing 78954a88810SDouglas Gregor // to read, so we just return. 79054a88810SDouglas Gregor bool Exists = false; 79154a88810SDouglas Gregor if (llvm::sys::fs::exists(LockFileName, Exists) || !Exists) 79254a88810SDouglas Gregor return llvm::Optional<std::pair<std::string, int> >(); 79354a88810SDouglas Gregor 79454a88810SDouglas Gregor // Read the owning host and PID out of the lock file. If it appears that the 79554a88810SDouglas Gregor // owning process is dead, the lock file is invalid. 79654a88810SDouglas Gregor int PID = 0; 79754a88810SDouglas Gregor std::string Hostname; 79854a88810SDouglas Gregor std::ifstream Input(LockFileName.str().c_str()); 79954a88810SDouglas Gregor if (Input >> Hostname >> PID && PID > 0 && 80054a88810SDouglas Gregor processStillExecuting(Hostname, PID)) 80154a88810SDouglas Gregor return std::make_pair(Hostname, PID); 80254a88810SDouglas Gregor 80354a88810SDouglas Gregor // Delete the lock file. It's invalid anyway. 80454a88810SDouglas Gregor bool Existed; 80554a88810SDouglas Gregor llvm::sys::fs::remove(LockFileName, Existed); 80654a88810SDouglas Gregor return llvm::Optional<std::pair<std::string, int> >(); 80754a88810SDouglas Gregor } 80854a88810SDouglas Gregor 80954a88810SDouglas Gregor bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) { 81054a88810SDouglas Gregor #if LLVM_ON_UNIX 81154a88810SDouglas Gregor char MyHostname[256]; 81254a88810SDouglas Gregor MyHostname[255] = 0; 81354a88810SDouglas Gregor MyHostname[0] = 0; 81454a88810SDouglas Gregor gethostname(MyHostname, 255); 81554a88810SDouglas Gregor // Check whether the process is dead. If so, we're done. 81654a88810SDouglas Gregor if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH) 81754a88810SDouglas Gregor return false; 81854a88810SDouglas Gregor #endif 81954a88810SDouglas Gregor 82054a88810SDouglas Gregor return true; 82154a88810SDouglas Gregor } 82254a88810SDouglas Gregor 82354a88810SDouglas Gregor LockFileManager::LockFileManager(StringRef FileName) 82454a88810SDouglas Gregor { 82554a88810SDouglas Gregor LockFileName = FileName; 82654a88810SDouglas Gregor LockFileName += ".lock"; 82754a88810SDouglas Gregor 82854a88810SDouglas Gregor // If the lock file already exists, don't bother to try to create our own 82954a88810SDouglas Gregor // lock file; it won't work anyway. Just figure out who owns this lock file. 83054a88810SDouglas Gregor if ((Owner = readLockFile(LockFileName))) 83154a88810SDouglas Gregor return; 83254a88810SDouglas Gregor 83354a88810SDouglas Gregor // Create a lock file that is unique to this instance. 83454a88810SDouglas Gregor UniqueLockFileName = LockFileName; 83554a88810SDouglas Gregor UniqueLockFileName += "-%%%%%%%%"; 83654a88810SDouglas Gregor int UniqueLockFileID; 83754a88810SDouglas Gregor if (llvm::error_code EC 83854a88810SDouglas Gregor = llvm::sys::fs::unique_file(UniqueLockFileName.str(), 83954a88810SDouglas Gregor UniqueLockFileID, 84054a88810SDouglas Gregor UniqueLockFileName, 84154a88810SDouglas Gregor /*makeAbsolute=*/false)) { 84254a88810SDouglas Gregor Error = EC; 84354a88810SDouglas Gregor return; 84454a88810SDouglas Gregor } 84554a88810SDouglas Gregor 84654a88810SDouglas Gregor // Write our process ID to our unique lock file. 84754a88810SDouglas Gregor { 84854a88810SDouglas Gregor llvm::raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true); 84954a88810SDouglas Gregor 85054a88810SDouglas Gregor #if LLVM_ON_UNIX 85154a88810SDouglas Gregor // FIXME: move getpid() call into LLVM 85254a88810SDouglas Gregor char hostname[256]; 85354a88810SDouglas Gregor hostname[255] = 0; 85454a88810SDouglas Gregor hostname[0] = 0; 85554a88810SDouglas Gregor gethostname(hostname, 255); 85654a88810SDouglas Gregor Out << hostname << ' ' << getpid(); 85754a88810SDouglas Gregor #else 85854a88810SDouglas Gregor Out << "localhost 1"; 85954a88810SDouglas Gregor #endif 86054a88810SDouglas Gregor Out.close(); 86154a88810SDouglas Gregor 86254a88810SDouglas Gregor if (Out.has_error()) { 86354a88810SDouglas Gregor // We failed to write out PID, so make up an excuse, remove the 86454a88810SDouglas Gregor // unique lock file, and fail. 86554a88810SDouglas Gregor Error = llvm::make_error_code(llvm::errc::no_space_on_device); 86654a88810SDouglas Gregor bool Existed; 86754a88810SDouglas Gregor llvm::sys::fs::remove(UniqueLockFileName.c_str(), Existed); 86854a88810SDouglas Gregor return; 86954a88810SDouglas Gregor } 87054a88810SDouglas Gregor } 87154a88810SDouglas Gregor 87254a88810SDouglas Gregor // Create a hard link from the lock file name. If this succeeds, we're done. 87354a88810SDouglas Gregor llvm::error_code EC 87454a88810SDouglas Gregor = llvm::sys::fs::create_hard_link(UniqueLockFileName.str(), 87554a88810SDouglas Gregor LockFileName.str()); 87654a88810SDouglas Gregor if (EC == llvm::errc::success) 87754a88810SDouglas Gregor return; 87854a88810SDouglas Gregor 87954a88810SDouglas Gregor // Creating the hard link failed. 88054a88810SDouglas Gregor 88154a88810SDouglas Gregor #ifdef LLVM_ON_UNIX 88254a88810SDouglas Gregor // The creation of the hard link may appear to fail, but if stat'ing the 88354a88810SDouglas Gregor // unique file returns a link count of 2, then we can still declare success. 88454a88810SDouglas Gregor struct stat StatBuf; 88554a88810SDouglas Gregor if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 && 88654a88810SDouglas Gregor StatBuf.st_nlink == 2) 88754a88810SDouglas Gregor return; 88854a88810SDouglas Gregor #endif 88954a88810SDouglas Gregor 89054a88810SDouglas Gregor // Someone else managed to create the lock file first. Wipe out our unique 89154a88810SDouglas Gregor // lock file (it's useless now) and read the process ID from the lock file. 89254a88810SDouglas Gregor bool Existed; 89354a88810SDouglas Gregor llvm::sys::fs::remove(UniqueLockFileName.str(), Existed); 89454a88810SDouglas Gregor if ((Owner = readLockFile(LockFileName))) 89554a88810SDouglas Gregor return; 89654a88810SDouglas Gregor 89754a88810SDouglas Gregor // There is a lock file that nobody owns; try to clean it up and report 89854a88810SDouglas Gregor // an error. 89954a88810SDouglas Gregor llvm::sys::fs::remove(LockFileName.str(), Existed); 90054a88810SDouglas Gregor Error = EC; 90154a88810SDouglas Gregor } 90254a88810SDouglas Gregor 90354a88810SDouglas Gregor LockFileManager::LockFileState LockFileManager::getState() const { 90454a88810SDouglas Gregor if (Owner) 90554a88810SDouglas Gregor return LFS_Shared; 90654a88810SDouglas Gregor 90754a88810SDouglas Gregor if (Error) 90854a88810SDouglas Gregor return LFS_Error; 90954a88810SDouglas Gregor 91054a88810SDouglas Gregor return LFS_Owned; 91154a88810SDouglas Gregor } 91254a88810SDouglas Gregor 91354a88810SDouglas Gregor LockFileManager::~LockFileManager() { 91454a88810SDouglas Gregor if (getState() != LFS_Owned) 91554a88810SDouglas Gregor return; 91654a88810SDouglas Gregor 91754a88810SDouglas Gregor // Since we own the lock, remove the lock file and our own unique lock file. 91854a88810SDouglas Gregor bool Existed; 91954a88810SDouglas Gregor llvm::sys::fs::remove(LockFileName.str(), Existed); 92054a88810SDouglas Gregor llvm::sys::fs::remove(UniqueLockFileName.str(), Existed); 92154a88810SDouglas Gregor } 92254a88810SDouglas Gregor 92354a88810SDouglas Gregor void LockFileManager::waitForUnlock() { 92454a88810SDouglas Gregor if (getState() != LFS_Shared) 92554a88810SDouglas Gregor return; 92654a88810SDouglas Gregor 92710312ab1SDouglas Gregor #if LLVM_ON_WIN32 92810312ab1SDouglas Gregor unsigned long Interval = 1; 92910312ab1SDouglas Gregor #else 93054a88810SDouglas Gregor struct timespec Interval; 93154a88810SDouglas Gregor Interval.tv_sec = 0; 93254a88810SDouglas Gregor Interval.tv_nsec = 1000000; 93310312ab1SDouglas Gregor #endif 93454a88810SDouglas Gregor // Don't wait more than an hour for the file to appear. 93554a88810SDouglas Gregor const unsigned MaxSeconds = 3600; 93654a88810SDouglas Gregor do { 93754a88810SDouglas Gregor // Sleep for the designated interval, to allow the owning process time to 93854a88810SDouglas Gregor // finish up and 93954a88810SDouglas Gregor // FIXME: Should we hook in to system APIs to get a notification when the 94054a88810SDouglas Gregor // lock file is deleted? 941a04a46e8SDouglas Gregor #if LLVM_ON_WIN32 942a04a46e8SDouglas Gregor Sleep(Interval); 943a04a46e8SDouglas Gregor #else 94454a88810SDouglas Gregor nanosleep(&Interval, NULL); 945a04a46e8SDouglas Gregor #endif 94654a88810SDouglas Gregor // If the file no longer exists, we're done. 94754a88810SDouglas Gregor bool Exists = false; 94854a88810SDouglas Gregor if (!llvm::sys::fs::exists(LockFileName.str(), Exists) && !Exists) 94954a88810SDouglas Gregor return; 95054a88810SDouglas Gregor 95154a88810SDouglas Gregor if (!processStillExecuting((*Owner).first, (*Owner).second)) 95254a88810SDouglas Gregor return; 95354a88810SDouglas Gregor 95454a88810SDouglas Gregor // Exponentially increase the time we wait for the lock to be removed. 95510312ab1SDouglas Gregor #if LLVM_ON_WIN32 95610312ab1SDouglas Gregor Interval *= 2; 95710312ab1SDouglas Gregor #else 95854a88810SDouglas Gregor Interval.tv_sec *= 2; 95954a88810SDouglas Gregor Interval.tv_nsec *= 2; 96054a88810SDouglas Gregor if (Interval.tv_nsec >= 1000000000) { 96154a88810SDouglas Gregor ++Interval.tv_sec; 96254a88810SDouglas Gregor Interval.tv_nsec -= 1000000000; 96354a88810SDouglas Gregor } 96410312ab1SDouglas Gregor #endif 96510312ab1SDouglas Gregor } while ( 96610312ab1SDouglas Gregor #if LLVM_ON_WIN32 96710312ab1SDouglas Gregor Interval < MaxSeconds * 1000 96810312ab1SDouglas Gregor #else 9690010bd96SNAKAMURA Takumi Interval.tv_sec < (time_t)MaxSeconds 97010312ab1SDouglas Gregor #endif 97110312ab1SDouglas Gregor ); 97254a88810SDouglas Gregor 97354a88810SDouglas Gregor // Give up. 97454a88810SDouglas Gregor } 97554a88810SDouglas Gregor 976*514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options 977*514b636aSDouglas Gregor /// provided by the importing compiler instance. 978faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance, 9796dc57927SDouglas Gregor ModuleMap::Module *Module, 9806dc57927SDouglas Gregor StringRef ModuleFileName) { 98154a88810SDouglas Gregor LockFileManager Locked(ModuleFileName); 98254a88810SDouglas Gregor switch (Locked) { 98354a88810SDouglas Gregor case LockFileManager::LFS_Error: 98454a88810SDouglas Gregor return; 98554a88810SDouglas Gregor 98654a88810SDouglas Gregor case LockFileManager::LFS_Owned: 98754a88810SDouglas Gregor // We're responsible for building the module ourselves. Do so below. 98854a88810SDouglas Gregor break; 98954a88810SDouglas Gregor 99054a88810SDouglas Gregor case LockFileManager::LFS_Shared: 99154a88810SDouglas Gregor // Someone else is responsible for building the module. Wait for them to 99254a88810SDouglas Gregor // finish. 99354a88810SDouglas Gregor Locked.waitForUnlock(); 99454a88810SDouglas Gregor break; 99554a88810SDouglas Gregor } 99654a88810SDouglas Gregor 997*514b636aSDouglas Gregor ModuleMap &ModMap 998*514b636aSDouglas Gregor = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); 999*514b636aSDouglas Gregor 1000faeb1d46SDouglas Gregor // Construct a compiler invocation for creating this module. 1001faeb1d46SDouglas Gregor llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation 1002faeb1d46SDouglas Gregor (new CompilerInvocation(ImportingInstance.getInvocation())); 100344bf68d8SDouglas Gregor 100444bf68d8SDouglas Gregor // For any options that aren't intended to affect how a module is built, 100544bf68d8SDouglas Gregor // reset them to their default values. 10068cf47df7STed Kremenek Invocation->getLangOpts()->resetNonModularOptions(); 1007f1312a82SDouglas Gregor Invocation->getPreprocessorOpts().resetNonModularOptions(); 100844bf68d8SDouglas Gregor 10097d106e42SDouglas Gregor // Note the name of the module we're building. 10106dc57927SDouglas Gregor Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); 10117d106e42SDouglas Gregor 101244bf68d8SDouglas Gregor // Note that this module is part of the module build path, so that we 101344bf68d8SDouglas Gregor // can detect cycles in the module graph. 10146dc57927SDouglas Gregor Invocation->getPreprocessorOpts().ModuleBuildPath 10156dc57927SDouglas Gregor .push_back(Module->getTopLevelModuleName()); 1016f1312a82SDouglas Gregor 1017*514b636aSDouglas Gregor if (const FileEntry *ModuleMapFile 1018*514b636aSDouglas Gregor = ModMap.getContainingModuleMapFile(Module)) { 1019*514b636aSDouglas Gregor // If there is a module map file, build the module using the module map. 1020*514b636aSDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella 1021*514b636aSDouglas Gregor // header. 1022*514b636aSDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 1023*514b636aSDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str(); 1024*514b636aSDouglas Gregor FrontendOpts.DisableFree = false; 1025*514b636aSDouglas Gregor FrontendOpts.Inputs.clear(); 1026*514b636aSDouglas Gregor FrontendOpts.Inputs.push_back( 1027*514b636aSDouglas Gregor std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()), 1028*514b636aSDouglas Gregor ModuleMapFile->getName())); 1029*514b636aSDouglas Gregor 1030*514b636aSDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 1031*514b636aSDouglas Gregor 1032*514b636aSDouglas Gregor 1033*514b636aSDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() == 1034*514b636aSDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!"); 1035*514b636aSDouglas Gregor 1036*514b636aSDouglas Gregor // Construct a compiler instance that will be used to actually create the 1037*514b636aSDouglas Gregor // module. 1038*514b636aSDouglas Gregor CompilerInstance Instance; 1039*514b636aSDouglas Gregor Instance.setInvocation(&*Invocation); 1040*514b636aSDouglas Gregor Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, 1041*514b636aSDouglas Gregor &ImportingInstance.getDiagnosticClient(), 1042*514b636aSDouglas Gregor /*ShouldOwnClient=*/true, 1043*514b636aSDouglas Gregor /*ShouldCloneClient=*/true); 1044*514b636aSDouglas Gregor 1045*514b636aSDouglas Gregor // Construct a module-generating action. 1046*514b636aSDouglas Gregor GenerateModuleAction CreateModuleAction; 1047*514b636aSDouglas Gregor 1048*514b636aSDouglas Gregor // Execute the action to actually build the module in-place. Use a separate 1049*514b636aSDouglas Gregor // thread so that we get a stack large enough. 1050*514b636aSDouglas Gregor const unsigned ThreadStackSize = 8 << 20; 1051*514b636aSDouglas Gregor llvm::CrashRecoveryContext CRC; 1052*514b636aSDouglas Gregor CompileModuleMapData Data = { Instance, CreateModuleAction }; 1053*514b636aSDouglas Gregor CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); 1054*514b636aSDouglas Gregor return; 1055*514b636aSDouglas Gregor } 1056*514b636aSDouglas Gregor 1057*514b636aSDouglas Gregor // FIXME: Temporary fallback: generate the module from the umbrella header. 1058*514b636aSDouglas Gregor // This is currently used when we infer a module map from a framework. 1059*514b636aSDouglas Gregor assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header"); 1060*514b636aSDouglas Gregor 106144bf68d8SDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella 106244bf68d8SDouglas Gregor // header. 1063faeb1d46SDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 10641735f4e7SDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str(); 1065faeb1d46SDouglas Gregor FrontendOpts.DisableFree = false; 1066faeb1d46SDouglas Gregor FrontendOpts.Inputs.clear(); 1067faeb1d46SDouglas Gregor FrontendOpts.Inputs.push_back( 10688cf47df7STed Kremenek std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()), 10696dc57927SDouglas Gregor Module->UmbrellaHeader->getName())); 10702b9b4642SDouglas Gregor 10712b9b4642SDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 10722b9b4642SDouglas Gregor 1073dff0e892SDouglas Gregor 10743728ea75SDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() == 10753728ea75SDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!"); 1076faeb1d46SDouglas Gregor 1077faeb1d46SDouglas Gregor // Construct a compiler instance that will be used to actually create the 1078faeb1d46SDouglas Gregor // module. 1079faeb1d46SDouglas Gregor CompilerInstance Instance; 1080faeb1d46SDouglas Gregor Instance.setInvocation(&*Invocation); 10812b9b4642SDouglas Gregor Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, 10822b9b4642SDouglas Gregor &ImportingInstance.getDiagnosticClient(), 1083d0e9e3a6SDouglas Gregor /*ShouldOwnClient=*/true, 1084d0e9e3a6SDouglas Gregor /*ShouldCloneClient=*/true); 1085faeb1d46SDouglas Gregor 1086faeb1d46SDouglas Gregor // Construct a module-generating action. 1087ac42ec6fSDouglas Gregor GeneratePCHAction CreateModuleAction(true); 1088faeb1d46SDouglas Gregor 108951e0b541SDouglas Gregor // Execute the action to actually build the module in-place. Use a separate 109051e0b541SDouglas Gregor // thread so that we get a stack large enough. 109151e0b541SDouglas Gregor const unsigned ThreadStackSize = 8 << 20; 109251e0b541SDouglas Gregor llvm::CrashRecoveryContext CRC; 109351e0b541SDouglas Gregor CompileModuleData Data = { Instance, CreateModuleAction }; 109451e0b541SDouglas Gregor CRC.RunSafelyOnThread(&doCompileModule, &Data, ThreadStackSize); 1095faeb1d46SDouglas Gregor } 1096faeb1d46SDouglas Gregor 109708142534SDouglas Gregor ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, 109808142534SDouglas Gregor IdentifierInfo &ModuleName, 109908142534SDouglas Gregor SourceLocation ModuleNameLoc) { 110008142534SDouglas Gregor // Determine what file we're searching from. 110108142534SDouglas Gregor SourceManager &SourceMgr = getSourceManager(); 110208142534SDouglas Gregor SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc); 110308142534SDouglas Gregor const FileEntry *CurFile 110408142534SDouglas Gregor = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc)); 110508142534SDouglas Gregor if (!CurFile) 110608142534SDouglas Gregor CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 110708142534SDouglas Gregor 110808142534SDouglas Gregor // Search for a module with the given name. 1109ca295457SDouglas Gregor ModuleMap::Module *Module = 0; 11101735f4e7SDouglas Gregor std::string ModuleFileName; 111108142534SDouglas Gregor const FileEntry *ModuleFile 1112ca295457SDouglas Gregor = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(), Module, 1113ca295457SDouglas Gregor &ModuleFileName); 1114faeb1d46SDouglas Gregor 1115faeb1d46SDouglas Gregor bool BuildingModule = false; 11166dc57927SDouglas Gregor if (!ModuleFile && Module) { 11176dc57927SDouglas Gregor // The module is not cached, but we have a module map from which we can 11186dc57927SDouglas Gregor // build the module. 1119dff0e892SDouglas Gregor 1120dff0e892SDouglas Gregor // Check whether there is a cycle in the module graph. 1121dff0e892SDouglas Gregor SmallVectorImpl<std::string> &ModuleBuildPath 1122dff0e892SDouglas Gregor = getPreprocessorOpts().ModuleBuildPath; 1123dff0e892SDouglas Gregor SmallVectorImpl<std::string>::iterator Pos 1124dff0e892SDouglas Gregor = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), 1125dff0e892SDouglas Gregor ModuleName.getName()); 1126dff0e892SDouglas Gregor if (Pos != ModuleBuildPath.end()) { 1127dff0e892SDouglas Gregor llvm::SmallString<256> CyclePath; 1128dff0e892SDouglas Gregor for (; Pos != ModuleBuildPath.end(); ++Pos) { 1129dff0e892SDouglas Gregor CyclePath += *Pos; 1130dff0e892SDouglas Gregor CyclePath += " -> "; 1131dff0e892SDouglas Gregor } 1132dff0e892SDouglas Gregor CyclePath += ModuleName.getName(); 1133dff0e892SDouglas Gregor 1134dff0e892SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) 1135dff0e892SDouglas Gregor << ModuleName.getName() << CyclePath; 1136dff0e892SDouglas Gregor return 0; 1137dff0e892SDouglas Gregor } 1138dff0e892SDouglas Gregor 113944e688d4SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build) 114044e688d4SDouglas Gregor << ModuleName.getName(); 1141faeb1d46SDouglas Gregor BuildingModule = true; 11426dc57927SDouglas Gregor compileModule(*this, Module, ModuleFileName); 1143ca295457SDouglas Gregor ModuleFile = FileMgr->getFile(ModuleFileName); 1144faeb1d46SDouglas Gregor } 1145faeb1d46SDouglas Gregor 114608142534SDouglas Gregor if (!ModuleFile) { 1147faeb1d46SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, 1148faeb1d46SDouglas Gregor BuildingModule? diag::err_module_not_built 1149faeb1d46SDouglas Gregor : diag::err_module_not_found) 115008142534SDouglas Gregor << ModuleName.getName() 115108142534SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 115208142534SDouglas Gregor return 0; 115308142534SDouglas Gregor } 115408142534SDouglas Gregor 115508142534SDouglas Gregor // If we don't already have an ASTReader, create one now. 115608142534SDouglas Gregor if (!ModuleManager) { 115721931efcSDouglas Gregor if (!hasASTContext()) 115821931efcSDouglas Gregor createASTContext(); 115921931efcSDouglas Gregor 116008142534SDouglas Gregor std::string Sysroot = getHeaderSearchOpts().Sysroot; 116108142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 11628835e03cSDouglas Gregor ModuleManager = new ASTReader(getPreprocessor(), *Context, 116308142534SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 116408142534SDouglas Gregor PPOpts.DisablePCHValidation, 116508142534SDouglas Gregor PPOpts.DisableStatCache); 116621931efcSDouglas Gregor if (hasASTConsumer()) { 116708142534SDouglas Gregor ModuleManager->setDeserializationListener( 116808142534SDouglas Gregor getASTConsumer().GetASTDeserializationListener()); 116908142534SDouglas Gregor getASTContext().setASTMutationListener( 117008142534SDouglas Gregor getASTConsumer().GetASTMutationListener()); 117121931efcSDouglas Gregor } 117208142534SDouglas Gregor llvm::OwningPtr<ExternalASTSource> Source; 117308142534SDouglas Gregor Source.reset(ModuleManager); 117408142534SDouglas Gregor getASTContext().setExternalSource(Source); 117521931efcSDouglas Gregor if (hasSema()) 117608142534SDouglas Gregor ModuleManager->InitializeSema(getSema()); 11776137d32cSDouglas Gregor if (hasASTConsumer()) 11786137d32cSDouglas Gregor ModuleManager->StartTranslationUnit(&getASTConsumer()); 117908142534SDouglas Gregor } 118008142534SDouglas Gregor 118108142534SDouglas Gregor // Try to load the module we found. 118208142534SDouglas Gregor switch (ModuleManager->ReadAST(ModuleFile->getName(), 118308142534SDouglas Gregor serialization::MK_Module)) { 118408142534SDouglas Gregor case ASTReader::Success: 118508142534SDouglas Gregor break; 118608142534SDouglas Gregor 118708142534SDouglas Gregor case ASTReader::IgnorePCH: 118808142534SDouglas Gregor // FIXME: The ASTReader will already have complained, but can we showhorn 118908142534SDouglas Gregor // that diagnostic information into a more useful form? 119008142534SDouglas Gregor return 0; 119108142534SDouglas Gregor 119208142534SDouglas Gregor case ASTReader::Failure: 119308142534SDouglas Gregor // Already complained. 119408142534SDouglas Gregor return 0; 119508142534SDouglas Gregor } 119608142534SDouglas Gregor 119708142534SDouglas Gregor // FIXME: The module file's FileEntry makes a poor key indeed! 119808142534SDouglas Gregor return (ModuleKey)ModuleFile; 119908142534SDouglas Gregor } 12004f2bc55dSDaniel Dunbar 1201