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" 1156d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h" 12df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h" 13bcfc7d02SDouglas Gregor #include "clang/AST/Decl.h" 14636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h" 15546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h" 16546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h" 17636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h" 184f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h" 198b00dcb0SDavid Blaikie #include "clang/Frontend/ChainedDiagnosticConsumer.h" 204f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h" 21faeb1d46SDouglas Gregor #include "clang/Frontend/FrontendActions.h" 22f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h" 232083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h" 244610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h" 257d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h" 26aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h" 273a02247dSChandler Carruth #include "clang/Frontend/VerifyDiagnosticConsumer.h" 283a02247dSChandler Carruth #include "clang/Lex/HeaderSearch.h" 293a02247dSChandler Carruth #include "clang/Lex/PTHManager.h" 303a02247dSChandler Carruth #include "clang/Lex/Preprocessor.h" 31f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h" 323a02247dSChandler Carruth #include "clang/Sema/Sema.h" 333a02247dSChandler Carruth #include "clang/Serialization/ASTReader.h" 34171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h" 353a02247dSChandler Carruth #include "llvm/Config/config.h" 363a02247dSChandler Carruth #include "llvm/Support/CrashRecoveryContext.h" 373a02247dSChandler Carruth #include "llvm/Support/FileSystem.h" 388aaf4995SMichael J. Spencer #include "llvm/Support/Host.h" 39e212489fSDouglas Gregor #include "llvm/Support/LockFileManager.h" 403a02247dSChandler Carruth #include "llvm/Support/MemoryBuffer.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" 443a02247dSChandler Carruth #include "llvm/Support/Timer.h" 453a02247dSChandler Carruth #include "llvm/Support/raw_ostream.h" 46f25faaafSMichael J. Spencer #include "llvm/Support/system_error.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() { 553c717b45SBenjamin Kramer assert(OutputFiles.empty() && "Still output files in flight?"); 56e922d9bdSDaniel Dunbar } 57e922d9bdSDaniel Dunbar 5868242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) { 595e14d39aSTed Kremenek Invocation = Value; 6068242254SDaniel Dunbar } 6168242254SDaniel Dunbar 629c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) { 637f95d26eSDouglas Gregor Diagnostics = Value; 64e01dc86dSDaniel Dunbar } 65e01dc86dSDaniel Dunbar 66e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) { 675e14d39aSTed Kremenek Target = Value; 68e01dc86dSDaniel Dunbar } 69e01dc86dSDaniel Dunbar 70e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) { 715e14d39aSTed Kremenek FileMgr = Value; 72e01dc86dSDaniel Dunbar } 73e01dc86dSDaniel Dunbar 74e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) { 755e14d39aSTed Kremenek SourceMgr = Value; 76e01dc86dSDaniel Dunbar } 77e01dc86dSDaniel Dunbar 785e14d39aSTed Kremenek void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; } 79e01dc86dSDaniel Dunbar 805e14d39aSTed Kremenek void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; } 81e01dc86dSDaniel Dunbar 820e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) { 830e93f017SDouglas Gregor TheSema.reset(S); 840e93f017SDouglas Gregor } 850e93f017SDouglas Gregor 8656d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 8756d9c293SDaniel Dunbar Consumer.reset(Value); 8856d9c293SDaniel Dunbar } 8956d9c293SDaniel Dunbar 90e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 91e01dc86dSDaniel Dunbar CompletionConsumer.reset(Value); 92e01dc86dSDaniel Dunbar } 93e01dc86dSDaniel Dunbar 947d75afc5SDaniel Dunbar // Diagnostics 95811db4eaSDouglas Gregor static void SetUpBuildDumpLog(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( 100811db4eaSDouglas Gregor 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) 103811db4eaSDouglas Gregor << 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 118811db4eaSDouglas Gregor static void SetUpDiagnosticLog(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(); 124811db4eaSDouglas Gregor if (DiagOpts->DiagnosticLogFile != "-") { 1252083c32fSDaniel Dunbar // Create the output stream. 1262083c32fSDaniel Dunbar llvm::raw_fd_ostream *FileOS( 127811db4eaSDouglas Gregor 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) 131811db4eaSDouglas Gregor << 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 148811db4eaSDouglas Gregor static void SetupSerializedDiagnostics(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) { 174811db4eaSDouglas Gregor Diagnostics = createDiagnostics(&getDiagnosticOpts(), Argc, Argv, Client, 175d0e9e3a6SDouglas Gregor ShouldOwnClient, ShouldCloneClient, 176d0e9e3a6SDouglas Gregor &getCodeGenOpts()); 1777d75afc5SDaniel Dunbar } 1787d75afc5SDaniel Dunbar 179c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine> 180811db4eaSDouglas Gregor CompilerInstance::createDiagnostics(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> 188811db4eaSDouglas Gregor Diags(new DiagnosticsEngine(DiagID, Opts)); 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. 201811db4eaSDouglas Gregor if (Opts->VerifyDiagnostics) 20269609dceSDavid Blaikie Diags->setClient(new VerifyDiagnosticConsumer(*Diags)); 2037d75afc5SDaniel Dunbar 2042083c32fSDaniel Dunbar // Chain in -diagnostic-log-file dumper, if requested. 205811db4eaSDouglas Gregor if (!Opts->DiagnosticLogFile.empty()) 2067b83306dSDaniel Dunbar SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags); 2072083c32fSDaniel Dunbar 208811db4eaSDouglas Gregor if (!Opts->DumpBuildInformation.empty()) 2094a94ba56SKovarththanan Rajaratnam SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); 2107d75afc5SDaniel Dunbar 211811db4eaSDouglas Gregor if (!Opts->DiagnosticSerializationFile.empty()) 2124610ea2bSTed Kremenek SetupSerializedDiagnostics(Opts, *Diags, 213811db4eaSDouglas Gregor Opts->DiagnosticSerializationFile); 2144610ea2bSTed Kremenek 2157d75afc5SDaniel Dunbar // Configure our handling of diagnostics. 216811db4eaSDouglas Gregor 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. 244b85b9ccbSDouglas Gregor HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(), 245b85b9ccbSDouglas Gregor getFileManager(), 2461fb5c3a6SDouglas Gregor getDiagnostics(), 24789929282SDouglas Gregor getLangOpts(), 24889929282SDouglas Gregor &getTarget()); 2491452ff15SDouglas Gregor PP = new Preprocessor(&getPreprocessorOpts(), 2501452ff15SDouglas Gregor getDiagnostics(), getLangOpts(), &getTarget(), 25108142534SDouglas Gregor getSourceManager(), *HeaderInfo, *this, PTHMgr, 252aaa148fdSDaniel Dunbar /*OwnsHeaderSearch=*/true); 253aaa148fdSDaniel Dunbar 254aaa148fdSDaniel Dunbar // Note that this is different then passing PTHMgr to Preprocessor's ctor. 255aaa148fdSDaniel Dunbar // That argument is used as the IdentifierInfoLookup argument to 256aaa148fdSDaniel Dunbar // IdentifierTable's ctor. 257aaa148fdSDaniel Dunbar if (PTHMgr) { 25808142534SDouglas Gregor PTHMgr->setPreprocessor(&*PP); 259aaa148fdSDaniel Dunbar PP->setPTHManager(PTHMgr); 260aaa148fdSDaniel Dunbar } 261aaa148fdSDaniel Dunbar 2627f6d60dcSDouglas Gregor if (PPOpts.DetailedRecord) 263f3d587eaSArgyrios Kyrtzidis PP->createPreprocessingRecord(); 2647f6d60dcSDouglas Gregor 26508142534SDouglas Gregor InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts()); 266aaa148fdSDaniel Dunbar 2671735f4e7SDouglas Gregor // Set up the module path, including the hash for the 2681735f4e7SDouglas Gregor // module-creation options. 2692c1dd271SDylan Noblesmith SmallString<256> SpecificModuleCache( 2701735f4e7SDouglas Gregor getHeaderSearchOpts().ModuleCachePath); 2711735f4e7SDouglas Gregor if (!getHeaderSearchOpts().DisableModuleHash) 2721735f4e7SDouglas Gregor llvm::sys::path::append(SpecificModuleCache, 2731735f4e7SDouglas Gregor getInvocation().getModuleHash()); 2742537a364SDouglas Gregor PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); 2751735f4e7SDouglas Gregor 276aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested. 27708142534SDouglas Gregor const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); 278aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty()) 279aaa148fdSDaniel Dunbar AttachDependencyFileGen(*PP, DepOpts); 2802e129659SDouglas Gregor if (!DepOpts.DOTOutputFile.empty()) 2812e129659SDouglas Gregor AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, 28283d46be3SDouglas Gregor getHeaderSearchOpts().Sysroot); 28383d46be3SDouglas Gregor 284aaa148fdSDaniel Dunbar 28527734fdbSDaniel Dunbar // Handle generating header include information, if requested. 28627734fdbSDaniel Dunbar if (DepOpts.ShowHeaderIncludes) 28727734fdbSDaniel Dunbar AttachHeaderIncludeGen(*PP); 2881af1d275SDaniel Dunbar if (!DepOpts.HeaderIncludeOutputFile.empty()) { 2890e62c1ccSChris Lattner StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; 2901af1d275SDaniel Dunbar if (OutputPath == "-") 2911af1d275SDaniel Dunbar OutputPath = ""; 292fe908a80SDaniel Dunbar AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, 293fe908a80SDaniel Dunbar /*ShowDepth=*/false); 2941af1d275SDaniel Dunbar } 295aaa148fdSDaniel Dunbar } 296df3e30c4SDaniel Dunbar 297df3e30c4SDaniel Dunbar // ASTContext 298df3e30c4SDaniel Dunbar 299df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() { 300df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor(); 3015e14d39aSTed Kremenek Context = new ASTContext(getLangOpts(), PP.getSourceManager(), 302e8bbc121SDouglas Gregor &getTarget(), PP.getIdentifierTable(), 303df3e30c4SDaniel Dunbar PP.getSelectorTable(), PP.getBuiltinInfo(), 3045e14d39aSTed Kremenek /*size_reserve=*/ 0); 305df3e30c4SDaniel Dunbar } 306599313efSDaniel Dunbar 307599313efSDaniel Dunbar // ExternalASTSource 308599313efSDaniel Dunbar 3090e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path, 31007a89a83SSebastian Redl bool DisablePCHValidation, 3114a280ff4SArgyrios Kyrtzidis bool AllowPCHWithCompilerErrors, 31207a89a83SSebastian Redl void *DeserializationListener){ 313e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 314009e7f20SSebastian Redl bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; 315599313efSDaniel Dunbar Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 316ce3a8293SDouglas Gregor DisablePCHValidation, 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, 3294a280ff4SArgyrios Kyrtzidis bool AllowPCHWithCompilerErrors, 330599313efSDaniel Dunbar Preprocessor &PP, 33107a89a83SSebastian Redl ASTContext &Context, 332009e7f20SSebastian Redl void *DeserializationListener, 333009e7f20SSebastian Redl bool Preamble) { 334e2778999SDylan Noblesmith OwningPtr<ASTReader> Reader; 3358835e03cSDouglas Gregor Reader.reset(new ASTReader(PP, Context, 336c567ba26SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 337d7c16b25SArgyrios Kyrtzidis DisablePCHValidation, 3384a280ff4SArgyrios Kyrtzidis AllowPCHWithCompilerErrors)); 339599313efSDaniel Dunbar 34007a89a83SSebastian Redl Reader->setDeserializationListener( 3413e31c724SSebastian Redl static_cast<ASTDeserializationListener *>(DeserializationListener)); 342009e7f20SSebastian Redl switch (Reader->ReadAST(Path, 343a6895d8aSDouglas Gregor Preamble ? serialization::MK_Preamble 3444b29c16eSDouglas Gregor : serialization::MK_PCH, 3452ec29367SArgyrios Kyrtzidis SourceLocation(), 3464b29c16eSDouglas Gregor ASTReader::ARR_None)) { 3472c499f65SSebastian Redl case ASTReader::Success: 348599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the 349599313efSDaniel Dunbar // predefines buffer will be empty. 350599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines()); 351599313efSDaniel Dunbar return Reader.take(); 352599313efSDaniel Dunbar 3532c499f65SSebastian Redl case ASTReader::Failure: 354599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file. 355599313efSDaniel Dunbar break; 356599313efSDaniel Dunbar 357c9ad5fb6SDouglas Gregor case ASTReader::OutOfDate: 358c9ad5fb6SDouglas Gregor case ASTReader::VersionMismatch: 359c9ad5fb6SDouglas Gregor case ASTReader::ConfigurationMismatch: 360c9ad5fb6SDouglas Gregor case ASTReader::HadErrors: 361599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error. 362599313efSDaniel Dunbar break; 363599313efSDaniel Dunbar } 364599313efSDaniel Dunbar 365599313efSDaniel Dunbar return 0; 366599313efSDaniel Dunbar } 367f7093b5aSDaniel Dunbar 368f7093b5aSDaniel Dunbar // Code Completion 369f7093b5aSDaniel Dunbar 3708e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP, 3718e984da8SDouglas Gregor const std::string &Filename, 3728e984da8SDouglas Gregor unsigned Line, 3738e984da8SDouglas Gregor unsigned Column) { 3748e984da8SDouglas Gregor // Tell the source manager to chop off the given file at a specific 3758e984da8SDouglas Gregor // line and column. 3765159f616SChris Lattner const FileEntry *Entry = PP.getFileManager().getFile(Filename); 3778e984da8SDouglas Gregor if (!Entry) { 3788e984da8SDouglas Gregor PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 3798e984da8SDouglas Gregor << Filename; 3808e984da8SDouglas Gregor return true; 3818e984da8SDouglas Gregor } 3828e984da8SDouglas Gregor 3838e984da8SDouglas Gregor // Truncate the named file at the given line/column. 3848e984da8SDouglas Gregor PP.SetCodeCompletionPoint(Entry, Line, Column); 3858e984da8SDouglas Gregor return false; 3868e984da8SDouglas Gregor } 3878e984da8SDouglas Gregor 388f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() { 389f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 3908e984da8SDouglas Gregor if (!CompletionConsumer) { 3912fca3c2cSErik Verbruggen setCodeCompletionConsumer( 392f7093b5aSDaniel Dunbar createCodeCompletionConsumer(getPreprocessor(), 393f7093b5aSDaniel Dunbar Loc.FileName, Loc.Line, Loc.Column, 3943292d06aSDmitri Gribenko getFrontendOpts().CodeCompleteOpts, 395f7093b5aSDaniel Dunbar llvm::outs())); 39600a0cf70SDouglas Gregor if (!CompletionConsumer) 39700a0cf70SDouglas Gregor return; 3988e984da8SDouglas Gregor } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName, 3998e984da8SDouglas Gregor Loc.Line, Loc.Column)) { 4002fca3c2cSErik Verbruggen setCodeCompletionConsumer(0); 4018e984da8SDouglas Gregor return; 4028e984da8SDouglas Gregor } 403f09935f1SDouglas Gregor 404f09935f1SDouglas Gregor if (CompletionConsumer->isOutputBinary() && 405f09935f1SDouglas Gregor llvm::sys::Program::ChangeStdoutToBinary()) { 406f09935f1SDouglas Gregor getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 4072fca3c2cSErik Verbruggen setCodeCompletionConsumer(0); 408f09935f1SDouglas Gregor } 409f7093b5aSDaniel Dunbar } 410f7093b5aSDaniel Dunbar 4115505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() { 4125505dff8SKovarththanan Rajaratnam FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 4135505dff8SKovarththanan Rajaratnam } 4145505dff8SKovarththanan Rajaratnam 415f7093b5aSDaniel Dunbar CodeCompleteConsumer * 416f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 417f7093b5aSDaniel Dunbar const std::string &Filename, 418f7093b5aSDaniel Dunbar unsigned Line, 419f7093b5aSDaniel Dunbar unsigned Column, 4203292d06aSDmitri Gribenko const CodeCompleteOptions &Opts, 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. 4263292d06aSDmitri Gribenko return new PrintingCodeCompleteConsumer(Opts, OS); 427f7093b5aSDaniel Dunbar } 428566eeb2dSDaniel Dunbar 42969f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind, 4300e93f017SDouglas Gregor CodeCompleteConsumer *CompletionConsumer) { 4310e93f017SDouglas Gregor TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(), 43269f74f80SDouglas Gregor TUKind, CompletionConsumer)); 4330e93f017SDouglas Gregor } 4340e93f017SDouglas Gregor 435566eeb2dSDaniel Dunbar // Output Files 436566eeb2dSDaniel Dunbar 437d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) { 438d0599970SArgyrios Kyrtzidis assert(OutFile.OS && "Attempt to add empty stream to output list!"); 439d0599970SArgyrios Kyrtzidis OutputFiles.push_back(OutFile); 440566eeb2dSDaniel Dunbar } 441566eeb2dSDaniel Dunbar 4421c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) { 443d0599970SArgyrios Kyrtzidis for (std::list<OutputFile>::iterator 444566eeb2dSDaniel Dunbar it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 445d0599970SArgyrios Kyrtzidis delete it->OS; 446d0599970SArgyrios Kyrtzidis if (!it->TempFilename.empty()) { 447b5c356a4SAnders Carlsson if (EraseFiles) { 448b5c356a4SAnders Carlsson bool existed; 449b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 450b5c356a4SAnders Carlsson } else { 4512c1dd271SDylan Noblesmith SmallString<128> NewOutFile(it->Filename); 452b5c356a4SAnders Carlsson 45371731d6bSArgyrios Kyrtzidis // If '-working-directory' was passed, the output filename should be 45471731d6bSArgyrios Kyrtzidis // relative to that. 4559ba8fb1eSAnders Carlsson FileMgr->FixupRelativePath(NewOutFile); 456b5c356a4SAnders Carlsson if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, 457b5c356a4SAnders Carlsson NewOutFile.str())) { 4583ef9c447SManuel Klimek getDiagnostics().Report(diag::err_unable_to_rename_temp) 459b5c356a4SAnders Carlsson << it->TempFilename << it->Filename << ec.message(); 460b5c356a4SAnders Carlsson 461b5c356a4SAnders Carlsson bool existed; 462b5c356a4SAnders Carlsson llvm::sys::fs::remove(it->TempFilename, existed); 463d0599970SArgyrios Kyrtzidis } 464d0599970SArgyrios Kyrtzidis } 465d0599970SArgyrios Kyrtzidis } else if (!it->Filename.empty() && EraseFiles) 466d0599970SArgyrios Kyrtzidis llvm::sys::Path(it->Filename).eraseFromDisk(); 467d0599970SArgyrios Kyrtzidis 468566eeb2dSDaniel Dunbar } 469566eeb2dSDaniel Dunbar OutputFiles.clear(); 470566eeb2dSDaniel Dunbar } 471566eeb2dSDaniel Dunbar 472420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 473420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary, 4740e62c1ccSChris Lattner StringRef InFile, 4750e62c1ccSChris Lattner StringRef Extension) { 476420b0f1bSDaniel Dunbar return createOutputFile(getFrontendOpts().OutputFile, Binary, 477ae77b3dfSDaniel Dunbar /*RemoveFileOnSignal=*/true, InFile, Extension, 478ae77b3dfSDaniel Dunbar /*UseTemporary=*/true); 479420b0f1bSDaniel Dunbar } 480420b0f1bSDaniel Dunbar 481420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 4820e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 483e326f9bbSDaniel Dunbar bool Binary, bool RemoveFileOnSignal, 4840e62c1ccSChris Lattner StringRef InFile, 48508a2bfd2SArgyrios Kyrtzidis StringRef Extension, 486b9c62c07SDaniel Dunbar bool UseTemporary, 487b9c62c07SDaniel Dunbar bool CreateMissingDirectories) { 488d0599970SArgyrios Kyrtzidis std::string Error, OutputPathName, TempPathName; 489420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 490e326f9bbSDaniel Dunbar RemoveFileOnSignal, 491420b0f1bSDaniel Dunbar InFile, Extension, 49208a2bfd2SArgyrios Kyrtzidis UseTemporary, 493b9c62c07SDaniel Dunbar CreateMissingDirectories, 494d0599970SArgyrios Kyrtzidis &OutputPathName, 495d0599970SArgyrios Kyrtzidis &TempPathName); 496420b0f1bSDaniel Dunbar if (!OS) { 4977554699aSDaniel Dunbar getDiagnostics().Report(diag::err_fe_unable_to_open_output) 4987554699aSDaniel Dunbar << OutputPath << Error; 4997554699aSDaniel Dunbar return 0; 500420b0f1bSDaniel Dunbar } 501420b0f1bSDaniel Dunbar 502420b0f1bSDaniel Dunbar // Add the output file -- but don't try to remove "-", since this means we are 503420b0f1bSDaniel Dunbar // using stdin. 504d0599970SArgyrios Kyrtzidis addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", 505d0599970SArgyrios Kyrtzidis TempPathName, OS)); 506420b0f1bSDaniel Dunbar 507420b0f1bSDaniel Dunbar return OS; 508420b0f1bSDaniel Dunbar } 509420b0f1bSDaniel Dunbar 510420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 5110e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath, 512420b0f1bSDaniel Dunbar std::string &Error, 513420b0f1bSDaniel Dunbar bool Binary, 514e326f9bbSDaniel Dunbar bool RemoveFileOnSignal, 5150e62c1ccSChris Lattner StringRef InFile, 5160e62c1ccSChris Lattner StringRef Extension, 51708a2bfd2SArgyrios Kyrtzidis bool UseTemporary, 518b9c62c07SDaniel Dunbar bool CreateMissingDirectories, 519d0599970SArgyrios Kyrtzidis std::string *ResultPathName, 520d0599970SArgyrios Kyrtzidis std::string *TempPathName) { 521b9c62c07SDaniel Dunbar assert((!CreateMissingDirectories || UseTemporary) && 522b9c62c07SDaniel Dunbar "CreateMissingDirectories is only allowed when using temporary files"); 523b9c62c07SDaniel Dunbar 524d0599970SArgyrios Kyrtzidis std::string OutFile, TempFile; 525420b0f1bSDaniel Dunbar if (!OutputPath.empty()) { 526420b0f1bSDaniel Dunbar OutFile = OutputPath; 527420b0f1bSDaniel Dunbar } else if (InFile == "-") { 528420b0f1bSDaniel Dunbar OutFile = "-"; 529420b0f1bSDaniel Dunbar } else if (!Extension.empty()) { 530420b0f1bSDaniel Dunbar llvm::sys::Path Path(InFile); 531420b0f1bSDaniel Dunbar Path.eraseSuffix(); 532420b0f1bSDaniel Dunbar Path.appendSuffix(Extension); 533420b0f1bSDaniel Dunbar OutFile = Path.str(); 534420b0f1bSDaniel Dunbar } else { 535420b0f1bSDaniel Dunbar OutFile = "-"; 536420b0f1bSDaniel Dunbar } 537420b0f1bSDaniel Dunbar 538e2778999SDylan Noblesmith OwningPtr<llvm::raw_fd_ostream> OS; 53908a2bfd2SArgyrios Kyrtzidis std::string OSFile; 54008a2bfd2SArgyrios Kyrtzidis 54108a2bfd2SArgyrios Kyrtzidis if (UseTemporary && OutFile != "-") { 542b9c62c07SDaniel Dunbar // Only create the temporary if the parent directory exists (or create 543b9c62c07SDaniel Dunbar // missing directories is true) and we can actually write to OutPath, 544b9c62c07SDaniel Dunbar // otherwise we want to fail early. 545b9c62c07SDaniel Dunbar SmallString<256> AbsPath(OutputPath); 546b9c62c07SDaniel Dunbar llvm::sys::fs::make_absolute(AbsPath); 547b9c62c07SDaniel Dunbar llvm::sys::Path OutPath(AbsPath); 548b9c62c07SDaniel Dunbar bool ParentExists = false; 549b9c62c07SDaniel Dunbar if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()), 550b9c62c07SDaniel Dunbar ParentExists)) 551b9c62c07SDaniel Dunbar ParentExists = false; 552f6efe58dSMichael J. Spencer bool Exists; 553b9c62c07SDaniel Dunbar if ((CreateMissingDirectories || ParentExists) && 554b9c62c07SDaniel Dunbar ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) || 555b9c62c07SDaniel Dunbar (OutPath.isRegularFile() && OutPath.canWrite()))) { 556d0599970SArgyrios Kyrtzidis // Create a temporary file. 5572c1dd271SDylan Noblesmith SmallString<128> TempPath; 55808a2bfd2SArgyrios Kyrtzidis TempPath = OutFile; 55908a2bfd2SArgyrios Kyrtzidis TempPath += "-%%%%%%%%"; 56008a2bfd2SArgyrios Kyrtzidis int fd; 56108a2bfd2SArgyrios Kyrtzidis if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, 562f6a6346dSEric Christopher /*makeAbsolute=*/false, 0664) 563f6a6346dSEric Christopher == 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 5931b3240b0SArgyrios Kyrtzidis bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){ 5941b3240b0SArgyrios Kyrtzidis return InitializeSourceManager(Input, getDiagnostics(), 595a686e1b0SDouglas Gregor getFileManager(), getSourceManager(), 596a686e1b0SDouglas Gregor getFrontendOpts()); 597409e890fSDaniel Dunbar } 598409e890fSDaniel Dunbar 5991b3240b0SArgyrios Kyrtzidis bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, 6009c902b55SDavid Blaikie DiagnosticsEngine &Diags, 601409e890fSDaniel Dunbar FileManager &FileMgr, 602409e890fSDaniel Dunbar SourceManager &SourceMgr, 603409e890fSDaniel Dunbar const FrontendOptions &Opts) { 6041b3240b0SArgyrios Kyrtzidis SrcMgr::CharacteristicKind 605873c8583SArgyrios Kyrtzidis Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User; 6061b3240b0SArgyrios Kyrtzidis 6076566e23eSArgyrios Kyrtzidis if (Input.isBuffer()) { 6086566e23eSArgyrios Kyrtzidis SourceMgr.createMainFileIDForMemBuffer(Input.getBuffer(), Kind); 6096566e23eSArgyrios Kyrtzidis assert(!SourceMgr.getMainFileID().isInvalid() && 6106566e23eSArgyrios Kyrtzidis "Couldn't establish MainFileID!"); 6116566e23eSArgyrios Kyrtzidis return true; 6126566e23eSArgyrios Kyrtzidis } 6136566e23eSArgyrios Kyrtzidis 6146566e23eSArgyrios Kyrtzidis StringRef InputFile = Input.getFile(); 6156566e23eSArgyrios Kyrtzidis 6167c06d866SArgyrios Kyrtzidis // Figure out where to get and map in the main file. 6177c06d866SArgyrios Kyrtzidis if (InputFile != "-") { 6185159f616SChris Lattner const FileEntry *File = FileMgr.getFile(InputFile); 61952765215SDan Gohman if (!File) { 620409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile; 621409e890fSDaniel Dunbar return false; 622409e890fSDaniel Dunbar } 623e2951f48SDaniel Dunbar 624e2951f48SDaniel Dunbar // The natural SourceManager infrastructure can't currently handle named 625e2951f48SDaniel Dunbar // pipes, but we would at least like to accept them for the main 626e2951f48SDaniel Dunbar // file. Detect them here, read them with the more generic MemoryBuffer 627e2951f48SDaniel Dunbar // function, and simply override their contents as we do for STDIN. 628e2951f48SDaniel Dunbar if (File->isNamedPipe()) { 629e2951f48SDaniel Dunbar OwningPtr<llvm::MemoryBuffer> MB; 630e2951f48SDaniel Dunbar if (llvm::error_code ec = llvm::MemoryBuffer::getFile(InputFile, MB)) { 631e2951f48SDaniel Dunbar Diags.Report(diag::err_cannot_open_file) << InputFile << ec.message(); 632e2951f48SDaniel Dunbar return false; 633e2951f48SDaniel Dunbar } 634db0745abSDaniel Dunbar 635db0745abSDaniel Dunbar // Create a new virtual file that will have the correct size. 636db0745abSDaniel Dunbar File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); 637e2951f48SDaniel Dunbar SourceMgr.overrideFileContents(File, MB.take()); 638e2951f48SDaniel Dunbar } 639db0745abSDaniel Dunbar 640db0745abSDaniel Dunbar SourceMgr.createMainFileID(File, Kind); 641409e890fSDaniel Dunbar } else { 642e2778999SDylan Noblesmith OwningPtr<llvm::MemoryBuffer> SB; 643d9da7a1fSMichael J. Spencer if (llvm::MemoryBuffer::getSTDIN(SB)) { 644f25faaafSMichael J. Spencer // FIXME: Give ec.message() in this diag. 645409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading_stdin); 646409e890fSDaniel Dunbar return false; 647409e890fSDaniel Dunbar } 6482f76cd75SDan Gohman const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), 6495159f616SChris Lattner SB->getBufferSize(), 0); 650a686e1b0SDouglas Gregor SourceMgr.createMainFileID(File, Kind); 651d9da7a1fSMichael J. Spencer SourceMgr.overrideFileContents(File, SB.take()); 652409e890fSDaniel Dunbar } 653409e890fSDaniel Dunbar 65452765215SDan Gohman assert(!SourceMgr.getMainFileID().isInvalid() && 65552765215SDan Gohman "Couldn't establish MainFileID!"); 656409e890fSDaniel Dunbar return true; 657409e890fSDaniel Dunbar } 6584f2bc55dSDaniel Dunbar 6594f2bc55dSDaniel Dunbar // High-Level Operations 6604f2bc55dSDaniel Dunbar 6614f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 6624f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 6634f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 6644f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 6654f2bc55dSDaniel Dunbar 6664f2bc55dSDaniel Dunbar // FIXME: Take this as an argument, once all the APIs we used have moved to 6674f2bc55dSDaniel Dunbar // taking it as an input instead of hard-coding llvm::errs. 6680e62c1ccSChris Lattner raw_ostream &OS = llvm::errs(); 6694f2bc55dSDaniel Dunbar 6704f2bc55dSDaniel Dunbar // Create the target instance. 671f8715de5SDouglas Gregor setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), &getTargetOpts())); 6724f2bc55dSDaniel Dunbar if (!hasTarget()) 6734f2bc55dSDaniel Dunbar return false; 6744f2bc55dSDaniel Dunbar 6754f2bc55dSDaniel Dunbar // Inform the target of the language options. 6764f2bc55dSDaniel Dunbar // 6774f2bc55dSDaniel Dunbar // FIXME: We shouldn't need to do this, the target should be immutable once 6784f2bc55dSDaniel Dunbar // created. This complexity should be lifted elsewhere. 6794f2bc55dSDaniel Dunbar getTarget().setForcedLangOptions(getLangOpts()); 6804f2bc55dSDaniel Dunbar 68129898f45SFariborz Jahanian // rewriter project will change target built-in bool type from its default. 68229898f45SFariborz Jahanian if (getFrontendOpts().ProgramAction == frontend::RewriteObjC) 68329898f45SFariborz Jahanian getTarget().noSignedCharForObjCBool(); 68429898f45SFariborz Jahanian 6854f2bc55dSDaniel Dunbar // Validate/process some options. 6864f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose) 6874f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING 6884f2bc55dSDaniel Dunbar << " based upon " << PACKAGE_STRING 6898188c8a1SSebastian Pop << " default target " << llvm::sys::getDefaultTargetTriple() << "\n"; 6904f2bc55dSDaniel Dunbar 6914f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowTimers) 6924f2bc55dSDaniel Dunbar createFrontendTimer(); 6934f2bc55dSDaniel Dunbar 694171b780cSDouglas Gregor if (getFrontendOpts().ShowStats) 695171b780cSDouglas Gregor llvm::EnableStatistics(); 696171b780cSDouglas Gregor 6974f2bc55dSDaniel Dunbar for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 6984f2bc55dSDaniel Dunbar // Reset the ID tables if we are reusing the SourceManager. 699aed46fcbSDaniel Dunbar if (hasSourceManager()) 7004f2bc55dSDaniel Dunbar getSourceManager().clearIDTables(); 7014f2bc55dSDaniel Dunbar 70232fbe312SDouglas Gregor if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) { 7034f2bc55dSDaniel Dunbar Act.Execute(); 7044f2bc55dSDaniel Dunbar Act.EndSourceFile(); 7054f2bc55dSDaniel Dunbar } 7064f2bc55dSDaniel Dunbar } 7074f2bc55dSDaniel Dunbar 7087910d7b7SArgyrios Kyrtzidis // Notify the diagnostic client that all files were processed. 7097910d7b7SArgyrios Kyrtzidis getDiagnostics().getClient()->finish(); 7107910d7b7SArgyrios Kyrtzidis 711198cb4dfSChris Lattner if (getDiagnosticOpts().ShowCarets) { 712c79346a5SArgyrios Kyrtzidis // We can have multiple diagnostics sharing one diagnostic client. 713c79346a5SArgyrios Kyrtzidis // Get the total number of warnings/errors from the client. 714c79346a5SArgyrios Kyrtzidis unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); 715c79346a5SArgyrios Kyrtzidis unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); 716198cb4dfSChris Lattner 717198cb4dfSChris Lattner if (NumWarnings) 718198cb4dfSChris Lattner OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); 719198cb4dfSChris Lattner if (NumWarnings && NumErrors) 720198cb4dfSChris Lattner OS << " and "; 721198cb4dfSChris Lattner if (NumErrors) 722198cb4dfSChris Lattner OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); 723198cb4dfSChris Lattner if (NumWarnings || NumErrors) 724198cb4dfSChris Lattner OS << " generated.\n"; 725198cb4dfSChris Lattner } 7264f2bc55dSDaniel Dunbar 727aed46fcbSDaniel Dunbar if (getFrontendOpts().ShowStats && hasFileManager()) { 7284f2bc55dSDaniel Dunbar getFileManager().PrintStats(); 7294f2bc55dSDaniel Dunbar OS << "\n"; 7304f2bc55dSDaniel Dunbar } 7314f2bc55dSDaniel Dunbar 732bc467933SArgyrios Kyrtzidis return !getDiagnostics().getClient()->getNumErrors(); 7334f2bc55dSDaniel Dunbar } 7344f2bc55dSDaniel Dunbar 735faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language 736faeb1d46SDouglas Gregor /// options. 737faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { 738faeb1d46SDouglas Gregor if (LangOpts.OpenCL) 739faeb1d46SDouglas Gregor return IK_OpenCL; 740faeb1d46SDouglas Gregor if (LangOpts.CUDA) 741faeb1d46SDouglas Gregor return IK_CUDA; 742faeb1d46SDouglas Gregor if (LangOpts.ObjC1) 743faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC; 744faeb1d46SDouglas Gregor return LangOpts.CPlusPlus? IK_CXX : IK_C; 745faeb1d46SDouglas Gregor } 746faeb1d46SDouglas Gregor 74751e0b541SDouglas Gregor namespace { 748514b636aSDouglas Gregor struct CompileModuleMapData { 749514b636aSDouglas Gregor CompilerInstance &Instance; 750514b636aSDouglas Gregor GenerateModuleAction &CreateModuleAction; 751514b636aSDouglas Gregor }; 752514b636aSDouglas Gregor } 753514b636aSDouglas Gregor 754514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under 755514b636aSDouglas Gregor /// a crash recovery context. 756514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) { 757514b636aSDouglas Gregor CompileModuleMapData &Data 758514b636aSDouglas Gregor = *reinterpret_cast<CompileModuleMapData *>(UserData); 759514b636aSDouglas Gregor Data.Instance.ExecuteAction(Data.CreateModuleAction); 760514b636aSDouglas Gregor } 761514b636aSDouglas Gregor 762514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options 763514b636aSDouglas Gregor /// provided by the importing compiler instance. 764faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance, 765af8f0263SDouglas Gregor SourceLocation ImportLoc, 766de3ef502SDouglas Gregor Module *Module, 7676dc57927SDouglas Gregor StringRef ModuleFileName) { 768e212489fSDouglas Gregor llvm::LockFileManager Locked(ModuleFileName); 76954a88810SDouglas Gregor switch (Locked) { 770e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Error: 77154a88810SDouglas Gregor return; 77254a88810SDouglas Gregor 773e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Owned: 77454a88810SDouglas Gregor // We're responsible for building the module ourselves. Do so below. 77554a88810SDouglas Gregor break; 77654a88810SDouglas Gregor 777e212489fSDouglas Gregor case llvm::LockFileManager::LFS_Shared: 77854a88810SDouglas Gregor // Someone else is responsible for building the module. Wait for them to 77954a88810SDouglas Gregor // finish. 78054a88810SDouglas Gregor Locked.waitForUnlock(); 781188dbef2SDouglas Gregor return; 78254a88810SDouglas Gregor } 78354a88810SDouglas Gregor 784514b636aSDouglas Gregor ModuleMap &ModMap 785514b636aSDouglas Gregor = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); 786514b636aSDouglas Gregor 787faeb1d46SDouglas Gregor // Construct a compiler invocation for creating this module. 788c95d8192SDylan Noblesmith IntrusiveRefCntPtr<CompilerInvocation> Invocation 789faeb1d46SDouglas Gregor (new CompilerInvocation(ImportingInstance.getInvocation())); 79044bf68d8SDouglas Gregor 791f545f67dSDouglas Gregor PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); 792f545f67dSDouglas Gregor 79344bf68d8SDouglas Gregor // For any options that aren't intended to affect how a module is built, 79444bf68d8SDouglas Gregor // reset them to their default values. 7958cf47df7STed Kremenek Invocation->getLangOpts()->resetNonModularOptions(); 796f545f67dSDouglas Gregor PPOpts.resetNonModularOptions(); 79744bf68d8SDouglas Gregor 7987d106e42SDouglas Gregor // Note the name of the module we're building. 7996dc57927SDouglas Gregor Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); 8007d106e42SDouglas Gregor 8017a626570SDouglas Gregor // Make sure that the failed-module structure has been allocated in 8027a626570SDouglas Gregor // the importing instance, and propagate the pointer to the newly-created 8037a626570SDouglas Gregor // instance. 8047a626570SDouglas Gregor PreprocessorOptions &ImportingPPOpts 8057a626570SDouglas Gregor = ImportingInstance.getInvocation().getPreprocessorOpts(); 8067a626570SDouglas Gregor if (!ImportingPPOpts.FailedModules) 8077a626570SDouglas Gregor ImportingPPOpts.FailedModules = new PreprocessorOptions::FailedModulesSet; 8087a626570SDouglas Gregor PPOpts.FailedModules = ImportingPPOpts.FailedModules; 8097a626570SDouglas Gregor 810514b636aSDouglas Gregor // If there is a module map file, build the module using the module map. 811514b636aSDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella 812514b636aSDouglas Gregor // header. 813514b636aSDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); 814514b636aSDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str(); 815514b636aSDouglas Gregor FrontendOpts.DisableFree = false; 816514b636aSDouglas Gregor FrontendOpts.Inputs.clear(); 817f545f67dSDouglas Gregor InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); 818f545f67dSDouglas Gregor 819f545f67dSDouglas Gregor // Get or create the module map that we'll use to build this module. 8202c1dd271SDylan Noblesmith SmallString<128> TempModuleMapFileName; 821f545f67dSDouglas Gregor if (const FileEntry *ModuleMapFile 822f545f67dSDouglas Gregor = ModMap.getContainingModuleMapFile(Module)) { 823f545f67dSDouglas Gregor // Use the module map where this module resides. 82432fbe312SDouglas Gregor FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), 82532fbe312SDouglas Gregor IK)); 826f545f67dSDouglas Gregor } else { 827f545f67dSDouglas Gregor // Create a temporary module map file. 828f545f67dSDouglas Gregor TempModuleMapFileName = Module->Name; 829f545f67dSDouglas Gregor TempModuleMapFileName += "-%%%%%%%%.map"; 830f545f67dSDouglas Gregor int FD; 831f545f67dSDouglas Gregor if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, 832f545f67dSDouglas Gregor TempModuleMapFileName, 83319f9f7bcSDouglas Gregor /*makeAbsolute=*/true) 8342f554c4cSDouglas Gregor != llvm::errc::success) { 835ee78d3e0SDouglas Gregor ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) 836ee78d3e0SDouglas Gregor << TempModuleMapFileName; 837f545f67dSDouglas Gregor return; 8382f554c4cSDouglas Gregor } 839f545f67dSDouglas Gregor // Print the module map to this file. 840f545f67dSDouglas Gregor llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); 841f545f67dSDouglas Gregor Module->print(OS); 842514b636aSDouglas Gregor FrontendOpts.Inputs.push_back( 84332fbe312SDouglas Gregor FrontendInputFile(TempModuleMapFileName.str().str(), IK)); 844f545f67dSDouglas Gregor } 845f545f67dSDouglas Gregor 846f545f67dSDouglas Gregor // Don't free the remapped file buffers; they are owned by our caller. 847f545f67dSDouglas Gregor PPOpts.RetainRemappedFileBuffers = true; 848514b636aSDouglas Gregor 849514b636aSDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; 850514b636aSDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() == 851514b636aSDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!"); 852514b636aSDouglas Gregor 853514b636aSDouglas Gregor // Construct a compiler instance that will be used to actually create the 854514b636aSDouglas Gregor // module. 855514b636aSDouglas Gregor CompilerInstance Instance; 856514b636aSDouglas Gregor Instance.setInvocation(&*Invocation); 857514b636aSDouglas Gregor Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, 858514b636aSDouglas Gregor &ImportingInstance.getDiagnosticClient(), 859514b636aSDouglas Gregor /*ShouldOwnClient=*/true, 860514b636aSDouglas Gregor /*ShouldCloneClient=*/true); 861514b636aSDouglas Gregor 86263365431SDouglas Gregor // Note that this module is part of the module build stack, so that we 863af8f0263SDouglas Gregor // can detect cycles in the module graph. 864af8f0263SDouglas Gregor Instance.createFileManager(); // FIXME: Adopt file manager from importer? 865af8f0263SDouglas Gregor Instance.createSourceManager(Instance.getFileManager()); 866af8f0263SDouglas Gregor SourceManager &SourceMgr = Instance.getSourceManager(); 86763365431SDouglas Gregor SourceMgr.setModuleBuildStack( 86863365431SDouglas Gregor ImportingInstance.getSourceManager().getModuleBuildStack()); 86963365431SDouglas Gregor SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), 870af8f0263SDouglas Gregor FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); 871af8f0263SDouglas Gregor 872af8f0263SDouglas Gregor 873514b636aSDouglas Gregor // Construct a module-generating action. 874514b636aSDouglas Gregor GenerateModuleAction CreateModuleAction; 875514b636aSDouglas Gregor 876514b636aSDouglas Gregor // Execute the action to actually build the module in-place. Use a separate 877514b636aSDouglas Gregor // thread so that we get a stack large enough. 878514b636aSDouglas Gregor const unsigned ThreadStackSize = 8 << 20; 879514b636aSDouglas Gregor llvm::CrashRecoveryContext CRC; 880514b636aSDouglas Gregor CompileModuleMapData Data = { Instance, CreateModuleAction }; 881514b636aSDouglas Gregor CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); 882514b636aSDouglas Gregor 883f545f67dSDouglas Gregor // Delete the temporary module map file. 884f545f67dSDouglas Gregor // FIXME: Even though we're executing under crash protection, it would still 885f545f67dSDouglas Gregor // be nice to do this with RemoveFileOnSignal when we can. However, that 886f545f67dSDouglas Gregor // doesn't make sense for all clients, so clean this up manually. 88713afbf42SBenjamin Kramer Instance.clearOutputFiles(/*EraseFiles=*/true); 888f545f67dSDouglas Gregor if (!TempModuleMapFileName.empty()) 889f545f67dSDouglas Gregor llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); 890faeb1d46SDouglas Gregor } 891faeb1d46SDouglas Gregor 8927a626570SDouglas Gregor ModuleLoadResult 8937a626570SDouglas Gregor CompilerInstance::loadModule(SourceLocation ImportLoc, 894ff2be53fSDouglas Gregor ModuleIdPath Path, 895bcfc7d02SDouglas Gregor Module::NameVisibilityKind Visibility, 896bcfc7d02SDouglas Gregor bool IsInclusionDirective) { 8971805b8a4SDouglas Gregor // If we've already handled this import, just return the cached result. 8981805b8a4SDouglas Gregor // This one-element cache is important to eliminate redundant diagnostics 8991805b8a4SDouglas Gregor // when both the preprocessor and parser see the same import declaration. 900ff2be53fSDouglas Gregor if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { 901ff2be53fSDouglas Gregor // Make the named module visible. 902ff2be53fSDouglas Gregor if (LastModuleImportResult) 903ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility); 90469021974SDouglas Gregor return LastModuleImportResult; 905ff2be53fSDouglas Gregor } 9061805b8a4SDouglas Gregor 90708142534SDouglas Gregor // Determine what file we're searching from. 90871944203SDouglas Gregor StringRef ModuleName = Path[0].first->getName(); 90971944203SDouglas Gregor SourceLocation ModuleNameLoc = Path[0].second; 91071944203SDouglas Gregor 911de3ef502SDouglas Gregor clang::Module *Module = 0; 9125196bc6bSDouglas Gregor 9135196bc6bSDouglas Gregor // If we don't already have information on this module, load the module now. 914de3ef502SDouglas Gregor llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known 91569021974SDouglas Gregor = KnownModules.find(Path[0].first); 9162537a364SDouglas Gregor if (Known != KnownModules.end()) { 9172537a364SDouglas Gregor // Retrieve the cached top-level module. 9182537a364SDouglas Gregor Module = Known->second; 9192537a364SDouglas Gregor } else if (ModuleName == getLangOpts().CurrentModule) { 9202537a364SDouglas Gregor // This is the module we're building. 9212537a364SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName); 9222537a364SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 9232537a364SDouglas Gregor } else { 9245196bc6bSDouglas Gregor // Search for a module with the given name. 925279a6c37SDouglas Gregor Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); 9261735f4e7SDouglas Gregor std::string ModuleFileName; 927279a6c37SDouglas Gregor if (Module) 928279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); 929279a6c37SDouglas Gregor else 930279a6c37SDouglas Gregor ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName); 931faeb1d46SDouglas Gregor 932279a6c37SDouglas Gregor if (ModuleFileName.empty()) { 933279a6c37SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) 934279a6c37SDouglas Gregor << ModuleName 935279a6c37SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 936279a6c37SDouglas Gregor LastModuleImportLoc = ImportLoc; 9377a626570SDouglas Gregor LastModuleImportResult = ModuleLoadResult(); 9387a626570SDouglas Gregor return LastModuleImportResult; 939279a6c37SDouglas Gregor } 940279a6c37SDouglas Gregor 941279a6c37SDouglas Gregor const FileEntry *ModuleFile 942279a6c37SDouglas Gregor = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false, 943279a6c37SDouglas Gregor /*CacheFailure=*/false); 944faeb1d46SDouglas Gregor bool BuildingModule = false; 9456dc57927SDouglas Gregor if (!ModuleFile && Module) { 9466dc57927SDouglas Gregor // The module is not cached, but we have a module map from which we can 9476dc57927SDouglas Gregor // build the module. 948dff0e892SDouglas Gregor 949dff0e892SDouglas Gregor // Check whether there is a cycle in the module graph. 95063365431SDouglas Gregor ModuleBuildStack Path = getSourceManager().getModuleBuildStack(); 95163365431SDouglas Gregor ModuleBuildStack::iterator Pos = Path.begin(), PosEnd = Path.end(); 952af8f0263SDouglas Gregor for (; Pos != PosEnd; ++Pos) { 953af8f0263SDouglas Gregor if (Pos->first == ModuleName) 954af8f0263SDouglas Gregor break; 955af8f0263SDouglas Gregor } 956af8f0263SDouglas Gregor 957af8f0263SDouglas Gregor if (Pos != PosEnd) { 9582c1dd271SDylan Noblesmith SmallString<256> CyclePath; 959af8f0263SDouglas Gregor for (; Pos != PosEnd; ++Pos) { 960af8f0263SDouglas Gregor CyclePath += Pos->first; 961dff0e892SDouglas Gregor CyclePath += " -> "; 962dff0e892SDouglas Gregor } 96371944203SDouglas Gregor CyclePath += ModuleName; 964dff0e892SDouglas Gregor 965dff0e892SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) 96671944203SDouglas Gregor << ModuleName << CyclePath; 9677a626570SDouglas Gregor return ModuleLoadResult(); 9687a626570SDouglas Gregor } 9697a626570SDouglas Gregor 9707a626570SDouglas Gregor // Check whether we have already attempted to build this module (but 9717a626570SDouglas Gregor // failed). 9727a626570SDouglas Gregor if (getPreprocessorOpts().FailedModules && 9737a626570SDouglas Gregor getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { 9747a626570SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) 9757a626570SDouglas Gregor << ModuleName 9767a626570SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 9777a626570SDouglas Gregor 9787a626570SDouglas Gregor return ModuleLoadResult(); 979dff0e892SDouglas Gregor } 980dff0e892SDouglas Gregor 981faeb1d46SDouglas Gregor BuildingModule = true; 982af8f0263SDouglas Gregor compileModule(*this, ModuleNameLoc, Module, ModuleFileName); 983ca295457SDouglas Gregor ModuleFile = FileMgr->getFile(ModuleFileName); 9847a626570SDouglas Gregor 985*0f2b4635SDouglas Gregor if (!ModuleFile && getPreprocessorOpts().FailedModules) 9867a626570SDouglas Gregor getPreprocessorOpts().FailedModules->addFailed(ModuleName); 987faeb1d46SDouglas Gregor } 988faeb1d46SDouglas Gregor 98908142534SDouglas Gregor if (!ModuleFile) { 990faeb1d46SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, 991faeb1d46SDouglas Gregor BuildingModule? diag::err_module_not_built 992faeb1d46SDouglas Gregor : diag::err_module_not_found) 99371944203SDouglas Gregor << ModuleName 99408142534SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 9957a626570SDouglas Gregor return ModuleLoadResult(); 99608142534SDouglas Gregor } 99708142534SDouglas Gregor 99808142534SDouglas Gregor // If we don't already have an ASTReader, create one now. 99908142534SDouglas Gregor if (!ModuleManager) { 100021931efcSDouglas Gregor if (!hasASTContext()) 100121931efcSDouglas Gregor createASTContext(); 100221931efcSDouglas Gregor 100308142534SDouglas Gregor std::string Sysroot = getHeaderSearchOpts().Sysroot; 100408142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts(); 10058835e03cSDouglas Gregor ModuleManager = new ASTReader(getPreprocessor(), *Context, 100608142534SDouglas Gregor Sysroot.empty() ? "" : Sysroot.c_str(), 1007d7c16b25SArgyrios Kyrtzidis PPOpts.DisablePCHValidation); 100821931efcSDouglas Gregor if (hasASTConsumer()) { 100908142534SDouglas Gregor ModuleManager->setDeserializationListener( 101008142534SDouglas Gregor getASTConsumer().GetASTDeserializationListener()); 101108142534SDouglas Gregor getASTContext().setASTMutationListener( 101208142534SDouglas Gregor getASTConsumer().GetASTMutationListener()); 1013cb28f9d7SDouglas Gregor getPreprocessor().setPPMutationListener( 1014cb28f9d7SDouglas Gregor getASTConsumer().GetPPMutationListener()); 101521931efcSDouglas Gregor } 1016e2778999SDylan Noblesmith OwningPtr<ExternalASTSource> Source; 101708142534SDouglas Gregor Source.reset(ModuleManager); 101808142534SDouglas Gregor getASTContext().setExternalSource(Source); 101921931efcSDouglas Gregor if (hasSema()) 102008142534SDouglas Gregor ModuleManager->InitializeSema(getSema()); 10216137d32cSDouglas Gregor if (hasASTConsumer()) 10226137d32cSDouglas Gregor ModuleManager->StartTranslationUnit(&getASTConsumer()); 102308142534SDouglas Gregor } 102408142534SDouglas Gregor 102508142534SDouglas Gregor // Try to load the module we found. 1026188dbef2SDouglas Gregor unsigned ARRFlags = ASTReader::ARR_None; 1027188dbef2SDouglas Gregor if (Module) 1028188dbef2SDouglas Gregor ARRFlags |= ASTReader::ARR_OutOfDate; 102908142534SDouglas Gregor switch (ModuleManager->ReadAST(ModuleFile->getName(), 10302ec29367SArgyrios Kyrtzidis serialization::MK_Module, ImportLoc, 1031188dbef2SDouglas Gregor ARRFlags)) { 103208142534SDouglas Gregor case ASTReader::Success: 103308142534SDouglas Gregor break; 103408142534SDouglas Gregor 1035188dbef2SDouglas Gregor case ASTReader::OutOfDate: { 1036188dbef2SDouglas Gregor // The module file is out-of-date. Rebuild it. 1037188dbef2SDouglas Gregor getFileManager().invalidateCache(ModuleFile); 1038188dbef2SDouglas Gregor bool Existed; 1039188dbef2SDouglas Gregor llvm::sys::fs::remove(ModuleFileName, Existed); 10407a626570SDouglas Gregor 10417a626570SDouglas Gregor // Check whether we have already attempted to build this module (but 10427a626570SDouglas Gregor // failed). 10437a626570SDouglas Gregor if (getPreprocessorOpts().FailedModules && 10447a626570SDouglas Gregor getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { 10457a626570SDouglas Gregor getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) 10467a626570SDouglas Gregor << ModuleName 10477a626570SDouglas Gregor << SourceRange(ImportLoc, ModuleNameLoc); 10487a626570SDouglas Gregor 10497a626570SDouglas Gregor return ModuleLoadResult(); 10507a626570SDouglas Gregor } 10517a626570SDouglas Gregor 1052af8f0263SDouglas Gregor compileModule(*this, ModuleNameLoc, Module, ModuleFileName); 1053188dbef2SDouglas Gregor 1054188dbef2SDouglas Gregor // Try loading the module again. 1055188dbef2SDouglas Gregor ModuleFile = FileMgr->getFile(ModuleFileName); 1056188dbef2SDouglas Gregor if (!ModuleFile || 1057188dbef2SDouglas Gregor ModuleManager->ReadAST(ModuleFileName, 10582ec29367SArgyrios Kyrtzidis serialization::MK_Module, ImportLoc, 1059188dbef2SDouglas Gregor ASTReader::ARR_None) != ASTReader::Success) { 1060*0f2b4635SDouglas Gregor if (getPreprocessorOpts().FailedModules) 10617a626570SDouglas Gregor getPreprocessorOpts().FailedModules->addFailed(ModuleName); 1062188dbef2SDouglas Gregor KnownModules[Path[0].first] = 0; 10637a626570SDouglas Gregor return ModuleLoadResult(); 1064188dbef2SDouglas Gregor } 1065188dbef2SDouglas Gregor 1066188dbef2SDouglas Gregor // Okay, we've rebuilt and now loaded the module. 1067188dbef2SDouglas Gregor break; 1068188dbef2SDouglas Gregor } 1069188dbef2SDouglas Gregor 1070c9ad5fb6SDouglas Gregor case ASTReader::VersionMismatch: 1071c9ad5fb6SDouglas Gregor case ASTReader::ConfigurationMismatch: 1072c9ad5fb6SDouglas Gregor case ASTReader::HadErrors: 107308142534SDouglas Gregor // FIXME: The ASTReader will already have complained, but can we showhorn 107408142534SDouglas Gregor // that diagnostic information into a more useful form? 107569021974SDouglas Gregor KnownModules[Path[0].first] = 0; 10767a626570SDouglas Gregor return ModuleLoadResult(); 107708142534SDouglas Gregor 107808142534SDouglas Gregor case ASTReader::Failure: 107969021974SDouglas Gregor // Already complained, but note now that we failed. 108069021974SDouglas Gregor KnownModules[Path[0].first] = 0; 10817a626570SDouglas Gregor return ModuleLoadResult(); 108208142534SDouglas Gregor } 108308142534SDouglas Gregor 108469021974SDouglas Gregor if (!Module) { 108569021974SDouglas Gregor // If we loaded the module directly, without finding a module map first, 108669021974SDouglas Gregor // we'll have loaded the module's information from the module itself. 108769021974SDouglas Gregor Module = PP->getHeaderSearchInfo().getModuleMap() 108869021974SDouglas Gregor .findModule((Path[0].first->getName())); 10895196bc6bSDouglas Gregor } 109043af5132SArgyrios Kyrtzidis 109143af5132SArgyrios Kyrtzidis if (Module) 109243af5132SArgyrios Kyrtzidis Module->setASTFile(ModuleFile); 10935196bc6bSDouglas Gregor 109469021974SDouglas Gregor // Cache the result of this top-level module lookup for later. 109569021974SDouglas Gregor Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; 109669021974SDouglas Gregor } 109769021974SDouglas Gregor 109869021974SDouglas Gregor // If we never found the module, fail. 109969021974SDouglas Gregor if (!Module) 11007a626570SDouglas Gregor return ModuleLoadResult(); 110169021974SDouglas Gregor 11025196bc6bSDouglas Gregor // Verify that the rest of the module path actually corresponds to 11035196bc6bSDouglas Gregor // a submodule. 110469021974SDouglas Gregor if (Path.size() > 1) { 11055196bc6bSDouglas Gregor for (unsigned I = 1, N = Path.size(); I != N; ++I) { 11065196bc6bSDouglas Gregor StringRef Name = Path[I].first->getName(); 1107eb90e830SDouglas Gregor clang::Module *Sub = Module->findSubmodule(Name); 11085196bc6bSDouglas Gregor 1109eb90e830SDouglas Gregor if (!Sub) { 11105196bc6bSDouglas Gregor // Attempt to perform typo correction to find a module name that works. 11115196bc6bSDouglas Gregor llvm::SmallVector<StringRef, 2> Best; 11125196bc6bSDouglas Gregor unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)(); 11135196bc6bSDouglas Gregor 1114eb90e830SDouglas Gregor for (clang::Module::submodule_iterator J = Module->submodule_begin(), 1115eb90e830SDouglas Gregor JEnd = Module->submodule_end(); 1116eb44edadSMatt Beaumont-Gay J != JEnd; ++J) { 1117eb90e830SDouglas Gregor unsigned ED = Name.edit_distance((*J)->Name, 11185196bc6bSDouglas Gregor /*AllowReplacements=*/true, 11195196bc6bSDouglas Gregor BestEditDistance); 11205196bc6bSDouglas Gregor if (ED <= BestEditDistance) { 1121eb90e830SDouglas Gregor if (ED < BestEditDistance) { 11225196bc6bSDouglas Gregor Best.clear(); 1123eb90e830SDouglas Gregor BestEditDistance = ED; 1124eb90e830SDouglas Gregor } 1125eb90e830SDouglas Gregor 1126eb90e830SDouglas Gregor Best.push_back((*J)->Name); 11275196bc6bSDouglas Gregor } 11285196bc6bSDouglas Gregor } 11295196bc6bSDouglas Gregor 11305196bc6bSDouglas Gregor // If there was a clear winner, user it. 11315196bc6bSDouglas Gregor if (Best.size() == 1) { 11325196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, 11335196bc6bSDouglas Gregor diag::err_no_submodule_suggest) 113469021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() << Best[0] 11355196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second) 11365196bc6bSDouglas Gregor << FixItHint::CreateReplacement(SourceRange(Path[I].second), 11375196bc6bSDouglas Gregor Best[0]); 1138eb90e830SDouglas Gregor 1139eb90e830SDouglas Gregor Sub = Module->findSubmodule(Best[0]); 11405196bc6bSDouglas Gregor } 11415196bc6bSDouglas Gregor } 11425196bc6bSDouglas Gregor 1143eb90e830SDouglas Gregor if (!Sub) { 11445196bc6bSDouglas Gregor // No submodule by this name. Complain, and don't look for further 11455196bc6bSDouglas Gregor // submodules. 11465196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, diag::err_no_submodule) 114769021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() 11485196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I-1].second); 11495196bc6bSDouglas Gregor break; 11505196bc6bSDouglas Gregor } 11515196bc6bSDouglas Gregor 1152eb90e830SDouglas Gregor Module = Sub; 11535196bc6bSDouglas Gregor } 11545196bc6bSDouglas Gregor } 11555196bc6bSDouglas Gregor 11562537a364SDouglas Gregor // Make the named module visible, if it's not already part of the module 11572537a364SDouglas Gregor // we are parsing. 115898a52db8SDouglas Gregor if (ModuleName != getLangOpts().CurrentModule) { 115998a52db8SDouglas Gregor if (!Module->IsFromModuleFile) { 116098a52db8SDouglas Gregor // We have an umbrella header or directory that doesn't actually include 116198a52db8SDouglas Gregor // all of the headers within the directory it covers. Complain about 116298a52db8SDouglas Gregor // this missing submodule and recover by forgetting that we ever saw 116398a52db8SDouglas Gregor // this submodule. 116498a52db8SDouglas Gregor // FIXME: Should we detect this at module load time? It seems fairly 116598a52db8SDouglas Gregor // expensive (and rare). 116698a52db8SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule) 116798a52db8SDouglas Gregor << Module->getFullModuleName() 116898a52db8SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 116998a52db8SDouglas Gregor 11707a626570SDouglas Gregor return ModuleLoadResult(0, true); 117198a52db8SDouglas Gregor } 11721fb5c3a6SDouglas Gregor 11731fb5c3a6SDouglas Gregor // Check whether this module is available. 11741fb5c3a6SDouglas Gregor StringRef Feature; 117589929282SDouglas Gregor if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) { 11761fb5c3a6SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) 11771fb5c3a6SDouglas Gregor << Module->getFullModuleName() 11781fb5c3a6SDouglas Gregor << Feature 11791fb5c3a6SDouglas Gregor << SourceRange(Path.front().second, Path.back().second); 11801fb5c3a6SDouglas Gregor LastModuleImportLoc = ImportLoc; 11817a626570SDouglas Gregor LastModuleImportResult = ModuleLoadResult(); 11827a626570SDouglas Gregor return ModuleLoadResult(); 11831fb5c3a6SDouglas Gregor } 11841fb5c3a6SDouglas Gregor 1185ff2be53fSDouglas Gregor ModuleManager->makeModuleVisible(Module, Visibility); 118698a52db8SDouglas Gregor } 11875196bc6bSDouglas Gregor 1188bcfc7d02SDouglas Gregor // If this module import was due to an inclusion directive, create an 1189bcfc7d02SDouglas Gregor // implicit import declaration to capture it in the AST. 1190bcfc7d02SDouglas Gregor if (IsInclusionDirective && hasASTContext()) { 1191bcfc7d02SDouglas Gregor TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); 119272d1aa3cSArgyrios Kyrtzidis ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, 1193bcfc7d02SDouglas Gregor ImportLoc, Module, 119472d1aa3cSArgyrios Kyrtzidis Path.back().second); 119572d1aa3cSArgyrios Kyrtzidis TU->addDecl(ImportD); 119672d1aa3cSArgyrios Kyrtzidis if (Consumer) 119772d1aa3cSArgyrios Kyrtzidis Consumer->HandleImplicitImportDecl(ImportD); 1198bcfc7d02SDouglas Gregor } 1199bcfc7d02SDouglas Gregor 12001805b8a4SDouglas Gregor LastModuleImportLoc = ImportLoc; 12017a626570SDouglas Gregor LastModuleImportResult = ModuleLoadResult(Module, false); 12027a626570SDouglas Gregor return LastModuleImportResult; 120308142534SDouglas Gregor } 1204