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" 14bcfc7d02SDouglas Gregor #include "clang/AST/Decl.h" 15636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h" 16546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h" 17546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h" 18636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h" 194f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h" 20aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h" 21aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h" 22aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.h" 238b00dcb0SDavid Blaikie #include "clang/Frontend/ChainedDiagnosticConsumer.h" 244f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h" 25faeb1d46SDouglas Gregor #include "clang/Frontend/FrontendActions.h" 26f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h" 272083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h" 284610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h" 297d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h" 3069609dceSDavid Blaikie #include "clang/Frontend/VerifyDiagnosticConsumer.h" 31aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h" 32f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h" 33f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h" 34f6efe58dSMichael J. Spencer #include "llvm/Support/FileSystem.h" 35409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h" 367d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 37171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h" 385505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h" 398aaf4995SMichael J. Spencer #include "llvm/Support/Host.h" 40e212489fSDouglas Gregor #include "llvm/Support/LockFileManager.h" 418aaf4995SMichael J. Spencer #include "llvm/Support/Path.h" 428aaf4995SMichael J. Spencer #include "llvm/Support/Program.h" 438aaf4995SMichael J. Spencer #include "llvm/Support/Signals.h" 44f25faaafSMichael J. Spencer #include "llvm/Support/system_error.h" 4551e0b541SDouglas Gregor #include "llvm/Support/CrashRecoveryContext.h" 46321cdb85SDylan Noblesmith #include "llvm/Config/config.h" 4754a88810SDouglas Gregor 48636404a3SDaniel Dunbar using namespace clang; 49636404a3SDaniel Dunbar 50e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance() 51925296b4SDouglas Gregor : Invocation(new CompilerInvocation()), ModuleManager(0) { 52636404a3SDaniel Dunbar } 53636404a3SDaniel Dunbar 54636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() { 55e922d9bdSDaniel Dunbar } 56e922d9bdSDaniel Dunbar 5768242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) { 585e14d39aSTed Kremenek Invocation = Value; 5968242254SDaniel Dunbar } 6068242254SDaniel Dunbar 619c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) { 627f95d26eSDouglas Gregor Diagnostics = Value; 63e01dc86dSDaniel Dunbar } 64e01dc86dSDaniel Dunbar 65e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) { 665e14d39aSTed Kremenek Target = Value; 67e01dc86dSDaniel Dunbar } 68e01dc86dSDaniel Dunbar 69e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) { 705e14d39aSTed Kremenek FileMgr = Value; 71e01dc86dSDaniel Dunbar } 72e01dc86dSDaniel Dunbar 73e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) { 745e14d39aSTed Kremenek SourceMgr = Value; 75e01dc86dSDaniel Dunbar } 76e01dc86dSDaniel Dunbar 775e14d39aSTed Kremenek void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; } 78e01dc86dSDaniel Dunbar 795e14d39aSTed Kremenek void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; } 80e01dc86dSDaniel Dunbar 810e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) { 820e93f017SDouglas Gregor TheSema.reset(S); 830e93f017SDouglas Gregor } 840e93f017SDouglas Gregor 8556d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 8656d9c293SDaniel Dunbar Consumer.reset(Value); 8756d9c293SDaniel Dunbar } 8856d9c293SDaniel Dunbar 89e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 90e01dc86dSDaniel Dunbar CompletionConsumer.reset(Value); 91e01dc86dSDaniel Dunbar } 92e01dc86dSDaniel Dunbar 937d75afc5SDaniel Dunbar // Diagnostics 947d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 9589c31490SAxel Naumann unsigned argc, const char* const *argv, 969c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 977d75afc5SDaniel Dunbar std::string ErrorInfo; 98e2778999SDylan Noblesmith OwningPtr<raw_ostream> OS( 99eeed0cc3SKovarththanan Rajaratnam new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo)); 1007d75afc5SDaniel Dunbar if (!ErrorInfo.empty()) { 1014a94ba56SKovarththanan Rajaratnam Diags.Report(diag::err_fe_unable_to_open_logfile) 1024a94ba56SKovarththanan Rajaratnam << DiagOpts.DumpBuildInformation << ErrorInfo; 1037d75afc5SDaniel Dunbar return; 1047d75afc5SDaniel Dunbar } 1057d75afc5SDaniel Dunbar 106520d1e6cSDaniel Dunbar (*OS) << "clang -cc1 command line arguments: "; 1077d75afc5SDaniel Dunbar for (unsigned i = 0; i != argc; ++i) 1087d75afc5SDaniel Dunbar (*OS) << argv[i] << ' '; 1097d75afc5SDaniel Dunbar (*OS) << '\n'; 1107d75afc5SDaniel Dunbar 1117d75afc5SDaniel Dunbar // Chain in a diagnostic client which will log the diagnostics. 112e2eefaecSDavid Blaikie DiagnosticConsumer *Logger = 113eeed0cc3SKovarththanan Rajaratnam new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true); 1148b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1157d75afc5SDaniel Dunbar } 1167d75afc5SDaniel Dunbar 1172083c32fSDaniel Dunbar static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, 1187b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts, 1199c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 1202083c32fSDaniel Dunbar std::string ErrorInfo; 1212083c32fSDaniel Dunbar bool OwnsStream = false; 1220e62c1ccSChris Lattner raw_ostream *OS = &llvm::errs(); 1232083c32fSDaniel Dunbar if (DiagOpts.DiagnosticLogFile != "-") { 1242083c32fSDaniel Dunbar // Create the output stream. 1252083c32fSDaniel Dunbar llvm::raw_fd_ostream *FileOS( 1262083c32fSDaniel Dunbar new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(), 12744d9ef78SDaniel Dunbar ErrorInfo, llvm::raw_fd_ostream::F_Append)); 1282083c32fSDaniel Dunbar if (!ErrorInfo.empty()) { 1292083c32fSDaniel Dunbar Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) 1302083c32fSDaniel Dunbar << DiagOpts.DumpBuildInformation << ErrorInfo; 1312083c32fSDaniel Dunbar } else { 1322083c32fSDaniel Dunbar FileOS->SetUnbuffered(); 1332083c32fSDaniel Dunbar FileOS->SetUseAtomicWrites(true); 1342083c32fSDaniel Dunbar OS = FileOS; 1352083c32fSDaniel Dunbar OwnsStream = true; 1362083c32fSDaniel Dunbar } 1372083c32fSDaniel Dunbar } 1382083c32fSDaniel Dunbar 1392083c32fSDaniel Dunbar // Chain in the diagnostic client which will log the diagnostics. 1407b83306dSDaniel Dunbar LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, 1412083c32fSDaniel Dunbar OwnsStream); 1427b83306dSDaniel Dunbar if (CodeGenOpts) 1437b83306dSDaniel Dunbar Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); 1448b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1452083c32fSDaniel Dunbar } 1462083c32fSDaniel Dunbar 1474610ea2bSTed Kremenek static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts, 1484610ea2bSTed Kremenek DiagnosticsEngine &Diags, 1494610ea2bSTed Kremenek StringRef OutputFile) { 1504610ea2bSTed Kremenek std::string ErrorInfo; 151e2778999SDylan Noblesmith OwningPtr<llvm::raw_fd_ostream> OS; 1524610ea2bSTed Kremenek OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, 1534610ea2bSTed Kremenek llvm::raw_fd_ostream::F_Binary)); 1544610ea2bSTed Kremenek 1554610ea2bSTed Kremenek if (!ErrorInfo.empty()) { 1564610ea2bSTed Kremenek Diags.Report(diag::warn_fe_serialized_diag_failure) 1574610ea2bSTed Kremenek << OutputFile << ErrorInfo; 1584610ea2bSTed Kremenek return; 1594610ea2bSTed Kremenek } 1604610ea2bSTed Kremenek 1614610ea2bSTed Kremenek DiagnosticConsumer *SerializedConsumer = 1624548e044STed Kremenek clang::serialized_diags::create(OS.take(), DiagOpts); 1634610ea2bSTed Kremenek 1644610ea2bSTed Kremenek 1654610ea2bSTed Kremenek Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), 1664610ea2bSTed Kremenek SerializedConsumer)); 1674610ea2bSTed Kremenek } 1684610ea2bSTed Kremenek 16944c6ee77SDouglas Gregor void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, 170e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 171d0e9e3a6SDouglas Gregor bool ShouldOwnClient, 172d0e9e3a6SDouglas Gregor bool ShouldCloneClient) { 1737b83306dSDaniel Dunbar Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client, 174d0e9e3a6SDouglas Gregor ShouldOwnClient, ShouldCloneClient, 175d0e9e3a6SDouglas Gregor &getCodeGenOpts()); 1767d75afc5SDaniel Dunbar } 1777d75afc5SDaniel Dunbar 178c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine> 1797f95d26eSDouglas Gregor CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 18044c6ee77SDouglas Gregor int Argc, const char* const *Argv, 181e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 1822b9b4642SDouglas Gregor bool ShouldOwnClient, 183d0e9e3a6SDouglas Gregor bool ShouldCloneClient, 1847b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts) { 185c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 186c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine> 1879c902b55SDavid Blaikie Diags(new DiagnosticsEngine(DiagID)); 1881b39a2edSDaniel Dunbar 1897d75afc5SDaniel Dunbar // Create the diagnostic client for reporting errors or for 1907d75afc5SDaniel Dunbar // implementing -verify. 191d0e9e3a6SDouglas Gregor if (Client) { 192d0e9e3a6SDouglas Gregor if (ShouldCloneClient) 193d0e9e3a6SDouglas Gregor Diags->setClient(Client->clone(*Diags), ShouldOwnClient); 19444c6ee77SDouglas Gregor else 195d0e9e3a6SDouglas Gregor Diags->setClient(Client, ShouldOwnClient); 196d0e9e3a6SDouglas Gregor } else 1972dd19f1dSDouglas Gregor Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); 19850ec0da0SDaniel Dunbar 19950ec0da0SDaniel Dunbar // Chain in -verify checker, if requested. 20050ec0da0SDaniel Dunbar if (Opts.VerifyDiagnostics) 20169609dceSDavid Blaikie Diags->setClient(new VerifyDiagnosticConsumer(*Diags)); 2027d75afc5SDaniel Dunbar 2032083c32fSDaniel Dunbar // Chain in -diagnostic-log-file dumper, if requested. 2042083c32fSDaniel Dunbar if (!Opts.DiagnosticLogFile.empty()) 2057b83306dSDaniel Dunbar SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags); 2062083c32fSDaniel Dunbar 2077d75afc5SDaniel Dunbar if (!Opts.DumpBuildInformation.empty()) 2084a94ba56SKovarththanan Rajaratnam SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); 2097d75afc5SDaniel Dunbar 2104610ea2bSTed Kremenek if (!Opts.DiagnosticSerializationFile.empty()) 2114610ea2bSTed Kremenek SetupSerializedDiagnostics(Opts, *Diags, 2124610ea2bSTed Kremenek Opts.DiagnosticSerializationFile); 2134610ea2bSTed Kremenek 2147d75afc5SDaniel Dunbar // Configure our handling of diagnostics. 2159ff84d9cSKovarththanan Rajaratnam ProcessWarningOptions(*Diags, Opts); 2167d75afc5SDaniel Dunbar 2177f95d26eSDouglas Gregor return Diags; 2187d75afc5SDaniel Dunbar } 2197d75afc5SDaniel Dunbar 2207d75afc5SDaniel Dunbar // File Manager 2217d75afc5SDaniel Dunbar 222546a676aSDaniel Dunbar void CompilerInstance::createFileManager() { 2235e14d39aSTed Kremenek FileMgr = new FileManager(getFileSystemOpts()); 224546a676aSDaniel Dunbar } 225546a676aSDaniel Dunbar 2267d75afc5SDaniel Dunbar // Source Manager 2277d75afc5SDaniel Dunbar 2285159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) { 2295e14d39aSTed Kremenek SourceMgr = new SourceManager(getDiagnostics(), FileMgr); 230546a676aSDaniel Dunbar } 231aaa148fdSDaniel Dunbar 2327d75afc5SDaniel Dunbar // Preprocessor 2337d75afc5SDaniel Dunbar 234aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() { 23508142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 236aaa148fdSDaniel Dunbar 237aaa148fdSDaniel Dunbar // Create a PTH manager if we are using some form of a token cache. 238aaa148fdSDaniel Dunbar PTHManager *PTHMgr = 0; 239d6ea9028SDaniel Dunbar if (!PPOpts.TokenCache.empty()) 24008142534SDouglas Gregor PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics()); 241aaa148fdSDaniel Dunbar 242aaa148fdSDaniel Dunbar // Create the Preprocessor. 243197ac203SDouglas Gregor HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(), 2441fb5c3a6SDouglas Gregor getDiagnostics(), 24589929282SDouglas Gregor getLangOpts(), 24689929282SDouglas Gregor &getTarget()); 24783297dfcSDouglas Gregor PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(), 24808142534SDouglas Gregor getSourceManager(), *HeaderInfo, *this, PTHMgr, 249aaa148fdSDaniel Dunbar /*OwnsHeaderSearch=*/true); 250aaa148fdSDaniel Dunbar 251aaa148fdSDaniel Dunbar // Note that this is different then passing PTHMgr to Preprocessor's ctor. 252aaa148fdSDaniel Dunbar // That argument is used as the IdentifierInfoLookup argument to 253aaa148fdSDaniel Dunbar // IdentifierTable's ctor. 254aaa148fdSDaniel Dunbar if (PTHMgr) { 25508142534SDouglas Gregor PTHMgr->setPreprocessor(&*PP); 256aaa148fdSDaniel Dunbar PP->setPTHManager(PTHMgr); 257aaa148fdSDaniel Dunbar } 258aaa148fdSDaniel Dunbar 2597f6d60dcSDouglas Gregor if (PPOpts.DetailedRecord) 260*647dcd80SArgyrios Kyrtzidis PP->createPreprocessingRecord(PPOpts.DetailedRecordConditionalDirectives); 2617f6d60dcSDouglas Gregor 26208142534SDouglas Gregor InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts()); 263aaa148fdSDaniel Dunbar 2641735f4e7SDouglas Gregor // Set up the module path, including the hash for the 2651735f4e7SDouglas Gregor // module-creation options. 2662c1dd271SDylan Noblesmith SmallString<256> SpecificModuleCache( 2671735f4e7SDouglas Gregor getHeaderSearchOpts().ModuleCachePath); 2681735f4e7SDouglas Gregor if (!getHeaderSearchOpts().DisableModuleHash) 2691735f4e7SDouglas Gregor llvm::sys::path::append(SpecificModuleCache, 2701735f4e7SDouglas Gregor getInvocation().getModuleHash()); 2712537a364SDouglas Gregor PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); 2721735f4e7SDouglas Gregor 273aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested. 27408142534SDouglas Gregor const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); 275aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty()) 276aaa148fdSDaniel Dunbar AttachDependencyFileGen(*PP, DepOpts); 2772e129659SDouglas Gregor if (!DepOpts.DOTOutputFile.empty()) 2782e129659SDouglas Gregor AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, 27983d46be3SDouglas Gregor getHeaderSearchOpts().Sysroot); 28083d46be3SDouglas Gregor 281aaa148fdSDaniel Dunbar 28227734fdbSDaniel Dunbar // Handle generating header include information, if requested. 28327734fdbSDaniel Dunbar if (DepOpts.ShowHeaderIncludes) 28427734fdbSDaniel Dunbar AttachHeaderIncludeGen(*PP); 2851af1d275SDaniel Dunbar if (!DepOpts.HeaderIncludeOutputFile.empty()) { 2860e62c1ccSChris Lattner StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; 2871af1d275SDaniel Dunbar if (OutputPath == "-") 2881af1d275SDaniel Dunbar OutputPath = ""; 289fe908a80SDaniel Dunbar AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, 290fe908a80SDaniel Dunbar /*ShowDepth=*/false); 2911af1d275SDaniel Dunbar } 292aaa148fdSDaniel Dunbar } 293df3e30c4SDaniel Dunbar 294df3e30c4SDaniel Dunbar // ASTContext 295df3e30c4SDaniel Dunbar 296df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() { 297df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor(); 2985e14d39aSTed Kremenek Context = new ASTContext(getLangOpts(), PP.getSourceManager(), 299e8bbc121SDouglas Gregor &getTarget(), PP.getIdentifierTable(), 300df3e30c4SDaniel Dunbar PP.getSelectorTable(), PP.getBuiltinInfo(), 3015e14d39aSTed Kremenek /*size_reserve=*/ 0); 302df3e30c4SDaniel Dunbar } 303599313efSDaniel Dunbar 304599313efSDaniel Dunbar // ExternalASTSource 305599313efSDaniel Dunbar 3060e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path, 30707a89a83SSebastian Redl bool DisablePCHValidation, 308606c4ac3SDouglas Gregor bool DisableStatCache, 30907a89a83SSebastian Redl void *DeserializationListener){ 310e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 311009e7f20SSebastian Redl bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; 312599313efSDaniel Dunbar Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 313ce3a8293SDouglas Gregor DisablePCHValidation, 314606c4ac3SDouglas Gregor DisableStatCache, 31507a89a83SSebastian Redl getPreprocessor(), getASTContext(), 316009e7f20SSebastian Redl DeserializationListener, 317009e7f20SSebastian Redl Preamble)); 318925296b4SDouglas Gregor ModuleManager = static_cast<ASTReader*>(Source.get()); 319599313efSDaniel Dunbar getASTContext().setExternalSource(Source); 320599313efSDaniel Dunbar } 321599313efSDaniel Dunbar 322599313efSDaniel Dunbar ExternalASTSource * 3230e62c1ccSChris Lattner CompilerInstance::createPCHExternalASTSource(StringRef Path, 324599313efSDaniel Dunbar const std::string &Sysroot, 325ce3a8293SDouglas Gregor bool DisablePCHValidation, 326606c4ac3SDouglas Gregor bool DisableStatCache, 327599313efSDaniel Dunbar Preprocessor &PP, 32807a89a83SSebastian Redl ASTContext &Context, 329009e7f20SSebastian Redl void *DeserializationListener, 330009e7f20SSebastian Redl bool Preamble) { 331e2778999SDylan Noblesmith OwningPtr<ASTReader> Reader; 3328835e03cSDouglas Gregor Reader.reset(new ASTReader(PP, Context, 333c567ba26SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 334606c4ac3SDouglas Gregor DisablePCHValidation, DisableStatCache)); 335599313efSDaniel Dunbar 33607a89a83SSebastian Redl Reader->setDeserializationListener( 3373e31c724SSebastian Redl static_cast<ASTDeserializationListener *>(DeserializationListener)); 338009e7f20SSebastian Redl switch (Reader->ReadAST(Path, 339a6895d8aSDouglas Gregor Preamble ? serialization::MK_Preamble 340a6895d8aSDouglas Gregor : serialization::MK_PCH)) { 3412c499f65SSebastian Redl case ASTReader::Success: 342599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the 343599313efSDaniel Dunbar // predefines buffer will be empty. 344599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines()); 345599313efSDaniel Dunbar return Reader.take(); 346599313efSDaniel Dunbar 3472c499f65SSebastian Redl case ASTReader::Failure: 348599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file. 349599313efSDaniel Dunbar break; 350599313efSDaniel Dunbar 3512c499f65SSebastian Redl case ASTReader::IgnorePCH: 352599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error. 353599313efSDaniel Dunbar break; 354599313efSDaniel Dunbar } 355599313efSDaniel Dunbar 356599313efSDaniel Dunbar return 0; 357599313efSDaniel Dunbar } 358f7093b5aSDaniel Dunbar 359f7093b5aSDaniel Dunbar // Code Completion 360f7093b5aSDaniel Dunbar 3618e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP, 3628e984da8SDouglas Gregor const std::string &Filename, 3638e984da8SDouglas Gregor unsigned Line, 3648e984da8SDouglas Gregor unsigned Column) { 3658e984da8SDouglas Gregor // Tell the source manager to chop off the given file at a specific 3668e984da8SDouglas Gregor // line and column. 3675159f616SChris Lattner const FileEntry *Entry = PP.getFileManager().getFile(Filename); 3688e984da8SDouglas Gregor if (!Entry) { 3698e984da8SDouglas Gregor PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 3708e984da8SDouglas Gregor << Filename; 3718e984da8SDouglas Gregor return true; 3728e984da8SDouglas Gregor } 3738e984da8SDouglas Gregor 3748e984da8SDouglas Gregor // Truncate the named file at the given line/column. 3758e984da8SDouglas Gregor PP.SetCodeCompletionPoint(Entry, Line, Column); 3768e984da8SDouglas Gregor return false; 3778e984da8SDouglas Gregor } 3788e984da8SDouglas Gregor 379f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() { 380f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 3818e984da8SDouglas Gregor if (!CompletionConsumer) { 382f7093b5aSDaniel Dunbar CompletionConsumer.reset( 383f7093b5aSDaniel Dunbar createCodeCompletionConsumer(getPreprocessor(), 384f7093b5aSDaniel Dunbar Loc.FileName, Loc.Line, Loc.Column, 385f7093b5aSDaniel Dunbar getFrontendOpts().ShowMacrosInCodeCompletion, 386f64acca2SDouglas Gregor getFrontendOpts().ShowCodePatternsInCodeCompletion, 38739982197SDouglas Gregor getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, 388f7093b5aSDaniel Dunbar llvm::outs())); 38900a0cf70SDouglas Gregor if (!CompletionConsumer) 39000a0cf70SDouglas Gregor return; 3918e984da8SDouglas Gregor } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName, 3928e984da8SDouglas Gregor Loc.Line, Loc.Column)) { 3938e984da8SDouglas Gregor CompletionConsumer.reset(); 3948e984da8SDouglas Gregor return; 3958e984da8SDouglas Gregor } 396f09935f1SDouglas Gregor 397f09935f1SDouglas Gregor if (CompletionConsumer->isOutputBinary() && 398f09935f1SDouglas Gregor llvm::sys::Program::ChangeStdoutToBinary()) { 399f09935f1SDouglas Gregor getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 400f09935f1SDouglas Gregor CompletionConsumer.reset(); 401f09935f1SDouglas Gregor } 402f7093b5aSDaniel Dunbar } 403f7093b5aSDaniel Dunbar 4045505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() { 4055505dff8SKovarththanan Rajaratnam FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 4065505dff8SKovarththanan Rajaratnam } 4075505dff8SKovarththanan Rajaratnam 408f7093b5aSDaniel Dunbar CodeCompleteConsumer * 409f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 410f7093b5aSDaniel Dunbar const std::string &Filename, 411f7093b5aSDaniel Dunbar unsigned Line, 412f7093b5aSDaniel Dunbar unsigned Column, 413f7093b5aSDaniel Dunbar bool ShowMacros, 414f64acca2SDouglas Gregor bool ShowCodePatterns, 41539982197SDouglas Gregor bool ShowGlobals, 4160e62c1ccSChris Lattner raw_ostream &OS) { 4178e984da8SDouglas Gregor if (EnableCodeCompletion(PP, Filename, Line, Column)) 418f7093b5aSDaniel Dunbar return 0; 419f7093b5aSDaniel Dunbar 420f7093b5aSDaniel Dunbar // Set up the creation routine for code-completion. 42139982197SDouglas Gregor return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, 42239982197SDouglas Gregor ShowGlobals, OS); 423f7093b5aSDaniel Dunbar } 424566eeb2dSDaniel Dunbar 42569f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind, 4260e93f017SDouglas Gregor CodeCompleteConsumer *CompletionConsumer) { 4270e93f017SDouglas Gregor TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(), 42869f74f80SDouglas Gregor TUKind, CompletionConsumer)); 4290e93f017SDouglas Gregor } 4300e93f017SDouglas Gregor 431566eeb2dSDaniel Dunbar // Output Files 432566eeb2dSDaniel Dunbar 433d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) { 434d0599970SArgyrios Kyrtzidis assert(OutFile.OS && "Attempt to add empty stream to output list!"); 435d0599970SArgyrios Kyrtzidis OutputFiles.push_back(OutFile); 436566eeb2dSDaniel Dunbar } 437566eeb2dSDaniel Dunbar 4381c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) { 439d0599970SArgyrios Kyrtzidis for (std::list<OutputFile>::iterator 440566eeb2dSDaniel Dunbar it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 441d0599970SArgyrios Kyrtzidis delete it->OS; 442d0599970SArgyrios Kyrtzidis if (!it->TempFilename.empty()) { 443b5c356a4SAnders Carlsson if (EraseFiles) { 444b5c356a4SAnders Carlsson bool existed; 445b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 446b5c356a4SAnders Carlsson } else { 4472c1dd271SDylan Noblesmith SmallString<128> NewOutFile(it->Filename); 448b5c356a4SAnders Carlsson 44971731d6bSArgyrios Kyrtzidis // If '-working-directory' was passed, the output filename should be 45071731d6bSArgyrios Kyrtzidis // relative to that. 4519ba8fb1eSAnders Carlsson FileMgr->FixupRelativePath(NewOutFile); 452b5c356a4SAnders Carlsson if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, 453b5c356a4SAnders Carlsson NewOutFile.str())) { 454d0599970SArgyrios Kyrtzidis getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) 455b5c356a4SAnders Carlsson << it->TempFilename << it->Filename << ec.message(); 456b5c356a4SAnders Carlsson 457b5c356a4SAnders Carlsson bool existed; 458b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 459d0599970SArgyrios Kyrtzidis } 460d0599970SArgyrios Kyrtzidis } 461d0599970SArgyrios Kyrtzidis } else if (!it->Filename.empty() && EraseFiles) 462d0599970SArgyrios Kyrtzidis llvm::sys::Path(it->Filename).eraseFromDisk(); 463d0599970SArgyrios Kyrtzidis 464566eeb2dSDaniel Dunbar } 465566eeb2dSDaniel Dunbar OutputFiles.clear(); 466566eeb2dSDaniel Dunbar } 467566eeb2dSDaniel Dunbar 468420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 469420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary, 4700e62c1ccSChris Lattner StringRef InFile, 4710e62c1ccSChris Lattner StringRef Extension) { 472420b0f1bSDaniel Dunbar return createOutputFile(getFrontendOpts().OutputFile, Binary, 473ae77b3dfSDaniel Dunbar /*RemoveFileOnSignal=*/true, InFile, Extension, 474ae77b3dfSDaniel Dunbar /*UseTemporary=*/true); 475420b0f1bSDaniel Dunbar } 476420b0f1bSDaniel Dunbar 477420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 4780e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 479e326f9bbSDaniel Dunbar bool Binary, bool RemoveFileOnSignal, 4800e62c1ccSChris Lattner StringRef InFile, 48108a2bfd2SArgyrios Kyrtzidis StringRef Extension, 482b9c62c07SDaniel Dunbar bool UseTemporary, 483b9c62c07SDaniel Dunbar bool CreateMissingDirectories) { 484d0599970SArgyrios Kyrtzidis std::string Error, OutputPathName, TempPathName; 485420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 486e326f9bbSDaniel Dunbar RemoveFileOnSignal, 487420b0f1bSDaniel Dunbar InFile, Extension, 48808a2bfd2SArgyrios Kyrtzidis UseTemporary, 489b9c62c07SDaniel Dunbar CreateMissingDirectories, 490d0599970SArgyrios Kyrtzidis &OutputPathName, 491d0599970SArgyrios Kyrtzidis &TempPathName); 492420b0f1bSDaniel Dunbar if (!OS) { 4937554699aSDaniel Dunbar getDiagnostics().Report(diag::err_fe_unable_to_open_output) 4947554699aSDaniel Dunbar << OutputPath << Error; 4957554699aSDaniel Dunbar return 0; 496420b0f1bSDaniel Dunbar } 497420b0f1bSDaniel Dunbar 498420b0f1bSDaniel Dunbar // Add the output file -- but don't try to remove "-", since this means we are 499420b0f1bSDaniel Dunbar // using stdin. 500d0599970SArgyrios Kyrtzidis addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", 501d0599970SArgyrios Kyrtzidis TempPathName, OS)); 502420b0f1bSDaniel Dunbar 503420b0f1bSDaniel Dunbar return OS; 504420b0f1bSDaniel Dunbar } 505420b0f1bSDaniel Dunbar 506420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 5070e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 508420b0f1bSDaniel Dunbar std::string &Error, 509420b0f1bSDaniel Dunbar bool Binary, 510e326f9bbSDaniel Dunbar bool RemoveFileOnSignal, 5110e62c1ccSChris Lattner StringRef InFile, 5120e62c1ccSChris Lattner StringRef Extension, 51308a2bfd2SArgyrios Kyrtzidis bool UseTemporary, 514b9c62c07SDaniel Dunbar bool CreateMissingDirectories, 515d0599970SArgyrios Kyrtzidis std::string *ResultPathName, 516d0599970SArgyrios Kyrtzidis std::string *TempPathName) { 517b9c62c07SDaniel Dunbar assert((!CreateMissingDirectories || UseTemporary) && 518b9c62c07SDaniel Dunbar "CreateMissingDirectories is only allowed when using temporary files"); 519b9c62c07SDaniel Dunbar 520d0599970SArgyrios Kyrtzidis std::string OutFile, TempFile; 521420b0f1bSDaniel Dunbar if (!OutputPath.empty()) { 522420b0f1bSDaniel Dunbar OutFile = OutputPath; 523420b0f1bSDaniel Dunbar } else if (InFile == "-") { 524420b0f1bSDaniel Dunbar OutFile = "-"; 525420b0f1bSDaniel Dunbar } else if (!Extension.empty()) { 526420b0f1bSDaniel Dunbar llvm::sys::Path Path(InFile); 527420b0f1bSDaniel Dunbar Path.eraseSuffix(); 528420b0f1bSDaniel Dunbar Path.appendSuffix(Extension); 529420b0f1bSDaniel Dunbar OutFile = Path.str(); 530420b0f1bSDaniel Dunbar } else { 531420b0f1bSDaniel Dunbar OutFile = "-"; 532420b0f1bSDaniel Dunbar } 533420b0f1bSDaniel Dunbar 534e2778999SDylan Noblesmith OwningPtr<llvm::raw_fd_ostream> OS; 53508a2bfd2SArgyrios Kyrtzidis std::string OSFile; 53608a2bfd2SArgyrios Kyrtzidis 53708a2bfd2SArgyrios Kyrtzidis if (UseTemporary && OutFile != "-") { 538b9c62c07SDaniel Dunbar // Only create the temporary if the parent directory exists (or create 539b9c62c07SDaniel Dunbar // missing directories is true) and we can actually write to OutPath, 540b9c62c07SDaniel Dunbar // otherwise we want to fail early. 541b9c62c07SDaniel Dunbar SmallString<256> AbsPath(OutputPath); 542b9c62c07SDaniel Dunbar llvm::sys::fs::make_absolute(AbsPath); 543b9c62c07SDaniel Dunbar llvm::sys::Path OutPath(AbsPath); 544b9c62c07SDaniel Dunbar bool ParentExists = false; 545b9c62c07SDaniel Dunbar if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()), 546b9c62c07SDaniel Dunbar ParentExists)) 547b9c62c07SDaniel Dunbar ParentExists = false; 548f6efe58dSMichael J. Spencer bool Exists; 549b9c62c07SDaniel Dunbar if ((CreateMissingDirectories || ParentExists) && 550b9c62c07SDaniel Dunbar ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) || 551b9c62c07SDaniel Dunbar (OutPath.isRegularFile() && OutPath.canWrite()))) { 552d0599970SArgyrios Kyrtzidis // Create a temporary file. 5532c1dd271SDylan Noblesmith SmallString<128> TempPath; 55408a2bfd2SArgyrios Kyrtzidis TempPath = OutFile; 55508a2bfd2SArgyrios Kyrtzidis TempPath += "-%%%%%%%%"; 55608a2bfd2SArgyrios Kyrtzidis int fd; 55708a2bfd2SArgyrios Kyrtzidis if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, 55808a2bfd2SArgyrios Kyrtzidis /*makeAbsolute=*/false) == llvm::errc::success) { 55908a2bfd2SArgyrios Kyrtzidis OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); 56008a2bfd2SArgyrios Kyrtzidis OSFile = TempFile = TempPath.str(); 56108a2bfd2SArgyrios Kyrtzidis } 562d0599970SArgyrios Kyrtzidis } 563d0599970SArgyrios Kyrtzidis } 564d0599970SArgyrios Kyrtzidis 56508a2bfd2SArgyrios Kyrtzidis if (!OS) { 56608a2bfd2SArgyrios Kyrtzidis OSFile = OutFile; 56708a2bfd2SArgyrios Kyrtzidis OS.reset( 568d0599970SArgyrios Kyrtzidis new llvm::raw_fd_ostream(OSFile.c_str(), Error, 5692eaef18eSDaniel Dunbar (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 5702eaef18eSDaniel Dunbar if (!Error.empty()) 571420b0f1bSDaniel Dunbar return 0; 57208a2bfd2SArgyrios Kyrtzidis } 573420b0f1bSDaniel Dunbar 574d0599970SArgyrios Kyrtzidis // Make sure the out stream file gets removed if we crash. 575e326f9bbSDaniel Dunbar if (RemoveFileOnSignal) 576d0599970SArgyrios Kyrtzidis llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); 577d0599970SArgyrios Kyrtzidis 578420b0f1bSDaniel Dunbar if (ResultPathName) 579420b0f1bSDaniel Dunbar *ResultPathName = OutFile; 580d0599970SArgyrios Kyrtzidis if (TempPathName) 581d0599970SArgyrios Kyrtzidis *TempPathName = TempFile; 582420b0f1bSDaniel Dunbar 5832eaef18eSDaniel Dunbar return OS.take(); 584420b0f1bSDaniel Dunbar } 585409e890fSDaniel Dunbar 586409e890fSDaniel Dunbar // Initialization Utilities 587409e890fSDaniel Dunbar 588a686e1b0SDouglas Gregor bool CompilerInstance::InitializeSourceManager(StringRef InputFile, 589a686e1b0SDouglas Gregor SrcMgr::CharacteristicKind Kind){ 590a686e1b0SDouglas Gregor return InitializeSourceManager(InputFile, Kind, getDiagnostics(), 591a686e1b0SDouglas Gregor getFileManager(), getSourceManager(), 592a686e1b0SDouglas Gregor getFrontendOpts()); 593409e890fSDaniel Dunbar } 594409e890fSDaniel Dunbar 5950e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile, 596a686e1b0SDouglas Gregor SrcMgr::CharacteristicKind Kind, 5979c902b55SDavid Blaikie DiagnosticsEngine &Diags, 598409e890fSDaniel Dunbar FileManager &FileMgr, 599409e890fSDaniel Dunbar SourceManager &SourceMgr, 600409e890fSDaniel Dunbar const FrontendOptions &Opts) { 6017c06d866SArgyrios Kyrtzidis // Figure out where to get and map in the main file. 6027c06d866SArgyrios Kyrtzidis if (InputFile != "-") { 6035159f616SChris Lattner const FileEntry *File = FileMgr.getFile(InputFile); 60452765215SDan Gohman if (!File) { 605409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile; 606409e890fSDaniel Dunbar return false; 607409e890fSDaniel Dunbar } 608a686e1b0SDouglas Gregor SourceMgr.createMainFileID(File, Kind); 609409e890fSDaniel Dunbar } else { 610e2778999SDylan Noblesmith OwningPtr<llvm::MemoryBuffer> SB; 611d9da7a1fSMichael J. Spencer if (llvm::MemoryBuffer::getSTDIN(SB)) { 612f25faaafSMichael J. Spencer // FIXME: Give ec.message() in this diag. 613409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading_stdin); 614409e890fSDaniel Dunbar return false; 615409e890fSDaniel Dunbar } 6162f76cd75SDan Gohman const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), 6175159f616SChris Lattner SB->getBufferSize(), 0); 618a686e1b0SDouglas Gregor SourceMgr.createMainFileID(File, Kind); 619d9da7a1fSMichael J. Spencer SourceMgr.overrideFileContents(File, SB.take()); 620409e890fSDaniel Dunbar } 621409e890fSDaniel Dunbar 62252765215SDan Gohman assert(!SourceMgr.getMainFileID().isInvalid() && 62352765215SDan Gohman "Couldn't establish MainFileID!"); 624409e890fSDaniel Dunbar return true; 625409e890fSDaniel Dunbar } 6264f2bc55dSDaniel Dunbar 6274f2bc55dSDaniel Dunbar // High-Level Operations 6284f2bc55dSDaniel Dunbar 6294f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 6304f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 6314f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 6324f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 6334f2bc55dSDaniel Dunbar 6344f2bc55dSDaniel Dunbar // FIXME: Take this as an argument, once all the APIs we used have moved to 6354f2bc55dSDaniel Dunbar // taking it as an input instead of hard-coding llvm::errs. 6360e62c1ccSChris Lattner raw_ostream &OS = llvm::errs(); 6374f2bc55dSDaniel Dunbar 6384f2bc55dSDaniel Dunbar // Create the target instance. 6394f2bc55dSDaniel Dunbar setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 6404f2bc55dSDaniel Dunbar if (!hasTarget()) 6414f2bc55dSDaniel Dunbar return false; 6424f2bc55dSDaniel Dunbar 6434f2bc55dSDaniel Dunbar // Inform the target of the language options. 6444f2bc55dSDaniel Dunbar // 6454f2bc55dSDaniel Dunbar // FIXME: We shouldn't need to do this, the target should be immutable once 6464f2bc55dSDaniel Dunbar // created. This complexity should be lifted elsewhere. 6474f2bc55dSDaniel Dunbar getTarget().setForcedLangOptions(getLangOpts()); 6484f2bc55dSDaniel Dunbar 6494f2bc55dSDaniel Dunbar // Validate/process some options. 6504f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose) 6514f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING 6524f2bc55dSDaniel Dunbar << " based upon " << PACKAGE_STRING 6538188c8a1SSebastian Pop << " default target " << llvm::sys::getDefaultTargetTriple() << "\n"; 6544f2bc55dSDaniel Dunbar 6554f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowTimers) 6564f2bc55dSDaniel Dunbar createFrontendTimer(); 6574f2bc55dSDaniel Dunbar 658171b780cSDouglas Gregor if (getFrontendOpts().ShowStats) 659171b780cSDouglas Gregor llvm::EnableStatistics(); 660171b780cSDouglas Gregor 6614f2bc55dSDaniel Dunbar for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 6624f2bc55dSDaniel Dunbar // Reset the ID tables if we are reusing the SourceManager. 663aed46fcbSDaniel Dunbar if (hasSourceManager()) 6644f2bc55dSDaniel Dunbar getSourceManager().clearIDTables(); 6654f2bc55dSDaniel Dunbar 66632fbe312SDouglas Gregor if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) { 6674f2bc55dSDaniel Dunbar Act.Execute(); 6684f2bc55dSDaniel Dunbar Act.EndSourceFile(); 6694f2bc55dSDaniel Dunbar } 6704f2bc55dSDaniel Dunbar } 6714f2bc55dSDaniel Dunbar 6727910d7b7SArgyrios Kyrtzidis // Notify the diagnostic client that all files were processed. 6737910d7b7SArgyrios Kyrtzidis getDiagnostics().getClient()->finish(); 6747910d7b7SArgyrios Kyrtzidis 675198cb4dfSChris Lattner if (getDiagnosticOpts().ShowCarets) { 676c79346a5SArgyrios Kyrtzidis // We can have multiple diagnostics sharing one diagnostic client. 677c79346a5SArgyrios Kyrtzidis // Get the total number of warnings/errors from the client. 678c79346a5SArgyrios Kyrtzidis unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); 679c79346a5SArgyrios Kyrtzidis unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); 680198cb4dfSChris Lattner 681198cb4dfSChris Lattner if (NumWarnings) 682198cb4dfSChris Lattner OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); 683198cb4dfSChris Lattner if (NumWarnings && NumErrors) 684198cb4dfSChris Lattner OS << " and "; 685198cb4dfSChris Lattner if (NumErrors) 686198cb4dfSChris Lattner OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); 687198cb4dfSChris Lattner if (NumWarnings || NumErrors) 688198cb4dfSChris Lattner OS << " generated.\n"; 689198cb4dfSChris Lattner } 6904f2bc55dSDaniel Dunbar 691aed46fcbSDaniel Dunbar if (getFrontendOpts().ShowStats && hasFileManager()) { 6924f2bc55dSDaniel Dunbar getFileManager().PrintStats(); 6934f2bc55dSDaniel Dunbar OS << "\n"; 6944f2bc55dSDaniel Dunbar } 6954f2bc55dSDaniel Dunbar 696bc467933SArgyrios Kyrtzidis return !getDiagnostics().getClient()->getNumErrors(); 6974f2bc55dSDaniel Dunbar } 6984f2bc55dSDaniel Dunbar 699faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language 700faeb1d46SDouglas Gregor /// options. 701faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { 702faeb1d46SDouglas Gregor if (LangOpts.OpenCL) 703faeb1d46SDouglas Gregor return IK_OpenCL; 704faeb1d46SDouglas Gregor if (LangOpts.CUDA) 705faeb1d46SDouglas Gregor return IK_CUDA; 706faeb1d46SDouglas Gregor if (LangOpts.ObjC1) 707faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC; 708faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_CXX : IK_C; 709faeb1d46SDouglas Gregor } 710faeb1d46SDouglas Gregor 71151e0b541SDouglas Gregor namespace { 712514b636aSDouglas Gregor struct CompileModuleMapData { 713514b636aSDouglas Gregor CompilerInstance &Instance; 714514b636aSDouglas Gregor GenerateModuleAction &CreateModuleAction; 715514b636aSDouglas Gregor }; 716514b636aSDouglas Gregor } 717514b636aSDouglas Gregor 718514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under 719514b636aSDouglas Gregor /// a crash recovery context. 720514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) { 721514b636aSDouglas Gregor CompileModuleMapData &Data 722514b636aSDouglas Gregor = *reinterpret_cast<CompileModuleMapData *>(UserData); 723514b636aSDouglas Gregor Data.Instance.ExecuteAction(Data.CreateModuleAction); 724514b636aSDouglas Gregor } 725514b636aSDouglas Gregor 726514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options 727514b636aSDouglas Gregor /// provided by the importing compiler instance. 728faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance, 729de3ef502SDouglas Gregor Module *Module, 7306dc57927SDouglas Gregor StringRef ModuleFileName) { 731e212489fSDouglas Gregor llvm::LockFileManager Locked(ModuleFileName); 73254a88810SDouglas Gregor switch (Locked) { 733e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Error: 73454a88810SDouglas Gregor return; 73554a88810SDouglas Gregor 736e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Owned: 73754a88810SDouglas Gregor // We're responsible for building the module ourselves. Do so below. 73854a88810SDouglas Gregor break; 73954a88810SDouglas Gregor 740e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Shared: 74154a88810SDouglas Gregor // Someone else is responsible for building the module. Wait for them to 74254a88810SDouglas Gregor // finish. 74354a88810SDouglas Gregor Locked.waitForUnlock(); 74454a88810SDouglas Gregor break; 74554a88810SDouglas Gregor } 74654a88810SDouglas Gregor 747514b636aSDouglas Gregor ModuleMap &ModMap 748514b636aSDouglas Gregor = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); 749514b636aSDouglas Gregor 750faeb1d46SDouglas Gregor // Construct a compiler invocation for creating this module. 751c95d8192SDylan Noblesmith IntrusiveRefCntPtr<CompilerInvocation> Invocation 752faeb1d46SDouglas Gregor (new CompilerInvocation(ImportingInstance.getInvocation())); 75344bf68d8SDouglas Gregor 754f545f67dSDouglas Gregor PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); 755f545f67dSDouglas Gregor 75644bf68d8SDouglas Gregor // For any options that aren't intended to affect how a module is built, 75744bf68d8SDouglas Gregor // reset them to their default values. 7588cf47df7STed Kremenek Invocation->getLangOpts()->resetNonModularOptions(); 759f545f67dSDouglas Gregor PPOpts.resetNonModularOptions(); 76044bf68d8SDouglas Gregor 7617d106e42SDouglas Gregor // Note the name of the module we're building. 7626dc57927SDouglas Gregor Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); 7637d106e42SDouglas Gregor 76444bf68d8SDouglas Gregor // Note that this module is part of the module build path, so that we 76544bf68d8SDouglas Gregor // can detect cycles in the module graph. 766f545f67dSDouglas Gregor PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName()); 767f1312a82SDouglas Gregor 768514b636aSDouglas Gregor // If there is a module map file, build the module using the module map. 769514b636aSDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella 770514b636aSDouglas Gregor // header. 771514b636aSDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 772514b636aSDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str(); 773514b636aSDouglas Gregor FrontendOpts.DisableFree = false; 774514b636aSDouglas Gregor FrontendOpts.Inputs.clear(); 775f545f67dSDouglas Gregor InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); 776f545f67dSDouglas Gregor 777f545f67dSDouglas Gregor // Get or create the module map that we'll use to build this module. 7782c1dd271SDylan Noblesmith SmallString<128> TempModuleMapFileName; 779f545f67dSDouglas Gregor if (const FileEntry *ModuleMapFile 780f545f67dSDouglas Gregor = ModMap.getContainingModuleMapFile(Module)) { 781f545f67dSDouglas Gregor // Use the module map where this module resides. 78232fbe312SDouglas Gregor FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), 78332fbe312SDouglas Gregor IK)); 784f545f67dSDouglas Gregor } else { 785f545f67dSDouglas Gregor // Create a temporary module map file. 786f545f67dSDouglas Gregor TempModuleMapFileName = Module->Name; 787f545f67dSDouglas Gregor TempModuleMapFileName += "-%%%%%%%%.map"; 788f545f67dSDouglas Gregor int FD; 789f545f67dSDouglas Gregor if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, 790f545f67dSDouglas Gregor TempModuleMapFileName, 79119f9f7bcSDouglas Gregor /*makeAbsolute=*/true) 7922f554c4cSDouglas Gregor != llvm::errc::success) { 793ee78d3e0SDouglas Gregor ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) 794ee78d3e0SDouglas Gregor << TempModuleMapFileName; 795f545f67dSDouglas Gregor return; 7962f554c4cSDouglas Gregor } 797f545f67dSDouglas Gregor // Print the module map to this file. 798f545f67dSDouglas Gregor llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); 799f545f67dSDouglas Gregor Module->print(OS); 800514b636aSDouglas Gregor FrontendOpts.Inputs.push_back( 80132fbe312SDouglas Gregor FrontendInputFile(TempModuleMapFileName.str().str(), IK)); 802f545f67dSDouglas Gregor } 803f545f67dSDouglas Gregor 804f545f67dSDouglas Gregor // Don't free the remapped file buffers; they are owned by our caller. 805f545f67dSDouglas Gregor PPOpts.RetainRemappedFileBuffers = true; 806514b636aSDouglas Gregor 807514b636aSDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 808514b636aSDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() == 809514b636aSDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!"); 810514b636aSDouglas Gregor 811514b636aSDouglas Gregor // Construct a compiler instance that will be used to actually create the 812514b636aSDouglas Gregor // module. 813514b636aSDouglas Gregor CompilerInstance Instance; 814514b636aSDouglas Gregor Instance.setInvocation(&*Invocation); 815514b636aSDouglas Gregor Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, 816514b636aSDouglas Gregor &ImportingInstance.getDiagnosticClient(), 817514b636aSDouglas Gregor /*ShouldOwnClient=*/true, 818514b636aSDouglas Gregor /*ShouldCloneClient=*/true); 819514b636aSDouglas Gregor 820514b636aSDouglas Gregor // Construct a module-generating action. 821514b636aSDouglas Gregor GenerateModuleAction CreateModuleAction; 822514b636aSDouglas Gregor 823514b636aSDouglas Gregor // Execute the action to actually build the module in-place. Use a separate 824514b636aSDouglas Gregor // thread so that we get a stack large enough. 825514b636aSDouglas Gregor const unsigned ThreadStackSize = 8 << 20; 826514b636aSDouglas Gregor llvm::CrashRecoveryContext CRC; 827514b636aSDouglas Gregor CompileModuleMapData Data = { Instance, CreateModuleAction }; 828514b636aSDouglas Gregor CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); 829514b636aSDouglas Gregor 830f545f67dSDouglas Gregor // Delete the temporary module map file. 831f545f67dSDouglas Gregor // FIXME: Even though we're executing under crash protection, it would still 832f545f67dSDouglas Gregor // be nice to do this with RemoveFileOnSignal when we can. However, that 833f545f67dSDouglas Gregor // doesn't make sense for all clients, so clean this up manually. 834f545f67dSDouglas Gregor if (!TempModuleMapFileName.empty()) 835f545f67dSDouglas Gregor llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); 836faeb1d46SDouglas Gregor } 837faeb1d46SDouglas Gregor 838de3ef502SDouglas Gregor Module *CompilerInstance::loadModule(SourceLocation ImportLoc, 839ff2be53fSDouglas Gregor ModuleIdPath Path, 840bcfc7d02SDouglas Gregor Module::NameVisibilityKind Visibility, 841bcfc7d02SDouglas Gregor bool IsInclusionDirective) { 8421805b8a4SDouglas Gregor // If we've already handled this import, just return the cached result. 8431805b8a4SDouglas Gregor // This one-element cache is important to eliminate redundant diagnostics 8441805b8a4SDouglas Gregor // when both the preprocessor and parser see the same import declaration. 845ff2be53fSDouglas Gregor if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { 846ff2be53fSDouglas Gregor // Make the named module visible. 847ff2be53fSDouglas Gregor if (LastModuleImportResult) 848ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility); 84969021974SDouglas Gregor return LastModuleImportResult; 850ff2be53fSDouglas Gregor } 8511805b8a4SDouglas Gregor 85208142534SDouglas Gregor // Determine what file we're searching from. 85308142534SDouglas Gregor SourceManager &SourceMgr = getSourceManager(); 85408142534SDouglas Gregor SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc); 85508142534SDouglas Gregor const FileEntry *CurFile 85608142534SDouglas Gregor = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc)); 85708142534SDouglas Gregor if (!CurFile) 85808142534SDouglas Gregor CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 85908142534SDouglas Gregor 86071944203SDouglas Gregor StringRef ModuleName = Path[0].first->getName(); 86171944203SDouglas Gregor SourceLocation ModuleNameLoc = Path[0].second; 86271944203SDouglas Gregor 863de3ef502SDouglas Gregor clang::Module *Module = 0; 8645196bc6bSDouglas Gregor 8655196bc6bSDouglas Gregor // If we don't already have information on this module, load the module now. 866de3ef502SDouglas Gregor llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known 86769021974SDouglas Gregor = KnownModules.find(Path[0].first); 8682537a364SDouglas Gregor if (Known != KnownModules.end()) { 8692537a364SDouglas Gregor // Retrieve the cached top-level module. 8702537a364SDouglas Gregor Module = Known->second; 8712537a364SDouglas Gregor } else if (ModuleName == getLangOpts().CurrentModule) { 8722537a364SDouglas Gregor // This is the module we're building. 8732537a364SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName); 8742537a364SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 8752537a364SDouglas Gregor } else { 8765196bc6bSDouglas Gregor // Search for a module with the given name. 877279a6c37SDouglas Gregor Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); 8781735f4e7SDouglas Gregor std::string ModuleFileName; 879279a6c37SDouglas Gregor if (Module) 880279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); 881279a6c37SDouglas Gregor else 882279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName); 883faeb1d46SDouglas Gregor 884279a6c37SDouglas Gregor if (ModuleFileName.empty()) { 885279a6c37SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) 886279a6c37SDouglas Gregor << ModuleName 887279a6c37SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 888279a6c37SDouglas Gregor LastModuleImportLoc = ImportLoc; 889279a6c37SDouglas Gregor LastModuleImportResult = 0; 890279a6c37SDouglas Gregor return 0; 891279a6c37SDouglas Gregor } 892279a6c37SDouglas Gregor 893279a6c37SDouglas Gregor const FileEntry *ModuleFile 894279a6c37SDouglas Gregor = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false, 895279a6c37SDouglas Gregor /*CacheFailure=*/false); 896faeb1d46SDouglas Gregor bool BuildingModule = false; 8976dc57927SDouglas Gregor if (!ModuleFile && Module) { 8986dc57927SDouglas Gregor // The module is not cached, but we have a module map from which we can 8996dc57927SDouglas Gregor // build the module. 900dff0e892SDouglas Gregor 901dff0e892SDouglas Gregor // Check whether there is a cycle in the module graph. 902dff0e892SDouglas Gregor SmallVectorImpl<std::string> &ModuleBuildPath 903dff0e892SDouglas Gregor = getPreprocessorOpts().ModuleBuildPath; 904dff0e892SDouglas Gregor SmallVectorImpl<std::string>::iterator Pos 90571944203SDouglas Gregor = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), ModuleName); 906dff0e892SDouglas Gregor if (Pos != ModuleBuildPath.end()) { 9072c1dd271SDylan Noblesmith SmallString<256> CyclePath; 908dff0e892SDouglas Gregor for (; Pos != ModuleBuildPath.end(); ++Pos) { 909dff0e892SDouglas Gregor CyclePath += *Pos; 910dff0e892SDouglas Gregor CyclePath += " -> "; 911dff0e892SDouglas Gregor } 91271944203SDouglas Gregor CyclePath += ModuleName; 913dff0e892SDouglas Gregor 914dff0e892SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) 91571944203SDouglas Gregor << ModuleName << CyclePath; 916dff0e892SDouglas Gregor return 0; 917dff0e892SDouglas Gregor } 918dff0e892SDouglas Gregor 91944e688d4SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build) 92071944203SDouglas Gregor << ModuleName; 921faeb1d46SDouglas Gregor BuildingModule = true; 9226dc57927SDouglas Gregor compileModule(*this, Module, ModuleFileName); 923ca295457SDouglas Gregor ModuleFile = FileMgr->getFile(ModuleFileName); 924faeb1d46SDouglas Gregor } 925faeb1d46SDouglas Gregor 92608142534SDouglas Gregor if (!ModuleFile) { 927faeb1d46SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, 928faeb1d46SDouglas Gregor BuildingModule? diag::err_module_not_built 929faeb1d46SDouglas Gregor : diag::err_module_not_found) 93071944203SDouglas Gregor << ModuleName 93108142534SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 93208142534SDouglas Gregor return 0; 93308142534SDouglas Gregor } 93408142534SDouglas Gregor 93508142534SDouglas Gregor // If we don't already have an ASTReader, create one now. 93608142534SDouglas Gregor if (!ModuleManager) { 93721931efcSDouglas Gregor if (!hasASTContext()) 93821931efcSDouglas Gregor createASTContext(); 93921931efcSDouglas Gregor 94008142534SDouglas Gregor std::string Sysroot = getHeaderSearchOpts().Sysroot; 94108142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 9428835e03cSDouglas Gregor ModuleManager = new ASTReader(getPreprocessor(), *Context, 94308142534SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 94408142534SDouglas Gregor PPOpts.DisablePCHValidation, 94508142534SDouglas Gregor PPOpts.DisableStatCache); 94621931efcSDouglas Gregor if (hasASTConsumer()) { 94708142534SDouglas Gregor ModuleManager->setDeserializationListener( 94808142534SDouglas Gregor getASTConsumer().GetASTDeserializationListener()); 94908142534SDouglas Gregor getASTContext().setASTMutationListener( 95008142534SDouglas Gregor getASTConsumer().GetASTMutationListener()); 95121931efcSDouglas Gregor } 952e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 95308142534SDouglas Gregor Source.reset(ModuleManager); 95408142534SDouglas Gregor getASTContext().setExternalSource(Source); 95521931efcSDouglas Gregor if (hasSema()) 95608142534SDouglas Gregor ModuleManager->InitializeSema(getSema()); 9576137d32cSDouglas Gregor if (hasASTConsumer()) 9586137d32cSDouglas Gregor ModuleManager->StartTranslationUnit(&getASTConsumer()); 95908142534SDouglas Gregor } 96008142534SDouglas Gregor 96108142534SDouglas Gregor // Try to load the module we found. 96208142534SDouglas Gregor switch (ModuleManager->ReadAST(ModuleFile->getName(), 96308142534SDouglas Gregor serialization::MK_Module)) { 96408142534SDouglas Gregor case ASTReader::Success: 96508142534SDouglas Gregor break; 96608142534SDouglas Gregor 96708142534SDouglas Gregor case ASTReader::IgnorePCH: 96808142534SDouglas Gregor // FIXME: The ASTReader will already have complained, but can we showhorn 96908142534SDouglas Gregor // that diagnostic information into a more useful form? 97069021974SDouglas Gregor KnownModules[Path[0].first] = 0; 97108142534SDouglas Gregor return 0; 97208142534SDouglas Gregor 97308142534SDouglas Gregor case ASTReader::Failure: 97469021974SDouglas Gregor // Already complained, but note now that we failed. 97569021974SDouglas Gregor KnownModules[Path[0].first] = 0; 97608142534SDouglas Gregor return 0; 97708142534SDouglas Gregor } 97808142534SDouglas Gregor 97969021974SDouglas Gregor if (!Module) { 98069021974SDouglas Gregor // If we loaded the module directly, without finding a module map first, 98169021974SDouglas Gregor // we'll have loaded the module's information from the module itself. 98269021974SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap() 98369021974SDouglas Gregor .findModule((Path[0].first->getName())); 9845196bc6bSDouglas Gregor } 9855196bc6bSDouglas Gregor 98669021974SDouglas Gregor // Cache the result of this top-level module lookup for later. 98769021974SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 98869021974SDouglas Gregor } 98969021974SDouglas Gregor 99069021974SDouglas Gregor // If we never found the module, fail. 99169021974SDouglas Gregor if (!Module) 99269021974SDouglas Gregor return 0; 99369021974SDouglas Gregor 9945196bc6bSDouglas Gregor // Verify that the rest of the module path actually corresponds to 9955196bc6bSDouglas Gregor // a submodule. 99669021974SDouglas Gregor if (Path.size() > 1) { 9975196bc6bSDouglas Gregor for (unsigned I = 1, N = Path.size(); I != N; ++I) { 9985196bc6bSDouglas Gregor StringRef Name = Path[I].first->getName(); 999eb90e830SDouglas Gregor clang::Module *Sub = Module->findSubmodule(Name); 10005196bc6bSDouglas Gregor 1001eb90e830SDouglas Gregor if (!Sub) { 10025196bc6bSDouglas Gregor // Attempt to perform typo correction to find a module name that works. 10035196bc6bSDouglas Gregor llvm::SmallVector<StringRef, 2> Best; 10045196bc6bSDouglas Gregor unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)(); 10055196bc6bSDouglas Gregor 1006eb90e830SDouglas Gregor for (clang::Module::submodule_iterator J = Module->submodule_begin(), 1007eb90e830SDouglas Gregor JEnd = Module->submodule_end(); 1008eb44edadSMatt Beaumont-Gay J != JEnd; ++J) { 1009eb90e830SDouglas Gregor unsigned ED = Name.edit_distance((*J)->Name, 10105196bc6bSDouglas Gregor /*AllowReplacements=*/true, 10115196bc6bSDouglas Gregor BestEditDistance); 10125196bc6bSDouglas Gregor if (ED <= BestEditDistance) { 1013eb90e830SDouglas Gregor if (ED < BestEditDistance) { 10145196bc6bSDouglas Gregor Best.clear(); 1015eb90e830SDouglas Gregor BestEditDistance = ED; 1016eb90e830SDouglas Gregor } 1017eb90e830SDouglas Gregor 1018eb90e830SDouglas Gregor Best.push_back((*J)->Name); 10195196bc6bSDouglas Gregor } 10205196bc6bSDouglas Gregor } 10215196bc6bSDouglas Gregor 10225196bc6bSDouglas Gregor // If there was a clear winner, user it. 10235196bc6bSDouglas Gregor if (Best.size() == 1) { 10245196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, 10255196bc6bSDouglas Gregor diag::err_no_submodule_suggest) 102669021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() << Best[0] 10275196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second) 10285196bc6bSDouglas Gregor << FixItHint::CreateReplacement(SourceRange(Path[I].second), 10295196bc6bSDouglas Gregor Best[0]); 1030eb90e830SDouglas Gregor 1031eb90e830SDouglas Gregor Sub = Module->findSubmodule(Best[0]); 10325196bc6bSDouglas Gregor } 10335196bc6bSDouglas Gregor } 10345196bc6bSDouglas Gregor 1035eb90e830SDouglas Gregor if (!Sub) { 10365196bc6bSDouglas Gregor // No submodule by this name. Complain, and don't look for further 10375196bc6bSDouglas Gregor // submodules. 10385196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, diag::err_no_submodule) 103969021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() 10405196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second); 10415196bc6bSDouglas Gregor break; 10425196bc6bSDouglas Gregor } 10435196bc6bSDouglas Gregor 1044eb90e830SDouglas Gregor Module = Sub; 10455196bc6bSDouglas Gregor } 10465196bc6bSDouglas Gregor } 10475196bc6bSDouglas Gregor 10482537a364SDouglas Gregor // Make the named module visible, if it's not already part of the module 10492537a364SDouglas Gregor // we are parsing. 105098a52db8SDouglas Gregor if (ModuleName != getLangOpts().CurrentModule) { 105198a52db8SDouglas Gregor if (!Module->IsFromModuleFile) { 105298a52db8SDouglas Gregor // We have an umbrella header or directory that doesn't actually include 105398a52db8SDouglas Gregor // all of the headers within the directory it covers. Complain about 105498a52db8SDouglas Gregor // this missing submodule and recover by forgetting that we ever saw 105598a52db8SDouglas Gregor // this submodule. 105698a52db8SDouglas Gregor // FIXME: Should we detect this at module load time? It seems fairly 105798a52db8SDouglas Gregor // expensive (and rare). 105898a52db8SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule) 105998a52db8SDouglas Gregor << Module->getFullModuleName() 106098a52db8SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 106198a52db8SDouglas Gregor 106298a52db8SDouglas Gregor return 0; 106398a52db8SDouglas Gregor } 10641fb5c3a6SDouglas Gregor 10651fb5c3a6SDouglas Gregor // Check whether this module is available. 10661fb5c3a6SDouglas Gregor StringRef Feature; 106789929282SDouglas Gregor if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) { 10681fb5c3a6SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) 10691fb5c3a6SDouglas Gregor << Module->getFullModuleName() 10701fb5c3a6SDouglas Gregor << Feature 10711fb5c3a6SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 10721fb5c3a6SDouglas Gregor LastModuleImportLoc = ImportLoc; 10731fb5c3a6SDouglas Gregor LastModuleImportResult = 0; 10741fb5c3a6SDouglas Gregor return 0; 10751fb5c3a6SDouglas Gregor } 10761fb5c3a6SDouglas Gregor 1077ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(Module, Visibility); 107898a52db8SDouglas Gregor } 10795196bc6bSDouglas Gregor 1080bcfc7d02SDouglas Gregor // If this module import was due to an inclusion directive, create an 1081bcfc7d02SDouglas Gregor // implicit import declaration to capture it in the AST. 1082bcfc7d02SDouglas Gregor if (IsInclusionDirective && hasASTContext()) { 1083bcfc7d02SDouglas Gregor TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); 1084bcfc7d02SDouglas Gregor TU->addDecl(ImportDecl::CreateImplicit(getASTContext(), TU, 1085bcfc7d02SDouglas Gregor ImportLoc, Module, 1086bcfc7d02SDouglas Gregor Path.back().second)); 1087bcfc7d02SDouglas Gregor } 1088bcfc7d02SDouglas Gregor 10891805b8a4SDouglas Gregor LastModuleImportLoc = ImportLoc; 109069021974SDouglas Gregor LastModuleImportResult = Module; 109169021974SDouglas Gregor return Module; 109208142534SDouglas Gregor } 1093