aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp247
1 files changed, 134 insertions, 113 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
index 956877d34680..c642af1849bc 100644
--- a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
+++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
@@ -77,7 +77,7 @@ bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
return (BuildGlobalModuleIndex ||
(TheASTReader && TheASTReader->isGlobalIndexUnavailable() &&
getFrontendOpts().GenerateGlobalModuleIndex)) &&
- !ModuleBuildFailed;
+ !DisableGeneratingGlobalModuleIndex;
}
void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
@@ -97,6 +97,62 @@ void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
+bool CompilerInstance::createTarget() {
+ // Create the target instance.
+ setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
+ getInvocation().TargetOpts));
+ if (!hasTarget())
+ return false;
+
+ // Check whether AuxTarget exists, if not, then create TargetInfo for the
+ // other side of CUDA/OpenMP/SYCL compilation.
+ if (!getAuxTarget() &&
+ (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
+ getLangOpts().SYCLIsDevice) &&
+ !getFrontendOpts().AuxTriple.empty()) {
+ auto TO = std::make_shared<TargetOptions>();
+ TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
+ if (getFrontendOpts().AuxTargetCPU)
+ TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
+ if (getFrontendOpts().AuxTargetFeatures)
+ TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
+ TO->HostTriple = getTarget().getTriple().str();
+ setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
+ }
+
+ if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
+ if (getLangOpts().getFPRoundingMode() !=
+ llvm::RoundingMode::NearestTiesToEven) {
+ getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
+ getLangOpts().setFPRoundingMode(llvm::RoundingMode::NearestTiesToEven);
+ }
+ if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) {
+ getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
+ getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
+ }
+ // FIXME: can we disable FEnvAccess?
+ }
+
+ // We should do it here because target knows nothing about
+ // language options when it's being created.
+ if (getLangOpts().OpenCL &&
+ !getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()))
+ return false;
+
+ // Inform the target of the language options.
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ getTarget().adjust(getDiagnostics(), getLangOpts());
+
+ // Adjust target options based on codegen options.
+ getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
+
+ if (auto *Aux = getAuxTarget())
+ getTarget().setAuxTarget(Aux);
+
+ return true;
+}
+
llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
return getFileManager().getVirtualFileSystem();
}
@@ -229,7 +285,7 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
// Create the output stream.
auto FileOS = std::make_unique<llvm::raw_fd_ostream>(
DiagOpts->DiagnosticLogFile, EC,
- llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text);
+ llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
<< DiagOpts->DiagnosticLogFile << EC.message();
@@ -401,7 +457,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
getSourceManager(), *HeaderInfo, *this,
/*IdentifierInfoLookup=*/nullptr,
/*OwnsHeaderSearch=*/true, TUKind);
- getTarget().adjust(getLangOpts());
+ getTarget().adjust(getDiagnostics(), getLangOpts());
PP->Initialize(getTarget(), getAuxTarget());
if (PPOpts.DetailedRecord)
@@ -495,7 +551,7 @@ void CompilerInstance::createASTContext() {
Preprocessor &PP = getPreprocessor();
auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ PP.getBuiltinInfo(), PP.TUKind);
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
setASTContext(Context);
}
@@ -647,31 +703,37 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
// Output Files
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
+ // Ignore errors that occur when trying to discard the temp file.
for (OutputFile &OF : OutputFiles) {
if (EraseFiles) {
- if (!OF.TempFilename.empty()) {
- llvm::sys::fs::remove(OF.TempFilename);
- continue;
- }
+ if (OF.File)
+ consumeError(OF.File->discard());
if (!OF.Filename.empty())
llvm::sys::fs::remove(OF.Filename);
continue;
}
- if (OF.TempFilename.empty())
+ if (!OF.File)
continue;
+ if (OF.File->TmpName.empty()) {
+ consumeError(OF.File->discard());
+ continue;
+ }
+
// If '-working-directory' was passed, the output filename should be
// relative to that.
SmallString<128> NewOutFile(OF.Filename);
FileMgr->FixupRelativePath(NewOutFile);
- std::error_code EC = llvm::sys::fs::rename(OF.TempFilename, NewOutFile);
- if (!EC)
+
+ llvm::Error E = OF.File->keep(NewOutFile);
+ if (!E)
continue;
+
getDiagnostics().Report(diag::err_unable_to_rename_temp)
- << OF.TempFilename << OF.Filename << EC.message();
+ << OF.File->TmpName << OF.Filename << std::move(E);
- llvm::sys::fs::remove(OF.TempFilename);
+ llvm::sys::fs::remove(OF.File->TmpName);
}
OutputFiles.clear();
if (DeleteBuiltModules) {
@@ -681,11 +743,9 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) {
}
}
-std::unique_ptr<raw_pwrite_stream>
-CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
- StringRef Extension,
- bool RemoveFileOnSignal,
- bool CreateMissingDirectories) {
+std::unique_ptr<raw_pwrite_stream> CompilerInstance::createDefaultOutputFile(
+ bool Binary, StringRef InFile, StringRef Extension, bool RemoveFileOnSignal,
+ bool CreateMissingDirectories, bool ForceUseTemporary) {
StringRef OutputPath = getFrontendOpts().OutputFile;
Optional<SmallString<128>> PathStorage;
if (OutputPath.empty()) {
@@ -698,9 +758,8 @@ CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
}
}
- // Force a temporary file if RemoveFileOnSignal was disabled.
return createOutputFile(OutputPath, Binary, RemoveFileOnSignal,
- getFrontendOpts().UseTemporary || !RemoveFileOnSignal,
+ getFrontendOpts().UseTemporary || ForceUseTemporary,
CreateMissingDirectories);
}
@@ -753,7 +812,7 @@ CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
}
}
- std::string TempFile;
+ Optional<llvm::sys::fs::TempFile> Temp;
if (UseTemporary) {
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -765,22 +824,34 @@ CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
TempPath += "-%%%%%%%%";
TempPath += OutputExtension;
TempPath += ".tmp";
- int fd;
- std::error_code EC =
- llvm::sys::fs::createUniqueFile(TempPath, 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, fd, TempPath);
- }
- }
+ Expected<llvm::sys::fs::TempFile> ExpectedFile =
+ llvm::sys::fs::TempFile::create(
+ TempPath, llvm::sys::fs::all_read | llvm::sys::fs::all_write,
+ Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text);
+
+ llvm::Error E = handleErrors(
+ ExpectedFile.takeError(), [&](const llvm::ECError &E) -> llvm::Error {
+ std::error_code EC = E.convertToErrorCode();
+ 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) {
+ ExpectedFile = llvm::sys::fs::TempFile::create(TempPath);
+ if (!ExpectedFile)
+ return llvm::errorCodeToError(
+ llvm::errc::no_such_file_or_directory);
+ }
+ }
+ return llvm::errorCodeToError(EC);
+ });
- if (!EC) {
- OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
- OSFile = TempFile = std::string(TempPath.str());
+ if (E) {
+ consumeError(std::move(E));
+ } else {
+ Temp = std::move(ExpectedFile.get());
+ OS.reset(new llvm::raw_fd_ostream(Temp->FD, /*shouldClose=*/false));
+ OSFile = Temp->TmpName;
}
// 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
@@ -792,19 +863,15 @@ CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
std::error_code EC;
OS.reset(new llvm::raw_fd_ostream(
*OSFile, EC,
- (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text)));
+ (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_TextWithCRLF)));
if (EC)
return llvm::errorCodeToError(EC);
}
- // Make sure the out stream file gets removed if we crash.
- if (RemoveFileOnSignal)
- llvm::sys::RemoveFileOnSignal(*OSFile);
-
// Add the output file -- but don't try to remove "-", since this means we are
// using stdin.
OutputFiles.emplace_back(((OutputPath != "-") ? OutputPath : "").str(),
- std::move(TempFile));
+ std::move(Temp));
if (!Binary || OS->supportsSeeking())
return std::move(OS);
@@ -878,51 +945,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (!Act.PrepareToExecute(*this))
return false;
- // Create the target instance.
- setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
- getInvocation().TargetOpts));
- if (!hasTarget())
+ if (!createTarget())
return false;
- // Create TargetInfo for the other side of CUDA/OpenMP/SYCL compilation.
- if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
- getLangOpts().SYCLIsDevice) &&
- !getFrontendOpts().AuxTriple.empty()) {
- auto TO = std::make_shared<TargetOptions>();
- TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
- if (getFrontendOpts().AuxTargetCPU)
- TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
- if (getFrontendOpts().AuxTargetFeatures)
- TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
- TO->HostTriple = getTarget().getTriple().str();
- setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
- }
-
- if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
- if (getLangOpts().getFPRoundingMode() !=
- llvm::RoundingMode::NearestTiesToEven) {
- getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
- getLangOpts().setFPRoundingMode(llvm::RoundingMode::NearestTiesToEven);
- }
- if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) {
- getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
- getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
- }
- // FIXME: can we disable FEnvAccess?
- }
-
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- getTarget().adjust(getLangOpts());
-
- // Adjust target options based on codegen options.
- getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
-
- if (auto *Aux = getAuxTarget())
- getTarget().setAuxTarget(Aux);
-
// rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
getTarget().noSignedCharForObjCBool();
@@ -992,7 +1017,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (!StatsFile.empty()) {
std::error_code EC;
auto StatS = std::make_unique<llvm::raw_fd_ostream>(
- StatsFile, EC, llvm::sys::fs::OF_Text);
+ StatsFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
<< StatsFile << EC.message();
@@ -1029,6 +1054,15 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
[](CompilerInstance &) {}) {
llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
+ // Never compile a module that's already finalized - this would cause the
+ // existing module to be freed, causing crashes if it is later referenced
+ if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) {
+ ImportingInstance.getDiagnostics().Report(
+ ImportLoc, diag::err_module_rebuild_finalized)
+ << ModuleName;
+ return false;
+ }
+
// Construct a compiler invocation for creating this module.
auto Invocation =
std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
@@ -1144,7 +1178,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
// module generation thread crashed.
Instance.clearOutputFiles(/*EraseFiles=*/true);
- return !Instance.getDiagnostics().hasErrorOccurred();
+ // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
+ // occurred.
+ return !Instance.getDiagnostics().hasErrorOccurred() ||
+ Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
}
static const FileEntry *getPublicModuleMap(const FileEntry *File,
@@ -1664,9 +1701,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
// We can't find a module, error out here.
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
<< ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
if (ModuleFilename.empty()) {
if (M && M->HasIncompatibleModuleFile) {
@@ -1677,9 +1712,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
<< ModuleName;
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Create an ASTReader on demand.
@@ -1697,7 +1730,8 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
// Try to load the module file. If we are not trying to load from the
// module cache, we don't know how to rebuild modules.
unsigned ARRFlags = Source == MS_ModuleCache
- ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing
+ ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing |
+ ASTReader::ARR_TreatModuleWithErrorsAsOutOfDate
: Source == MS_PrebuiltModulePath
? 0
: ASTReader::ARR_ConfigurationMismatch;
@@ -1724,7 +1758,6 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
if (*ModuleFile == M->getASTFile())
return M;
- ModuleBuildFailed = true;
getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
<< ModuleName;
return ModuleLoadResult();
@@ -1746,14 +1779,12 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
LLVM_FALLTHROUGH;
case ASTReader::VersionMismatch:
case ASTReader::HadErrors:
- // FIXME: Should this set ModuleBuildFailed = true?
ModuleLoader::HadFatalFailure = true;
// FIXME: The ASTReader will already have complained, but can we shoehorn
// that diagnostic information into a more useful form?
return ModuleLoadResult();
case ASTReader::Failure:
- // FIXME: Should this set ModuleBuildFailed = true?
ModuleLoader::HadFatalFailure = true;
return ModuleLoadResult();
}
@@ -1763,7 +1794,6 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
// We don't know the desired configuration for this module and don't
// necessarily even have a module map. Since ReadAST already produces
// diagnostics for these two cases, we simply error out here.
- ModuleBuildFailed = true;
return ModuleLoadResult();
}
@@ -1788,9 +1818,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
<< ModuleName << CyclePath;
- // FIXME: Should this set ModuleBuildFailed = true?
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Check whether we have already attempted to build this module (but
@@ -1799,9 +1827,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
<< ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Try to compile and then read the AST.
@@ -1811,9 +1837,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
"undiagnosed error in compileModuleAndReadAST");
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Okay, we've rebuilt and now loaded the module.
@@ -1856,22 +1880,19 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
//if (Module == nullptr) {
// getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
// << ModuleName;
- // ModuleBuildFailed = true;
+ // DisableGeneratingGlobalModuleIndex = true;
// return ModuleLoadResult();
//}
MM.cacheModuleLoad(*Path[0].first, Module);
} else {
ModuleLoadResult Result = findOrCompileModuleAndReadAST(
ModuleName, ImportLoc, ModuleNameLoc, IsInclusionDirective);
- // FIXME: Can we pull 'ModuleBuildFailed = true' out of the return
- // sequences for findOrCompileModuleAndReadAST and do it here (as long as
- // the result is not a config mismatch)? See FIXMEs there.
if (!Result.isNormal())
return Result;
+ if (!Result)
+ DisableGeneratingGlobalModuleIndex = true;
Module = Result;
MM.cacheModuleLoad(*Path[0].first, Module);
- if (!Module)
- return Module;
}
// If we never found the module, fail. Otherwise, verify the module and link