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); 91*2fca3c2cSErik Verbruggen getFrontendOpts().SkipFunctionBodies = Value != 0; 92e01dc86dSDaniel Dunbar } 93e01dc86dSDaniel Dunbar 947d75afc5SDaniel Dunbar // Diagnostics 957d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 9689c31490SAxel Naumann unsigned argc, const char* const *argv, 979c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 987d75afc5SDaniel Dunbar std::string ErrorInfo; 99e2778999SDylan Noblesmith OwningPtr<raw_ostream> OS( 100eeed0cc3SKovarththanan Rajaratnam new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo)); 1017d75afc5SDaniel Dunbar if (!ErrorInfo.empty()) { 1024a94ba56SKovarththanan Rajaratnam Diags.Report(diag::err_fe_unable_to_open_logfile) 1034a94ba56SKovarththanan Rajaratnam << DiagOpts.DumpBuildInformation << ErrorInfo; 1047d75afc5SDaniel Dunbar return; 1057d75afc5SDaniel Dunbar } 1067d75afc5SDaniel Dunbar 107520d1e6cSDaniel Dunbar (*OS) << "clang -cc1 command line arguments: "; 1087d75afc5SDaniel Dunbar for (unsigned i = 0; i != argc; ++i) 1097d75afc5SDaniel Dunbar (*OS) << argv[i] << ' '; 1107d75afc5SDaniel Dunbar (*OS) << '\n'; 1117d75afc5SDaniel Dunbar 1127d75afc5SDaniel Dunbar // Chain in a diagnostic client which will log the diagnostics. 113e2eefaecSDavid Blaikie DiagnosticConsumer *Logger = 114eeed0cc3SKovarththanan Rajaratnam new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true); 1158b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1167d75afc5SDaniel Dunbar } 1177d75afc5SDaniel Dunbar 1182083c32fSDaniel Dunbar static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, 1197b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts, 1209c902b55SDavid Blaikie DiagnosticsEngine &Diags) { 1212083c32fSDaniel Dunbar std::string ErrorInfo; 1222083c32fSDaniel Dunbar bool OwnsStream = false; 1230e62c1ccSChris Lattner raw_ostream *OS = &llvm::errs(); 1242083c32fSDaniel Dunbar if (DiagOpts.DiagnosticLogFile != "-") { 1252083c32fSDaniel Dunbar // Create the output stream. 1262083c32fSDaniel Dunbar llvm::raw_fd_ostream *FileOS( 1272083c32fSDaniel Dunbar new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(), 12844d9ef78SDaniel Dunbar ErrorInfo, llvm::raw_fd_ostream::F_Append)); 1292083c32fSDaniel Dunbar if (!ErrorInfo.empty()) { 1302083c32fSDaniel Dunbar Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) 1312083c32fSDaniel Dunbar << DiagOpts.DumpBuildInformation << ErrorInfo; 1322083c32fSDaniel Dunbar } else { 1332083c32fSDaniel Dunbar FileOS->SetUnbuffered(); 1342083c32fSDaniel Dunbar FileOS->SetUseAtomicWrites(true); 1352083c32fSDaniel Dunbar OS = FileOS; 1362083c32fSDaniel Dunbar OwnsStream = true; 1372083c32fSDaniel Dunbar } 1382083c32fSDaniel Dunbar } 1392083c32fSDaniel Dunbar 1402083c32fSDaniel Dunbar // Chain in the diagnostic client which will log the diagnostics. 1417b83306dSDaniel Dunbar LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, 1422083c32fSDaniel Dunbar OwnsStream); 1437b83306dSDaniel Dunbar if (CodeGenOpts) 1447b83306dSDaniel Dunbar Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); 1458b00dcb0SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger)); 1462083c32fSDaniel Dunbar } 1472083c32fSDaniel Dunbar 1484610ea2bSTed Kremenek static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts, 1494610ea2bSTed Kremenek DiagnosticsEngine &Diags, 1504610ea2bSTed Kremenek StringRef OutputFile) { 1514610ea2bSTed Kremenek std::string ErrorInfo; 152e2778999SDylan Noblesmith OwningPtr<llvm::raw_fd_ostream> OS; 1534610ea2bSTed Kremenek OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, 1544610ea2bSTed Kremenek llvm::raw_fd_ostream::F_Binary)); 1554610ea2bSTed Kremenek 1564610ea2bSTed Kremenek if (!ErrorInfo.empty()) { 1574610ea2bSTed Kremenek Diags.Report(diag::warn_fe_serialized_diag_failure) 1584610ea2bSTed Kremenek << OutputFile << ErrorInfo; 1594610ea2bSTed Kremenek return; 1604610ea2bSTed Kremenek } 1614610ea2bSTed Kremenek 1624610ea2bSTed Kremenek DiagnosticConsumer *SerializedConsumer = 1634548e044STed Kremenek clang::serialized_diags::create(OS.take(), DiagOpts); 1644610ea2bSTed Kremenek 1654610ea2bSTed Kremenek 1664610ea2bSTed Kremenek Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), 1674610ea2bSTed Kremenek SerializedConsumer)); 1684610ea2bSTed Kremenek } 1694610ea2bSTed Kremenek 17044c6ee77SDouglas Gregor void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, 171e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 172d0e9e3a6SDouglas Gregor bool ShouldOwnClient, 173d0e9e3a6SDouglas Gregor bool ShouldCloneClient) { 1747b83306dSDaniel Dunbar Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client, 175d0e9e3a6SDouglas Gregor ShouldOwnClient, ShouldCloneClient, 176d0e9e3a6SDouglas Gregor &getCodeGenOpts()); 1777d75afc5SDaniel Dunbar } 1787d75afc5SDaniel Dunbar 179c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine> 1807f95d26eSDouglas Gregor CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 18144c6ee77SDouglas Gregor int Argc, const char* const *Argv, 182e2eefaecSDavid Blaikie DiagnosticConsumer *Client, 1832b9b4642SDouglas Gregor bool ShouldOwnClient, 184d0e9e3a6SDouglas Gregor bool ShouldCloneClient, 1857b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts) { 186c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 187c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine> 1889c902b55SDavid Blaikie Diags(new DiagnosticsEngine(DiagID)); 1891b39a2edSDaniel Dunbar 1907d75afc5SDaniel Dunbar // Create the diagnostic client for reporting errors or for 1917d75afc5SDaniel Dunbar // implementing -verify. 192d0e9e3a6SDouglas Gregor if (Client) { 193d0e9e3a6SDouglas Gregor if (ShouldCloneClient) 194d0e9e3a6SDouglas Gregor Diags->setClient(Client->clone(*Diags), ShouldOwnClient); 19544c6ee77SDouglas Gregor else 196d0e9e3a6SDouglas Gregor Diags->setClient(Client, ShouldOwnClient); 197d0e9e3a6SDouglas Gregor } else 1982dd19f1dSDouglas Gregor Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); 19950ec0da0SDaniel Dunbar 20050ec0da0SDaniel Dunbar // Chain in -verify checker, if requested. 20150ec0da0SDaniel Dunbar if (Opts.VerifyDiagnostics) 20269609dceSDavid Blaikie Diags->setClient(new VerifyDiagnosticConsumer(*Diags)); 2037d75afc5SDaniel Dunbar 2042083c32fSDaniel Dunbar // Chain in -diagnostic-log-file dumper, if requested. 2052083c32fSDaniel Dunbar if (!Opts.DiagnosticLogFile.empty()) 2067b83306dSDaniel Dunbar SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags); 2072083c32fSDaniel Dunbar 2087d75afc5SDaniel Dunbar if (!Opts.DumpBuildInformation.empty()) 2094a94ba56SKovarththanan Rajaratnam SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); 2107d75afc5SDaniel Dunbar 2114610ea2bSTed Kremenek if (!Opts.DiagnosticSerializationFile.empty()) 2124610ea2bSTed Kremenek SetupSerializedDiagnostics(Opts, *Diags, 2134610ea2bSTed Kremenek Opts.DiagnosticSerializationFile); 2144610ea2bSTed Kremenek 2157d75afc5SDaniel Dunbar // Configure our handling of diagnostics. 2169ff84d9cSKovarththanan Rajaratnam ProcessWarningOptions(*Diags, Opts); 2177d75afc5SDaniel Dunbar 2187f95d26eSDouglas Gregor return Diags; 2197d75afc5SDaniel Dunbar } 2207d75afc5SDaniel Dunbar 2217d75afc5SDaniel Dunbar // File Manager 2227d75afc5SDaniel Dunbar 223546a676aSDaniel Dunbar void CompilerInstance::createFileManager() { 2245e14d39aSTed Kremenek FileMgr = new FileManager(getFileSystemOpts()); 225546a676aSDaniel Dunbar } 226546a676aSDaniel Dunbar 2277d75afc5SDaniel Dunbar // Source Manager 2287d75afc5SDaniel Dunbar 2295159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) { 2305e14d39aSTed Kremenek SourceMgr = new SourceManager(getDiagnostics(), FileMgr); 231546a676aSDaniel Dunbar } 232aaa148fdSDaniel Dunbar 2337d75afc5SDaniel Dunbar // Preprocessor 2347d75afc5SDaniel Dunbar 235aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() { 23608142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 237aaa148fdSDaniel Dunbar 238aaa148fdSDaniel Dunbar // Create a PTH manager if we are using some form of a token cache. 239aaa148fdSDaniel Dunbar PTHManager *PTHMgr = 0; 240d6ea9028SDaniel Dunbar if (!PPOpts.TokenCache.empty()) 24108142534SDouglas Gregor PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics()); 242aaa148fdSDaniel Dunbar 243aaa148fdSDaniel Dunbar // Create the Preprocessor. 244197ac203SDouglas Gregor HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(), 2451fb5c3a6SDouglas Gregor getDiagnostics(), 24689929282SDouglas Gregor getLangOpts(), 24789929282SDouglas Gregor &getTarget()); 24883297dfcSDouglas Gregor PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(), 24908142534SDouglas Gregor getSourceManager(), *HeaderInfo, *this, PTHMgr, 250aaa148fdSDaniel Dunbar /*OwnsHeaderSearch=*/true); 251aaa148fdSDaniel Dunbar 252aaa148fdSDaniel Dunbar // Note that this is different then passing PTHMgr to Preprocessor's ctor. 253aaa148fdSDaniel Dunbar // That argument is used as the IdentifierInfoLookup argument to 254aaa148fdSDaniel Dunbar // IdentifierTable's ctor. 255aaa148fdSDaniel Dunbar if (PTHMgr) { 25608142534SDouglas Gregor PTHMgr->setPreprocessor(&*PP); 257aaa148fdSDaniel Dunbar PP->setPTHManager(PTHMgr); 258aaa148fdSDaniel Dunbar } 259aaa148fdSDaniel Dunbar 2607f6d60dcSDouglas Gregor if (PPOpts.DetailedRecord) 261647dcd80SArgyrios Kyrtzidis PP->createPreprocessingRecord(PPOpts.DetailedRecordConditionalDirectives); 2627f6d60dcSDouglas Gregor 26308142534SDouglas Gregor InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts()); 264aaa148fdSDaniel Dunbar 2651735f4e7SDouglas Gregor // Set up the module path, including the hash for the 2661735f4e7SDouglas Gregor // module-creation options. 2672c1dd271SDylan Noblesmith SmallString<256> SpecificModuleCache( 2681735f4e7SDouglas Gregor getHeaderSearchOpts().ModuleCachePath); 2691735f4e7SDouglas Gregor if (!getHeaderSearchOpts().DisableModuleHash) 2701735f4e7SDouglas Gregor llvm::sys::path::append(SpecificModuleCache, 2711735f4e7SDouglas Gregor getInvocation().getModuleHash()); 2722537a364SDouglas Gregor PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); 2731735f4e7SDouglas Gregor 274aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested. 27508142534SDouglas Gregor const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); 276aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty()) 277aaa148fdSDaniel Dunbar AttachDependencyFileGen(*PP, DepOpts); 2782e129659SDouglas Gregor if (!DepOpts.DOTOutputFile.empty()) 2792e129659SDouglas Gregor AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, 28083d46be3SDouglas Gregor getHeaderSearchOpts().Sysroot); 28183d46be3SDouglas Gregor 282aaa148fdSDaniel Dunbar 28327734fdbSDaniel Dunbar // Handle generating header include information, if requested. 28427734fdbSDaniel Dunbar if (DepOpts.ShowHeaderIncludes) 28527734fdbSDaniel Dunbar AttachHeaderIncludeGen(*PP); 2861af1d275SDaniel Dunbar if (!DepOpts.HeaderIncludeOutputFile.empty()) { 2870e62c1ccSChris Lattner StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; 2881af1d275SDaniel Dunbar if (OutputPath == "-") 2891af1d275SDaniel Dunbar OutputPath = ""; 290fe908a80SDaniel Dunbar AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, 291fe908a80SDaniel Dunbar /*ShowDepth=*/false); 2921af1d275SDaniel Dunbar } 293aaa148fdSDaniel Dunbar } 294df3e30c4SDaniel Dunbar 295df3e30c4SDaniel Dunbar // ASTContext 296df3e30c4SDaniel Dunbar 297df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() { 298df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor(); 2995e14d39aSTed Kremenek Context = new ASTContext(getLangOpts(), PP.getSourceManager(), 300e8bbc121SDouglas Gregor &getTarget(), PP.getIdentifierTable(), 301df3e30c4SDaniel Dunbar PP.getSelectorTable(), PP.getBuiltinInfo(), 3025e14d39aSTed Kremenek /*size_reserve=*/ 0); 303df3e30c4SDaniel Dunbar } 304599313efSDaniel Dunbar 305599313efSDaniel Dunbar // ExternalASTSource 306599313efSDaniel Dunbar 3070e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path, 30807a89a83SSebastian Redl bool DisablePCHValidation, 309606c4ac3SDouglas Gregor bool DisableStatCache, 3104a280ff4SArgyrios Kyrtzidis bool AllowPCHWithCompilerErrors, 31107a89a83SSebastian Redl void *DeserializationListener){ 312e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 313009e7f20SSebastian Redl bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; 314599313efSDaniel Dunbar Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 315ce3a8293SDouglas Gregor DisablePCHValidation, 316606c4ac3SDouglas Gregor DisableStatCache, 3174a280ff4SArgyrios Kyrtzidis AllowPCHWithCompilerErrors, 31807a89a83SSebastian Redl getPreprocessor(), getASTContext(), 319009e7f20SSebastian Redl DeserializationListener, 320009e7f20SSebastian Redl Preamble)); 321925296b4SDouglas Gregor ModuleManager = static_cast<ASTReader*>(Source.get()); 322599313efSDaniel Dunbar getASTContext().setExternalSource(Source); 323599313efSDaniel Dunbar } 324599313efSDaniel Dunbar 325599313efSDaniel Dunbar ExternalASTSource * 3260e62c1ccSChris Lattner CompilerInstance::createPCHExternalASTSource(StringRef Path, 327599313efSDaniel Dunbar const std::string &Sysroot, 328ce3a8293SDouglas Gregor bool DisablePCHValidation, 329606c4ac3SDouglas Gregor bool DisableStatCache, 3304a280ff4SArgyrios Kyrtzidis bool AllowPCHWithCompilerErrors, 331599313efSDaniel Dunbar Preprocessor &PP, 33207a89a83SSebastian Redl ASTContext &Context, 333009e7f20SSebastian Redl void *DeserializationListener, 334009e7f20SSebastian Redl bool Preamble) { 335e2778999SDylan Noblesmith OwningPtr<ASTReader> Reader; 3368835e03cSDouglas Gregor Reader.reset(new ASTReader(PP, Context, 337c567ba26SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 3384a280ff4SArgyrios Kyrtzidis DisablePCHValidation, DisableStatCache, 3394a280ff4SArgyrios Kyrtzidis AllowPCHWithCompilerErrors)); 340599313efSDaniel Dunbar 34107a89a83SSebastian Redl Reader->setDeserializationListener( 3423e31c724SSebastian Redl static_cast<ASTDeserializationListener *>(DeserializationListener)); 343009e7f20SSebastian Redl switch (Reader->ReadAST(Path, 344a6895d8aSDouglas Gregor Preamble ? serialization::MK_Preamble 345a6895d8aSDouglas Gregor : serialization::MK_PCH)) { 3462c499f65SSebastian Redl case ASTReader::Success: 347599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the 348599313efSDaniel Dunbar // predefines buffer will be empty. 349599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines()); 350599313efSDaniel Dunbar return Reader.take(); 351599313efSDaniel Dunbar 3522c499f65SSebastian Redl case ASTReader::Failure: 353599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file. 354599313efSDaniel Dunbar break; 355599313efSDaniel Dunbar 3562c499f65SSebastian Redl case ASTReader::IgnorePCH: 357599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error. 358599313efSDaniel Dunbar break; 359599313efSDaniel Dunbar } 360599313efSDaniel Dunbar 361599313efSDaniel Dunbar return 0; 362599313efSDaniel Dunbar } 363f7093b5aSDaniel Dunbar 364f7093b5aSDaniel Dunbar // Code Completion 365f7093b5aSDaniel Dunbar 3668e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP, 3678e984da8SDouglas Gregor const std::string &Filename, 3688e984da8SDouglas Gregor unsigned Line, 3698e984da8SDouglas Gregor unsigned Column) { 3708e984da8SDouglas Gregor // Tell the source manager to chop off the given file at a specific 3718e984da8SDouglas Gregor // line and column. 3725159f616SChris Lattner const FileEntry *Entry = PP.getFileManager().getFile(Filename); 3738e984da8SDouglas Gregor if (!Entry) { 3748e984da8SDouglas Gregor PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 3758e984da8SDouglas Gregor << Filename; 3768e984da8SDouglas Gregor return true; 3778e984da8SDouglas Gregor } 3788e984da8SDouglas Gregor 3798e984da8SDouglas Gregor // Truncate the named file at the given line/column. 3808e984da8SDouglas Gregor PP.SetCodeCompletionPoint(Entry, Line, Column); 3818e984da8SDouglas Gregor return false; 3828e984da8SDouglas Gregor } 3838e984da8SDouglas Gregor 384f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() { 385f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 3868e984da8SDouglas Gregor if (!CompletionConsumer) { 387*2fca3c2cSErik Verbruggen setCodeCompletionConsumer( 388f7093b5aSDaniel Dunbar createCodeCompletionConsumer(getPreprocessor(), 389f7093b5aSDaniel Dunbar Loc.FileName, Loc.Line, Loc.Column, 390f7093b5aSDaniel Dunbar getFrontendOpts().ShowMacrosInCodeCompletion, 391f64acca2SDouglas Gregor getFrontendOpts().ShowCodePatternsInCodeCompletion, 39239982197SDouglas Gregor getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, 393f7093b5aSDaniel Dunbar llvm::outs())); 39400a0cf70SDouglas Gregor if (!CompletionConsumer) 39500a0cf70SDouglas Gregor return; 3968e984da8SDouglas Gregor } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName, 3978e984da8SDouglas Gregor Loc.Line, Loc.Column)) { 398*2fca3c2cSErik Verbruggen setCodeCompletionConsumer(0); 3998e984da8SDouglas Gregor return; 4008e984da8SDouglas Gregor } 401f09935f1SDouglas Gregor 402f09935f1SDouglas Gregor if (CompletionConsumer->isOutputBinary() && 403f09935f1SDouglas Gregor llvm::sys::Program::ChangeStdoutToBinary()) { 404f09935f1SDouglas Gregor getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 405*2fca3c2cSErik Verbruggen setCodeCompletionConsumer(0); 406f09935f1SDouglas Gregor } 407f7093b5aSDaniel Dunbar } 408f7093b5aSDaniel Dunbar 4095505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() { 4105505dff8SKovarththanan Rajaratnam FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 4115505dff8SKovarththanan Rajaratnam } 4125505dff8SKovarththanan Rajaratnam 413f7093b5aSDaniel Dunbar CodeCompleteConsumer * 414f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 415f7093b5aSDaniel Dunbar const std::string &Filename, 416f7093b5aSDaniel Dunbar unsigned Line, 417f7093b5aSDaniel Dunbar unsigned Column, 418f7093b5aSDaniel Dunbar bool ShowMacros, 419f64acca2SDouglas Gregor bool ShowCodePatterns, 42039982197SDouglas Gregor bool ShowGlobals, 4210e62c1ccSChris Lattner raw_ostream &OS) { 4228e984da8SDouglas Gregor if (EnableCodeCompletion(PP, Filename, Line, Column)) 423f7093b5aSDaniel Dunbar return 0; 424f7093b5aSDaniel Dunbar 425f7093b5aSDaniel Dunbar // Set up the creation routine for code-completion. 42639982197SDouglas Gregor return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, 42739982197SDouglas Gregor ShowGlobals, OS); 428f7093b5aSDaniel Dunbar } 429566eeb2dSDaniel Dunbar 43069f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind, 4310e93f017SDouglas Gregor CodeCompleteConsumer *CompletionConsumer) { 4320e93f017SDouglas Gregor TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(), 43369f74f80SDouglas Gregor TUKind, CompletionConsumer)); 4340e93f017SDouglas Gregor } 4350e93f017SDouglas Gregor 436566eeb2dSDaniel Dunbar // Output Files 437566eeb2dSDaniel Dunbar 438d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) { 439d0599970SArgyrios Kyrtzidis assert(OutFile.OS && "Attempt to add empty stream to output list!"); 440d0599970SArgyrios Kyrtzidis OutputFiles.push_back(OutFile); 441566eeb2dSDaniel Dunbar } 442566eeb2dSDaniel Dunbar 4431c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) { 444d0599970SArgyrios Kyrtzidis for (std::list<OutputFile>::iterator 445566eeb2dSDaniel Dunbar it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 446d0599970SArgyrios Kyrtzidis delete it->OS; 447d0599970SArgyrios Kyrtzidis if (!it->TempFilename.empty()) { 448b5c356a4SAnders Carlsson if (EraseFiles) { 449b5c356a4SAnders Carlsson bool existed; 450b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 451b5c356a4SAnders Carlsson } else { 4522c1dd271SDylan Noblesmith SmallString<128> NewOutFile(it->Filename); 453b5c356a4SAnders Carlsson 45471731d6bSArgyrios Kyrtzidis // If '-working-directory' was passed, the output filename should be 45571731d6bSArgyrios Kyrtzidis // relative to that. 4569ba8fb1eSAnders Carlsson FileMgr->FixupRelativePath(NewOutFile); 457b5c356a4SAnders Carlsson if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, 458b5c356a4SAnders Carlsson NewOutFile.str())) { 459d0599970SArgyrios Kyrtzidis getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) 460b5c356a4SAnders Carlsson << it->TempFilename << it->Filename << ec.message(); 461b5c356a4SAnders Carlsson 462b5c356a4SAnders Carlsson bool existed; 463b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 464d0599970SArgyrios Kyrtzidis } 465d0599970SArgyrios Kyrtzidis } 466d0599970SArgyrios Kyrtzidis } else if (!it->Filename.empty() && EraseFiles) 467d0599970SArgyrios Kyrtzidis llvm::sys::Path(it->Filename).eraseFromDisk(); 468d0599970SArgyrios Kyrtzidis 469566eeb2dSDaniel Dunbar } 470566eeb2dSDaniel Dunbar OutputFiles.clear(); 471566eeb2dSDaniel Dunbar } 472566eeb2dSDaniel Dunbar 473420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 474420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary, 4750e62c1ccSChris Lattner StringRef InFile, 4760e62c1ccSChris Lattner StringRef Extension) { 477420b0f1bSDaniel Dunbar return createOutputFile(getFrontendOpts().OutputFile, Binary, 478ae77b3dfSDaniel Dunbar /*RemoveFileOnSignal=*/true, InFile, Extension, 479ae77b3dfSDaniel Dunbar /*UseTemporary=*/true); 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, 487b9c62c07SDaniel Dunbar bool UseTemporary, 488b9c62c07SDaniel Dunbar bool CreateMissingDirectories) { 489d0599970SArgyrios Kyrtzidis std::string Error, OutputPathName, TempPathName; 490420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 491e326f9bbSDaniel Dunbar RemoveFileOnSignal, 492420b0f1bSDaniel Dunbar InFile, Extension, 49308a2bfd2SArgyrios Kyrtzidis UseTemporary, 494b9c62c07SDaniel Dunbar CreateMissingDirectories, 495d0599970SArgyrios Kyrtzidis &OutputPathName, 496d0599970SArgyrios Kyrtzidis &TempPathName); 497420b0f1bSDaniel Dunbar if (!OS) { 4987554699aSDaniel Dunbar getDiagnostics().Report(diag::err_fe_unable_to_open_output) 4997554699aSDaniel Dunbar << OutputPath << Error; 5007554699aSDaniel Dunbar return 0; 501420b0f1bSDaniel Dunbar } 502420b0f1bSDaniel Dunbar 503420b0f1bSDaniel Dunbar // Add the output file -- but don't try to remove "-", since this means we are 504420b0f1bSDaniel Dunbar // using stdin. 505d0599970SArgyrios Kyrtzidis addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", 506d0599970SArgyrios Kyrtzidis TempPathName, OS)); 507420b0f1bSDaniel Dunbar 508420b0f1bSDaniel Dunbar return OS; 509420b0f1bSDaniel Dunbar } 510420b0f1bSDaniel Dunbar 511420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 5120e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 513420b0f1bSDaniel Dunbar std::string &Error, 514420b0f1bSDaniel Dunbar bool Binary, 515e326f9bbSDaniel Dunbar bool RemoveFileOnSignal, 5160e62c1ccSChris Lattner StringRef InFile, 5170e62c1ccSChris Lattner StringRef Extension, 51808a2bfd2SArgyrios Kyrtzidis bool UseTemporary, 519b9c62c07SDaniel Dunbar bool CreateMissingDirectories, 520d0599970SArgyrios Kyrtzidis std::string *ResultPathName, 521d0599970SArgyrios Kyrtzidis std::string *TempPathName) { 522b9c62c07SDaniel Dunbar assert((!CreateMissingDirectories || UseTemporary) && 523b9c62c07SDaniel Dunbar "CreateMissingDirectories is only allowed when using temporary files"); 524b9c62c07SDaniel Dunbar 525d0599970SArgyrios Kyrtzidis std::string OutFile, TempFile; 526420b0f1bSDaniel Dunbar if (!OutputPath.empty()) { 527420b0f1bSDaniel Dunbar OutFile = OutputPath; 528420b0f1bSDaniel Dunbar } else if (InFile == "-") { 529420b0f1bSDaniel Dunbar OutFile = "-"; 530420b0f1bSDaniel Dunbar } else if (!Extension.empty()) { 531420b0f1bSDaniel Dunbar llvm::sys::Path Path(InFile); 532420b0f1bSDaniel Dunbar Path.eraseSuffix(); 533420b0f1bSDaniel Dunbar Path.appendSuffix(Extension); 534420b0f1bSDaniel Dunbar OutFile = Path.str(); 535420b0f1bSDaniel Dunbar } else { 536420b0f1bSDaniel Dunbar OutFile = "-"; 537420b0f1bSDaniel Dunbar } 538420b0f1bSDaniel Dunbar 539e2778999SDylan Noblesmith OwningPtr<llvm::raw_fd_ostream> OS; 54008a2bfd2SArgyrios Kyrtzidis std::string OSFile; 54108a2bfd2SArgyrios Kyrtzidis 54208a2bfd2SArgyrios Kyrtzidis if (UseTemporary && OutFile != "-") { 543b9c62c07SDaniel Dunbar // Only create the temporary if the parent directory exists (or create 544b9c62c07SDaniel Dunbar // missing directories is true) and we can actually write to OutPath, 545b9c62c07SDaniel Dunbar // otherwise we want to fail early. 546b9c62c07SDaniel Dunbar SmallString<256> AbsPath(OutputPath); 547b9c62c07SDaniel Dunbar llvm::sys::fs::make_absolute(AbsPath); 548b9c62c07SDaniel Dunbar llvm::sys::Path OutPath(AbsPath); 549b9c62c07SDaniel Dunbar bool ParentExists = false; 550b9c62c07SDaniel Dunbar if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()), 551b9c62c07SDaniel Dunbar ParentExists)) 552b9c62c07SDaniel Dunbar ParentExists = false; 553f6efe58dSMichael J. Spencer bool Exists; 554b9c62c07SDaniel Dunbar if ((CreateMissingDirectories || ParentExists) && 555b9c62c07SDaniel Dunbar ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) || 556b9c62c07SDaniel Dunbar (OutPath.isRegularFile() && OutPath.canWrite()))) { 557d0599970SArgyrios Kyrtzidis // Create a temporary file. 5582c1dd271SDylan Noblesmith SmallString<128> TempPath; 55908a2bfd2SArgyrios Kyrtzidis TempPath = OutFile; 56008a2bfd2SArgyrios Kyrtzidis TempPath += "-%%%%%%%%"; 56108a2bfd2SArgyrios Kyrtzidis int fd; 56208a2bfd2SArgyrios Kyrtzidis if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, 56308a2bfd2SArgyrios Kyrtzidis /*makeAbsolute=*/false) == llvm::errc::success) { 56408a2bfd2SArgyrios Kyrtzidis OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); 56508a2bfd2SArgyrios Kyrtzidis OSFile = TempFile = TempPath.str(); 56608a2bfd2SArgyrios Kyrtzidis } 567d0599970SArgyrios Kyrtzidis } 568d0599970SArgyrios Kyrtzidis } 569d0599970SArgyrios Kyrtzidis 57008a2bfd2SArgyrios Kyrtzidis if (!OS) { 57108a2bfd2SArgyrios Kyrtzidis OSFile = OutFile; 57208a2bfd2SArgyrios Kyrtzidis OS.reset( 573d0599970SArgyrios Kyrtzidis new llvm::raw_fd_ostream(OSFile.c_str(), Error, 5742eaef18eSDaniel Dunbar (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 5752eaef18eSDaniel Dunbar if (!Error.empty()) 576420b0f1bSDaniel Dunbar return 0; 57708a2bfd2SArgyrios Kyrtzidis } 578420b0f1bSDaniel Dunbar 579d0599970SArgyrios Kyrtzidis // Make sure the out stream file gets removed if we crash. 580e326f9bbSDaniel Dunbar if (RemoveFileOnSignal) 581d0599970SArgyrios Kyrtzidis llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); 582d0599970SArgyrios Kyrtzidis 583420b0f1bSDaniel Dunbar if (ResultPathName) 584420b0f1bSDaniel Dunbar *ResultPathName = OutFile; 585d0599970SArgyrios Kyrtzidis if (TempPathName) 586d0599970SArgyrios Kyrtzidis *TempPathName = TempFile; 587420b0f1bSDaniel Dunbar 5882eaef18eSDaniel Dunbar return OS.take(); 589420b0f1bSDaniel Dunbar } 590409e890fSDaniel Dunbar 591409e890fSDaniel Dunbar // Initialization Utilities 592409e890fSDaniel Dunbar 593a686e1b0SDouglas Gregor bool CompilerInstance::InitializeSourceManager(StringRef InputFile, 594a686e1b0SDouglas Gregor SrcMgr::CharacteristicKind Kind){ 595a686e1b0SDouglas Gregor return InitializeSourceManager(InputFile, Kind, getDiagnostics(), 596a686e1b0SDouglas Gregor getFileManager(), getSourceManager(), 597a686e1b0SDouglas Gregor getFrontendOpts()); 598409e890fSDaniel Dunbar } 599409e890fSDaniel Dunbar 6000e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile, 601a686e1b0SDouglas Gregor SrcMgr::CharacteristicKind Kind, 6029c902b55SDavid Blaikie DiagnosticsEngine &Diags, 603409e890fSDaniel Dunbar FileManager &FileMgr, 604409e890fSDaniel Dunbar SourceManager &SourceMgr, 605409e890fSDaniel Dunbar const FrontendOptions &Opts) { 6067c06d866SArgyrios Kyrtzidis // Figure out where to get and map in the main file. 6077c06d866SArgyrios Kyrtzidis if (InputFile != "-") { 6085159f616SChris Lattner const FileEntry *File = FileMgr.getFile(InputFile); 60952765215SDan Gohman if (!File) { 610409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile; 611409e890fSDaniel Dunbar return false; 612409e890fSDaniel Dunbar } 613a686e1b0SDouglas Gregor SourceMgr.createMainFileID(File, Kind); 614409e890fSDaniel Dunbar } else { 615e2778999SDylan Noblesmith OwningPtr<llvm::MemoryBuffer> SB; 616d9da7a1fSMichael J. Spencer if (llvm::MemoryBuffer::getSTDIN(SB)) { 617f25faaafSMichael J. Spencer // FIXME: Give ec.message() in this diag. 618409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading_stdin); 619409e890fSDaniel Dunbar return false; 620409e890fSDaniel Dunbar } 6212f76cd75SDan Gohman const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), 6225159f616SChris Lattner SB->getBufferSize(), 0); 623a686e1b0SDouglas Gregor SourceMgr.createMainFileID(File, Kind); 624d9da7a1fSMichael J. Spencer SourceMgr.overrideFileContents(File, SB.take()); 625409e890fSDaniel Dunbar } 626409e890fSDaniel Dunbar 62752765215SDan Gohman assert(!SourceMgr.getMainFileID().isInvalid() && 62852765215SDan Gohman "Couldn't establish MainFileID!"); 629409e890fSDaniel Dunbar return true; 630409e890fSDaniel Dunbar } 6314f2bc55dSDaniel Dunbar 6324f2bc55dSDaniel Dunbar // High-Level Operations 6334f2bc55dSDaniel Dunbar 6344f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 6354f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 6364f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 6374f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 6384f2bc55dSDaniel Dunbar 6394f2bc55dSDaniel Dunbar // FIXME: Take this as an argument, once all the APIs we used have moved to 6404f2bc55dSDaniel Dunbar // taking it as an input instead of hard-coding llvm::errs. 6410e62c1ccSChris Lattner raw_ostream &OS = llvm::errs(); 6424f2bc55dSDaniel Dunbar 6434f2bc55dSDaniel Dunbar // Create the target instance. 6444f2bc55dSDaniel Dunbar setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 6454f2bc55dSDaniel Dunbar if (!hasTarget()) 6464f2bc55dSDaniel Dunbar return false; 6474f2bc55dSDaniel Dunbar 6484f2bc55dSDaniel Dunbar // Inform the target of the language options. 6494f2bc55dSDaniel Dunbar // 6504f2bc55dSDaniel Dunbar // FIXME: We shouldn't need to do this, the target should be immutable once 6514f2bc55dSDaniel Dunbar // created. This complexity should be lifted elsewhere. 6524f2bc55dSDaniel Dunbar getTarget().setForcedLangOptions(getLangOpts()); 6534f2bc55dSDaniel Dunbar 6544f2bc55dSDaniel Dunbar // Validate/process some options. 6554f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose) 6564f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING 6574f2bc55dSDaniel Dunbar << " based upon " << PACKAGE_STRING 6588188c8a1SSebastian Pop << " default target " << llvm::sys::getDefaultTargetTriple() << "\n"; 6594f2bc55dSDaniel Dunbar 6604f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowTimers) 6614f2bc55dSDaniel Dunbar createFrontendTimer(); 6624f2bc55dSDaniel Dunbar 663171b780cSDouglas Gregor if (getFrontendOpts().ShowStats) 664171b780cSDouglas Gregor llvm::EnableStatistics(); 665171b780cSDouglas Gregor 6664f2bc55dSDaniel Dunbar for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 6674f2bc55dSDaniel Dunbar // Reset the ID tables if we are reusing the SourceManager. 668aed46fcbSDaniel Dunbar if (hasSourceManager()) 6694f2bc55dSDaniel Dunbar getSourceManager().clearIDTables(); 6704f2bc55dSDaniel Dunbar 67132fbe312SDouglas Gregor if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) { 6724f2bc55dSDaniel Dunbar Act.Execute(); 6734f2bc55dSDaniel Dunbar Act.EndSourceFile(); 6744f2bc55dSDaniel Dunbar } 6754f2bc55dSDaniel Dunbar } 6764f2bc55dSDaniel Dunbar 6777910d7b7SArgyrios Kyrtzidis // Notify the diagnostic client that all files were processed. 6787910d7b7SArgyrios Kyrtzidis getDiagnostics().getClient()->finish(); 6797910d7b7SArgyrios Kyrtzidis 680198cb4dfSChris Lattner if (getDiagnosticOpts().ShowCarets) { 681c79346a5SArgyrios Kyrtzidis // We can have multiple diagnostics sharing one diagnostic client. 682c79346a5SArgyrios Kyrtzidis // Get the total number of warnings/errors from the client. 683c79346a5SArgyrios Kyrtzidis unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); 684c79346a5SArgyrios Kyrtzidis unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); 685198cb4dfSChris Lattner 686198cb4dfSChris Lattner if (NumWarnings) 687198cb4dfSChris Lattner OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); 688198cb4dfSChris Lattner if (NumWarnings && NumErrors) 689198cb4dfSChris Lattner OS << " and "; 690198cb4dfSChris Lattner if (NumErrors) 691198cb4dfSChris Lattner OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); 692198cb4dfSChris Lattner if (NumWarnings || NumErrors) 693198cb4dfSChris Lattner OS << " generated.\n"; 694198cb4dfSChris Lattner } 6954f2bc55dSDaniel Dunbar 696aed46fcbSDaniel Dunbar if (getFrontendOpts().ShowStats && hasFileManager()) { 6974f2bc55dSDaniel Dunbar getFileManager().PrintStats(); 6984f2bc55dSDaniel Dunbar OS << "\n"; 6994f2bc55dSDaniel Dunbar } 7004f2bc55dSDaniel Dunbar 701bc467933SArgyrios Kyrtzidis return !getDiagnostics().getClient()->getNumErrors(); 7024f2bc55dSDaniel Dunbar } 7034f2bc55dSDaniel Dunbar 704faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language 705faeb1d46SDouglas Gregor /// options. 706faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { 707faeb1d46SDouglas Gregor if (LangOpts.OpenCL) 708faeb1d46SDouglas Gregor return IK_OpenCL; 709faeb1d46SDouglas Gregor if (LangOpts.CUDA) 710faeb1d46SDouglas Gregor return IK_CUDA; 711faeb1d46SDouglas Gregor if (LangOpts.ObjC1) 712faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC; 713faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_CXX : IK_C; 714faeb1d46SDouglas Gregor } 715faeb1d46SDouglas Gregor 71651e0b541SDouglas Gregor namespace { 717514b636aSDouglas Gregor struct CompileModuleMapData { 718514b636aSDouglas Gregor CompilerInstance &Instance; 719514b636aSDouglas Gregor GenerateModuleAction &CreateModuleAction; 720514b636aSDouglas Gregor }; 721514b636aSDouglas Gregor } 722514b636aSDouglas Gregor 723514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under 724514b636aSDouglas Gregor /// a crash recovery context. 725514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) { 726514b636aSDouglas Gregor CompileModuleMapData &Data 727514b636aSDouglas Gregor = *reinterpret_cast<CompileModuleMapData *>(UserData); 728514b636aSDouglas Gregor Data.Instance.ExecuteAction(Data.CreateModuleAction); 729514b636aSDouglas Gregor } 730514b636aSDouglas Gregor 731514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options 732514b636aSDouglas Gregor /// provided by the importing compiler instance. 733faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance, 734de3ef502SDouglas Gregor Module *Module, 7356dc57927SDouglas Gregor StringRef ModuleFileName) { 736e212489fSDouglas Gregor llvm::LockFileManager Locked(ModuleFileName); 73754a88810SDouglas Gregor switch (Locked) { 738e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Error: 73954a88810SDouglas Gregor return; 74054a88810SDouglas Gregor 741e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Owned: 74254a88810SDouglas Gregor // We're responsible for building the module ourselves. Do so below. 74354a88810SDouglas Gregor break; 74454a88810SDouglas Gregor 745e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Shared: 74654a88810SDouglas Gregor // Someone else is responsible for building the module. Wait for them to 74754a88810SDouglas Gregor // finish. 74854a88810SDouglas Gregor Locked.waitForUnlock(); 74954a88810SDouglas Gregor break; 75054a88810SDouglas Gregor } 75154a88810SDouglas Gregor 752514b636aSDouglas Gregor ModuleMap &ModMap 753514b636aSDouglas Gregor = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); 754514b636aSDouglas Gregor 755faeb1d46SDouglas Gregor // Construct a compiler invocation for creating this module. 756c95d8192SDylan Noblesmith IntrusiveRefCntPtr<CompilerInvocation> Invocation 757faeb1d46SDouglas Gregor (new CompilerInvocation(ImportingInstance.getInvocation())); 75844bf68d8SDouglas Gregor 759f545f67dSDouglas Gregor PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); 760f545f67dSDouglas Gregor 76144bf68d8SDouglas Gregor // For any options that aren't intended to affect how a module is built, 76244bf68d8SDouglas Gregor // reset them to their default values. 7638cf47df7STed Kremenek Invocation->getLangOpts()->resetNonModularOptions(); 764f545f67dSDouglas Gregor PPOpts.resetNonModularOptions(); 76544bf68d8SDouglas Gregor 7667d106e42SDouglas Gregor // Note the name of the module we're building. 7676dc57927SDouglas Gregor Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); 7687d106e42SDouglas Gregor 76944bf68d8SDouglas Gregor // Note that this module is part of the module build path, so that we 77044bf68d8SDouglas Gregor // can detect cycles in the module graph. 771f545f67dSDouglas Gregor PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName()); 772f1312a82SDouglas Gregor 773514b636aSDouglas Gregor // If there is a module map file, build the module using the module map. 774514b636aSDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella 775514b636aSDouglas Gregor // header. 776514b636aSDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 777514b636aSDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str(); 778514b636aSDouglas Gregor FrontendOpts.DisableFree = false; 779514b636aSDouglas Gregor FrontendOpts.Inputs.clear(); 780f545f67dSDouglas Gregor InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); 781f545f67dSDouglas Gregor 782f545f67dSDouglas Gregor // Get or create the module map that we'll use to build this module. 7832c1dd271SDylan Noblesmith SmallString<128> TempModuleMapFileName; 784f545f67dSDouglas Gregor if (const FileEntry *ModuleMapFile 785f545f67dSDouglas Gregor = ModMap.getContainingModuleMapFile(Module)) { 786f545f67dSDouglas Gregor // Use the module map where this module resides. 78732fbe312SDouglas Gregor FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), 78832fbe312SDouglas Gregor IK)); 789f545f67dSDouglas Gregor } else { 790f545f67dSDouglas Gregor // Create a temporary module map file. 791f545f67dSDouglas Gregor TempModuleMapFileName = Module->Name; 792f545f67dSDouglas Gregor TempModuleMapFileName += "-%%%%%%%%.map"; 793f545f67dSDouglas Gregor int FD; 794f545f67dSDouglas Gregor if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, 795f545f67dSDouglas Gregor TempModuleMapFileName, 79619f9f7bcSDouglas Gregor /*makeAbsolute=*/true) 7972f554c4cSDouglas Gregor != llvm::errc::success) { 798ee78d3e0SDouglas Gregor ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) 799ee78d3e0SDouglas Gregor << TempModuleMapFileName; 800f545f67dSDouglas Gregor return; 8012f554c4cSDouglas Gregor } 802f545f67dSDouglas Gregor // Print the module map to this file. 803f545f67dSDouglas Gregor llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); 804f545f67dSDouglas Gregor Module->print(OS); 805514b636aSDouglas Gregor FrontendOpts.Inputs.push_back( 80632fbe312SDouglas Gregor FrontendInputFile(TempModuleMapFileName.str().str(), IK)); 807f545f67dSDouglas Gregor } 808f545f67dSDouglas Gregor 809f545f67dSDouglas Gregor // Don't free the remapped file buffers; they are owned by our caller. 810f545f67dSDouglas Gregor PPOpts.RetainRemappedFileBuffers = true; 811514b636aSDouglas Gregor 812514b636aSDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 813514b636aSDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() == 814514b636aSDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!"); 815514b636aSDouglas Gregor 816514b636aSDouglas Gregor // Construct a compiler instance that will be used to actually create the 817514b636aSDouglas Gregor // module. 818514b636aSDouglas Gregor CompilerInstance Instance; 819514b636aSDouglas Gregor Instance.setInvocation(&*Invocation); 820514b636aSDouglas Gregor Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, 821514b636aSDouglas Gregor &ImportingInstance.getDiagnosticClient(), 822514b636aSDouglas Gregor /*ShouldOwnClient=*/true, 823514b636aSDouglas Gregor /*ShouldCloneClient=*/true); 824514b636aSDouglas Gregor 825514b636aSDouglas Gregor // Construct a module-generating action. 826514b636aSDouglas Gregor GenerateModuleAction CreateModuleAction; 827514b636aSDouglas Gregor 828514b636aSDouglas Gregor // Execute the action to actually build the module in-place. Use a separate 829514b636aSDouglas Gregor // thread so that we get a stack large enough. 830514b636aSDouglas Gregor const unsigned ThreadStackSize = 8 << 20; 831514b636aSDouglas Gregor llvm::CrashRecoveryContext CRC; 832514b636aSDouglas Gregor CompileModuleMapData Data = { Instance, CreateModuleAction }; 833514b636aSDouglas Gregor CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); 834514b636aSDouglas Gregor 835f545f67dSDouglas Gregor // Delete the temporary module map file. 836f545f67dSDouglas Gregor // FIXME: Even though we're executing under crash protection, it would still 837f545f67dSDouglas Gregor // be nice to do this with RemoveFileOnSignal when we can. However, that 838f545f67dSDouglas Gregor // doesn't make sense for all clients, so clean this up manually. 839f545f67dSDouglas Gregor if (!TempModuleMapFileName.empty()) 840f545f67dSDouglas Gregor llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); 841faeb1d46SDouglas Gregor } 842faeb1d46SDouglas Gregor 843de3ef502SDouglas Gregor Module *CompilerInstance::loadModule(SourceLocation ImportLoc, 844ff2be53fSDouglas Gregor ModuleIdPath Path, 845bcfc7d02SDouglas Gregor Module::NameVisibilityKind Visibility, 846bcfc7d02SDouglas Gregor bool IsInclusionDirective) { 8471805b8a4SDouglas Gregor // If we've already handled this import, just return the cached result. 8481805b8a4SDouglas Gregor // This one-element cache is important to eliminate redundant diagnostics 8491805b8a4SDouglas Gregor // when both the preprocessor and parser see the same import declaration. 850ff2be53fSDouglas Gregor if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { 851ff2be53fSDouglas Gregor // Make the named module visible. 852ff2be53fSDouglas Gregor if (LastModuleImportResult) 853ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility); 85469021974SDouglas Gregor return LastModuleImportResult; 855ff2be53fSDouglas Gregor } 8561805b8a4SDouglas Gregor 85708142534SDouglas Gregor // Determine what file we're searching from. 85808142534SDouglas Gregor SourceManager &SourceMgr = getSourceManager(); 85908142534SDouglas Gregor SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc); 86008142534SDouglas Gregor const FileEntry *CurFile 86108142534SDouglas Gregor = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc)); 86208142534SDouglas Gregor if (!CurFile) 86308142534SDouglas Gregor CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 86408142534SDouglas Gregor 86571944203SDouglas Gregor StringRef ModuleName = Path[0].first->getName(); 86671944203SDouglas Gregor SourceLocation ModuleNameLoc = Path[0].second; 86771944203SDouglas Gregor 868de3ef502SDouglas Gregor clang::Module *Module = 0; 8695196bc6bSDouglas Gregor 8705196bc6bSDouglas Gregor // If we don't already have information on this module, load the module now. 871de3ef502SDouglas Gregor llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known 87269021974SDouglas Gregor = KnownModules.find(Path[0].first); 8732537a364SDouglas Gregor if (Known != KnownModules.end()) { 8742537a364SDouglas Gregor // Retrieve the cached top-level module. 8752537a364SDouglas Gregor Module = Known->second; 8762537a364SDouglas Gregor } else if (ModuleName == getLangOpts().CurrentModule) { 8772537a364SDouglas Gregor // This is the module we're building. 8782537a364SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName); 8792537a364SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 8802537a364SDouglas Gregor } else { 8815196bc6bSDouglas Gregor // Search for a module with the given name. 882279a6c37SDouglas Gregor Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); 8831735f4e7SDouglas Gregor std::string ModuleFileName; 884279a6c37SDouglas Gregor if (Module) 885279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); 886279a6c37SDouglas Gregor else 887279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName); 888faeb1d46SDouglas Gregor 889279a6c37SDouglas Gregor if (ModuleFileName.empty()) { 890279a6c37SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) 891279a6c37SDouglas Gregor << ModuleName 892279a6c37SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 893279a6c37SDouglas Gregor LastModuleImportLoc = ImportLoc; 894279a6c37SDouglas Gregor LastModuleImportResult = 0; 895279a6c37SDouglas Gregor return 0; 896279a6c37SDouglas Gregor } 897279a6c37SDouglas Gregor 898279a6c37SDouglas Gregor const FileEntry *ModuleFile 899279a6c37SDouglas Gregor = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false, 900279a6c37SDouglas Gregor /*CacheFailure=*/false); 901faeb1d46SDouglas Gregor bool BuildingModule = false; 9026dc57927SDouglas Gregor if (!ModuleFile && Module) { 9036dc57927SDouglas Gregor // The module is not cached, but we have a module map from which we can 9046dc57927SDouglas Gregor // build the module. 905dff0e892SDouglas Gregor 906dff0e892SDouglas Gregor // Check whether there is a cycle in the module graph. 907dff0e892SDouglas Gregor SmallVectorImpl<std::string> &ModuleBuildPath 908dff0e892SDouglas Gregor = getPreprocessorOpts().ModuleBuildPath; 909dff0e892SDouglas Gregor SmallVectorImpl<std::string>::iterator Pos 91071944203SDouglas Gregor = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), ModuleName); 911dff0e892SDouglas Gregor if (Pos != ModuleBuildPath.end()) { 9122c1dd271SDylan Noblesmith SmallString<256> CyclePath; 913dff0e892SDouglas Gregor for (; Pos != ModuleBuildPath.end(); ++Pos) { 914dff0e892SDouglas Gregor CyclePath += *Pos; 915dff0e892SDouglas Gregor CyclePath += " -> "; 916dff0e892SDouglas Gregor } 91771944203SDouglas Gregor CyclePath += ModuleName; 918dff0e892SDouglas Gregor 919dff0e892SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) 92071944203SDouglas Gregor << ModuleName << CyclePath; 921dff0e892SDouglas Gregor return 0; 922dff0e892SDouglas Gregor } 923dff0e892SDouglas Gregor 92444e688d4SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build) 92571944203SDouglas Gregor << ModuleName; 926faeb1d46SDouglas Gregor BuildingModule = true; 9276dc57927SDouglas Gregor compileModule(*this, Module, ModuleFileName); 928ca295457SDouglas Gregor ModuleFile = FileMgr->getFile(ModuleFileName); 929faeb1d46SDouglas Gregor } 930faeb1d46SDouglas Gregor 93108142534SDouglas Gregor if (!ModuleFile) { 932faeb1d46SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, 933faeb1d46SDouglas Gregor BuildingModule? diag::err_module_not_built 934faeb1d46SDouglas Gregor : diag::err_module_not_found) 93571944203SDouglas Gregor << ModuleName 93608142534SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 93708142534SDouglas Gregor return 0; 93808142534SDouglas Gregor } 93908142534SDouglas Gregor 94008142534SDouglas Gregor // If we don't already have an ASTReader, create one now. 94108142534SDouglas Gregor if (!ModuleManager) { 94221931efcSDouglas Gregor if (!hasASTContext()) 94321931efcSDouglas Gregor createASTContext(); 94421931efcSDouglas Gregor 94508142534SDouglas Gregor std::string Sysroot = getHeaderSearchOpts().Sysroot; 94608142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 9478835e03cSDouglas Gregor ModuleManager = new ASTReader(getPreprocessor(), *Context, 94808142534SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 94908142534SDouglas Gregor PPOpts.DisablePCHValidation, 95008142534SDouglas Gregor PPOpts.DisableStatCache); 95121931efcSDouglas Gregor if (hasASTConsumer()) { 95208142534SDouglas Gregor ModuleManager->setDeserializationListener( 95308142534SDouglas Gregor getASTConsumer().GetASTDeserializationListener()); 95408142534SDouglas Gregor getASTContext().setASTMutationListener( 95508142534SDouglas Gregor getASTConsumer().GetASTMutationListener()); 95621931efcSDouglas Gregor } 957e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 95808142534SDouglas Gregor Source.reset(ModuleManager); 95908142534SDouglas Gregor getASTContext().setExternalSource(Source); 96021931efcSDouglas Gregor if (hasSema()) 96108142534SDouglas Gregor ModuleManager->InitializeSema(getSema()); 9626137d32cSDouglas Gregor if (hasASTConsumer()) 9636137d32cSDouglas Gregor ModuleManager->StartTranslationUnit(&getASTConsumer()); 96408142534SDouglas Gregor } 96508142534SDouglas Gregor 96608142534SDouglas Gregor // Try to load the module we found. 96708142534SDouglas Gregor switch (ModuleManager->ReadAST(ModuleFile->getName(), 96808142534SDouglas Gregor serialization::MK_Module)) { 96908142534SDouglas Gregor case ASTReader::Success: 97008142534SDouglas Gregor break; 97108142534SDouglas Gregor 97208142534SDouglas Gregor case ASTReader::IgnorePCH: 97308142534SDouglas Gregor // FIXME: The ASTReader will already have complained, but can we showhorn 97408142534SDouglas Gregor // that diagnostic information into a more useful form? 97569021974SDouglas Gregor KnownModules[Path[0].first] = 0; 97608142534SDouglas Gregor return 0; 97708142534SDouglas Gregor 97808142534SDouglas Gregor case ASTReader::Failure: 97969021974SDouglas Gregor // Already complained, but note now that we failed. 98069021974SDouglas Gregor KnownModules[Path[0].first] = 0; 98108142534SDouglas Gregor return 0; 98208142534SDouglas Gregor } 98308142534SDouglas Gregor 98469021974SDouglas Gregor if (!Module) { 98569021974SDouglas Gregor // If we loaded the module directly, without finding a module map first, 98669021974SDouglas Gregor // we'll have loaded the module's information from the module itself. 98769021974SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap() 98869021974SDouglas Gregor .findModule((Path[0].first->getName())); 9895196bc6bSDouglas Gregor } 9905196bc6bSDouglas Gregor 99169021974SDouglas Gregor // Cache the result of this top-level module lookup for later. 99269021974SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 99369021974SDouglas Gregor } 99469021974SDouglas Gregor 99569021974SDouglas Gregor // If we never found the module, fail. 99669021974SDouglas Gregor if (!Module) 99769021974SDouglas Gregor return 0; 99869021974SDouglas Gregor 9995196bc6bSDouglas Gregor // Verify that the rest of the module path actually corresponds to 10005196bc6bSDouglas Gregor // a submodule. 100169021974SDouglas Gregor if (Path.size() > 1) { 10025196bc6bSDouglas Gregor for (unsigned I = 1, N = Path.size(); I != N; ++I) { 10035196bc6bSDouglas Gregor StringRef Name = Path[I].first->getName(); 1004eb90e830SDouglas Gregor clang::Module *Sub = Module->findSubmodule(Name); 10055196bc6bSDouglas Gregor 1006eb90e830SDouglas Gregor if (!Sub) { 10075196bc6bSDouglas Gregor // Attempt to perform typo correction to find a module name that works. 10085196bc6bSDouglas Gregor llvm::SmallVector<StringRef, 2> Best; 10095196bc6bSDouglas Gregor unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)(); 10105196bc6bSDouglas Gregor 1011eb90e830SDouglas Gregor for (clang::Module::submodule_iterator J = Module->submodule_begin(), 1012eb90e830SDouglas Gregor JEnd = Module->submodule_end(); 1013eb44edadSMatt Beaumont-Gay J != JEnd; ++J) { 1014eb90e830SDouglas Gregor unsigned ED = Name.edit_distance((*J)->Name, 10155196bc6bSDouglas Gregor /*AllowReplacements=*/true, 10165196bc6bSDouglas Gregor BestEditDistance); 10175196bc6bSDouglas Gregor if (ED <= BestEditDistance) { 1018eb90e830SDouglas Gregor if (ED < BestEditDistance) { 10195196bc6bSDouglas Gregor Best.clear(); 1020eb90e830SDouglas Gregor BestEditDistance = ED; 1021eb90e830SDouglas Gregor } 1022eb90e830SDouglas Gregor 1023eb90e830SDouglas Gregor Best.push_back((*J)->Name); 10245196bc6bSDouglas Gregor } 10255196bc6bSDouglas Gregor } 10265196bc6bSDouglas Gregor 10275196bc6bSDouglas Gregor // If there was a clear winner, user it. 10285196bc6bSDouglas Gregor if (Best.size() == 1) { 10295196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, 10305196bc6bSDouglas Gregor diag::err_no_submodule_suggest) 103169021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() << Best[0] 10325196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second) 10335196bc6bSDouglas Gregor << FixItHint::CreateReplacement(SourceRange(Path[I].second), 10345196bc6bSDouglas Gregor Best[0]); 1035eb90e830SDouglas Gregor 1036eb90e830SDouglas Gregor Sub = Module->findSubmodule(Best[0]); 10375196bc6bSDouglas Gregor } 10385196bc6bSDouglas Gregor } 10395196bc6bSDouglas Gregor 1040eb90e830SDouglas Gregor if (!Sub) { 10415196bc6bSDouglas Gregor // No submodule by this name. Complain, and don't look for further 10425196bc6bSDouglas Gregor // submodules. 10435196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, diag::err_no_submodule) 104469021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() 10455196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second); 10465196bc6bSDouglas Gregor break; 10475196bc6bSDouglas Gregor } 10485196bc6bSDouglas Gregor 1049eb90e830SDouglas Gregor Module = Sub; 10505196bc6bSDouglas Gregor } 10515196bc6bSDouglas Gregor } 10525196bc6bSDouglas Gregor 10532537a364SDouglas Gregor // Make the named module visible, if it's not already part of the module 10542537a364SDouglas Gregor // we are parsing. 105598a52db8SDouglas Gregor if (ModuleName != getLangOpts().CurrentModule) { 105698a52db8SDouglas Gregor if (!Module->IsFromModuleFile) { 105798a52db8SDouglas Gregor // We have an umbrella header or directory that doesn't actually include 105898a52db8SDouglas Gregor // all of the headers within the directory it covers. Complain about 105998a52db8SDouglas Gregor // this missing submodule and recover by forgetting that we ever saw 106098a52db8SDouglas Gregor // this submodule. 106198a52db8SDouglas Gregor // FIXME: Should we detect this at module load time? It seems fairly 106298a52db8SDouglas Gregor // expensive (and rare). 106398a52db8SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule) 106498a52db8SDouglas Gregor << Module->getFullModuleName() 106598a52db8SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 106698a52db8SDouglas Gregor 106798a52db8SDouglas Gregor return 0; 106898a52db8SDouglas Gregor } 10691fb5c3a6SDouglas Gregor 10701fb5c3a6SDouglas Gregor // Check whether this module is available. 10711fb5c3a6SDouglas Gregor StringRef Feature; 107289929282SDouglas Gregor if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) { 10731fb5c3a6SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) 10741fb5c3a6SDouglas Gregor << Module->getFullModuleName() 10751fb5c3a6SDouglas Gregor << Feature 10761fb5c3a6SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 10771fb5c3a6SDouglas Gregor LastModuleImportLoc = ImportLoc; 10781fb5c3a6SDouglas Gregor LastModuleImportResult = 0; 10791fb5c3a6SDouglas Gregor return 0; 10801fb5c3a6SDouglas Gregor } 10811fb5c3a6SDouglas Gregor 1082ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(Module, Visibility); 108398a52db8SDouglas Gregor } 10845196bc6bSDouglas Gregor 1085bcfc7d02SDouglas Gregor // If this module import was due to an inclusion directive, create an 1086bcfc7d02SDouglas Gregor // implicit import declaration to capture it in the AST. 1087bcfc7d02SDouglas Gregor if (IsInclusionDirective && hasASTContext()) { 1088bcfc7d02SDouglas Gregor TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); 1089bcfc7d02SDouglas Gregor TU->addDecl(ImportDecl::CreateImplicit(getASTContext(), TU, 1090bcfc7d02SDouglas Gregor ImportLoc, Module, 1091bcfc7d02SDouglas Gregor Path.back().second)); 1092bcfc7d02SDouglas Gregor } 1093bcfc7d02SDouglas Gregor 10941805b8a4SDouglas Gregor LastModuleImportLoc = ImportLoc; 109569021974SDouglas Gregor LastModuleImportResult = Module; 109669021974SDouglas Gregor return Module; 109708142534SDouglas Gregor } 1098