diff options
Diffstat (limited to 'lib/Frontend/CompilerInstance.cpp')
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 219 |
1 files changed, 116 insertions, 103 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index cf856fc..eccb94c 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -111,8 +111,8 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, if (DiagOpts->DiagnosticLogFile != "-") { // Create the output stream. llvm::raw_fd_ostream *FileOS( - new llvm::raw_fd_ostream(DiagOpts->DiagnosticLogFile.c_str(), - ErrorInfo, llvm::raw_fd_ostream::F_Append)); + new llvm::raw_fd_ostream(DiagOpts->DiagnosticLogFile.c_str(), ErrorInfo, + llvm::sys::fs::F_Append)); if (!ErrorInfo.empty()) { Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) << DiagOpts->DiagnosticLogFile << ErrorInfo; @@ -138,8 +138,8 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, std::string ErrorInfo; OwningPtr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary)); - + llvm::sys::fs::F_Binary)); + if (!ErrorInfo.empty()) { Diags.Report(diag::warn_fe_serialized_diag_failure) << OutputFile << ErrorInfo; @@ -218,7 +218,7 @@ void CompilerInstance::createPreprocessor() { // Create the Preprocessor. HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(), - getFileManager(), + getSourceManager(), getDiagnostics(), getLangOpts(), &getTarget()); @@ -259,7 +259,7 @@ void CompilerInstance::createPreprocessor() { AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, getHeaderSearchOpts().Sysroot); - + // Handle generating header include information, if requested. if (DepOpts.ShowHeaderIncludes) AttachHeaderIncludeGen(*PP); @@ -270,6 +270,11 @@ void CompilerInstance::createPreprocessor() { AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, /*ShowDepth=*/false); } + + if (DepOpts.PrintShowIncludes) { + AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"", + /*ShowDepth=*/true, /*MSStyle=*/true); + } } // ASTContext @@ -384,7 +389,7 @@ void CompilerInstance::createCodeCompletionConsumer() { } if (CompletionConsumer->isOutputBinary() && - llvm::sys::Program::ChangeStdoutToBinary()) { + llvm::sys::ChangeStdoutToBinary()) { getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); setCodeCompletionConsumer(0); } @@ -445,7 +450,7 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) { } } } else if (!it->Filename.empty() && EraseFiles) - llvm::sys::Path(it->Filename).eraseFromDisk(); + llvm::sys::fs::remove(it->Filename); } OutputFiles.clear(); @@ -509,9 +514,8 @@ CompilerInstance::createOutputFile(StringRef OutputPath, } else if (InFile == "-") { OutFile = "-"; } else if (!Extension.empty()) { - llvm::sys::Path Path(InFile); - Path.eraseSuffix(); - Path.appendSuffix(Extension); + SmallString<128> Path(InFile); + llvm::sys::path::replace_extension(Path, Extension); OutFile = Path.str(); } else { OutFile = "-"; @@ -520,47 +524,64 @@ CompilerInstance::createOutputFile(StringRef OutputPath, OwningPtr<llvm::raw_fd_ostream> OS; std::string OSFile; - if (UseTemporary && OutFile != "-") { - // Only create the temporary if the parent directory exists (or create - // missing directories is true) and we can actually write to OutPath, - // otherwise we want to fail early. - SmallString<256> AbsPath(OutputPath); - llvm::sys::fs::make_absolute(AbsPath); - llvm::sys::Path OutPath(AbsPath); - bool ParentExists = false; - if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()), - ParentExists)) - ParentExists = false; - bool Exists; - if ((CreateMissingDirectories || ParentExists) && - ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) || - (OutPath.isRegularFile() && OutPath.canWrite()))) { - // Create a temporary file. - SmallString<128> TempPath; - TempPath = OutFile; - TempPath += "-%%%%%%%%"; - int fd; - if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, - /*makeAbsolute=*/false, 0664) - == llvm::errc::success) { - OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); - OSFile = TempFile = TempPath.str(); + if (UseTemporary) { + if (OutFile == "-") + UseTemporary = false; + else { + llvm::sys::fs::file_status Status; + llvm::sys::fs::status(OutputPath, Status); + if (llvm::sys::fs::exists(Status)) { + // Fail early if we can't write to the final destination. + if (!llvm::sys::fs::can_write(OutputPath)) + return 0; + + // Don't use a temporary if the output is a special file. This handles + // things like '-o /dev/null' + if (!llvm::sys::fs::is_regular_file(Status)) + UseTemporary = false; } } } + if (UseTemporary) { + // Create a temporary file. + SmallString<128> TempPath; + TempPath = OutFile; + TempPath += "-%%%%%%%%"; + int fd; + llvm::error_code EC = + llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); + + if (CreateMissingDirectories && + EC == llvm::errc::no_such_file_or_directory) { + StringRef Parent = llvm::sys::path::parent_path(OutputPath); + EC = llvm::sys::fs::create_directories(Parent); + if (!EC) { + EC = llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); + } + } + + if (!EC) { + OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); + OSFile = TempFile = TempPath.str(); + } + // If we failed to create the temporary, fallback to writing to the file + // directly. This handles the corner case where we cannot write to the + // directory, but can write to the file. + } + if (!OS) { OSFile = OutFile; - OS.reset( - new llvm::raw_fd_ostream(OSFile.c_str(), Error, - (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); + OS.reset(new llvm::raw_fd_ostream( + OSFile.c_str(), Error, + (Binary ? llvm::sys::fs::F_Binary : llvm::sys::fs::F_None))); if (!Error.empty()) return 0; } // Make sure the out stream file gets removed if we crash. if (RemoveFileOnSignal) - llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); + llvm::sys::RemoveFileOnSignal(OSFile); if (ResultPathName) *ResultPathName = OutFile; @@ -597,7 +618,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File = FileMgr.getFile(InputFile); + const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; @@ -605,26 +626,27 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, // The natural SourceManager infrastructure can't currently handle named // pipes, but we would at least like to accept them for the main - // file. Detect them here, read them with the more generic MemoryBuffer - // function, and simply override their contents as we do for STDIN. + // file. Detect them here, read them with the volatile flag so FileMgr will + // pick up the correct size, and simply override their contents as we do for + // STDIN. if (File->isNamedPipe()) { - OwningPtr<llvm::MemoryBuffer> MB; - if (llvm::error_code ec = llvm::MemoryBuffer::getFile(InputFile, MB)) { - Diags.Report(diag::err_cannot_open_file) << InputFile << ec.message(); + std::string ErrorStr; + if (llvm::MemoryBuffer *MB = + FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)) { + // Create a new virtual file that will have the correct size. + File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); + SourceMgr.overrideFileContents(File, MB); + } else { + Diags.Report(diag::err_cannot_open_file) << InputFile << ErrorStr; return false; } - - // Create a new virtual file that will have the correct size. - File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); - SourceMgr.overrideFileContents(File, MB.take()); } SourceMgr.createMainFileID(File, Kind); } else { OwningPtr<llvm::MemoryBuffer> SB; - if (llvm::MemoryBuffer::getSTDIN(SB)) { - // FIXME: Give ec.message() in this diag. - Diags.Report(diag::err_fe_error_reading_stdin); + if (llvm::error_code ec = llvm::MemoryBuffer::getSTDIN(SB)) { + Diags.Report(diag::err_fe_error_reading_stdin) << ec.message(); return false; } const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), @@ -764,6 +786,11 @@ static void compileModule(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName) { + // FIXME: have LockFileManager return an error_code so that we can + // avoid the mkdir when the directory already exists. + StringRef Dir = llvm::sys::path::parent_path(ModuleFileName); + llvm::sys::fs::create_directories(Dir); + llvm::LockFileManager Locked(ModuleFileName); switch (Locked) { case llvm::LockFileManager::LFS_Error: @@ -824,33 +851,6 @@ static void compileModule(CompilerInstance &ImportingInstance, FrontendOpts.Inputs.clear(); InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); - // Get or create the module map that we'll use to build this module. - SmallString<128> TempModuleMapFileName; - if (const FileEntry *ModuleMapFile - = ModMap.getContainingModuleMapFile(Module)) { - // Use the module map where this module resides. - FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), - IK)); - } else { - // Create a temporary module map file. - TempModuleMapFileName = Module->Name; - TempModuleMapFileName += "-%%%%%%%%.map"; - int FD; - if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, - TempModuleMapFileName, - /*makeAbsolute=*/true) - != llvm::errc::success) { - ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) - << TempModuleMapFileName; - return; - } - // Print the module map to this file. - llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); - Module->print(OS); - FrontendOpts.Inputs.push_back( - FrontendInputFile(TempModuleMapFileName.str().str(), IK)); - } - // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; @@ -877,9 +877,29 @@ static void compileModule(CompilerInstance &ImportingInstance, SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Get or create the module map that we'll use to build this module. + std::string InferredModuleMapContent; + if (const FileEntry *ModuleMapFile = + ModMap.getContainingModuleMapFile(Module)) { + // Use the module map where this module resides. + FrontendOpts.Inputs.push_back( + FrontendInputFile(ModuleMapFile->getName(), IK)); + } else { + llvm::raw_string_ostream OS(InferredModuleMapContent); + Module->print(OS); + OS.flush(); + FrontendOpts.Inputs.push_back( + FrontendInputFile("__inferred_module.map", IK)); + + const llvm::MemoryBuffer *ModuleMapBuffer = + llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); + ModuleMapFile = Instance.getFileManager().getVirtualFile( + "__inferred_module.map", InferredModuleMapContent.size(), 0); + SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer); + } // Construct a module-generating action. - GenerateModuleAction CreateModuleAction; + GenerateModuleAction CreateModuleAction(Module->IsSystem); // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. @@ -894,8 +914,6 @@ static void compileModule(CompilerInstance &ImportingInstance, // be nice to do this with RemoveFileOnSignal when we can. However, that // doesn't make sense for all clients, so clean this up manually. Instance.clearOutputFiles(/*EraseFiles=*/true); - if (!TempModuleMapFileName.empty()) - llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); // We've rebuilt a module. If we're allowed to generate or update the global // module index, record that fact in the importing compiler instance. @@ -994,7 +1012,7 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, static void writeTimestampFile(StringRef TimestampFile) { std::string ErrorInfo; llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary); + llvm::sys::fs::F_Binary); } /// \brief Prune the module cache of modules that haven't been accessed in @@ -1035,8 +1053,7 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { Dir(ModuleCachePathNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // If we don't have a directory, there's nothing to look into. - bool IsDirectory; - if (llvm::sys::fs::is_directory(Dir->path(), IsDirectory) || !IsDirectory) + if (!llvm::sys::fs::is_directory(Dir->path())) continue; // Walk all of the files within this directory. @@ -1086,23 +1103,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) { + // Determine what file we're searching from. + StringRef ModuleName = Path[0].first->getName(); + SourceLocation ModuleNameLoc = Path[0].second; + // If we've already handled this import, just return the cached result. // This one-element cache is important to eliminate redundant diagnostics // when both the preprocessor and parser see the same import declaration. if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { // Make the named module visible. - if (LastModuleImportResult) + if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule) ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility, ImportLoc, /*Complain=*/false); return LastModuleImportResult; } - - // Determine what file we're searching from. - StringRef ModuleName = Path[0].first->getName(); - SourceLocation ModuleNameLoc = Path[0].second; clang::Module *Module = 0; - + // If we don't already have information on this module, load the module now. llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known = KnownModules.find(Path[0].first); @@ -1164,15 +1181,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::Success: break; - case ASTReader::OutOfDate: { - // The module file is out-of-date. Remove it, then rebuild it. - bool Existed; - llvm::sys::fs::remove(ModuleFileName, Existed); - } - // Fall through to build the module again. - + case ASTReader::OutOfDate: case ASTReader::Missing: { - // The module file is (now) missing. Build it. + // The module file is missing or out-of-date. Build it. // If we don't have a module, we don't know how to build the module file. // Complain and return. @@ -1247,12 +1258,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: case ASTReader::HadErrors: + ModuleLoader::HadFatalFailure = true; // FIXME: The ASTReader will already have complained, but can we showhorn // that diagnostic information into a more useful form? KnownModules[Path[0].first] = 0; return ModuleLoadResult(); case ASTReader::Failure: + ModuleLoader::HadFatalFailure = true; // Already complained, but note now that we failed. KnownModules[Path[0].first] = 0; ModuleBuildFailed = true; @@ -1346,11 +1359,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } // Check whether this module is available. - StringRef Feature; - if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) { + clang::Module::Requirement Requirement; + if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement)) { getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) << Module->getFullModuleName() - << Feature + << Requirement.second << Requirement.first << SourceRange(Path.front().second, Path.back().second); LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(); |