diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-12-01 12:32:12 +0000 |
commit | fbc266465ed3585efdbd8e9ebf71e97ce7e8b464 (patch) | |
tree | 7560c2cbec09e542e5f2e2100ffc16ca742b1075 /contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp | |
parent | ac8517f04c0fe31968ed43e36608ad02d72d3597 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp | 148 |
1 files changed, 96 insertions, 52 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp index a25aa88bd85e..6242b5a7d9fe 100644 --- a/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInstance.cpp @@ -411,8 +411,7 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags, SourceMgr.overrideFileContents(FromFile, RB.second->getMemBufferRef()); else SourceMgr.overrideFileContents( - FromFile, std::unique_ptr<llvm::MemoryBuffer>( - const_cast<llvm::MemoryBuffer *>(RB.second))); + FromFile, std::unique_ptr<llvm::MemoryBuffer>(RB.second)); } // Remap files in the source manager (with other files). @@ -1047,6 +1046,11 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty()) llvm::EnableStatistics(false); + // Sort vectors containing toc data and no toc data variables to facilitate + // binary search later. + llvm::sort(getCodeGenOpts().TocDataVarsUserSpecified); + llvm::sort(getCodeGenOpts().NoTocDataVars); + for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) { // Reset the ID tables if we are reusing the SourceManager and parsing // regular files. @@ -1061,30 +1065,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { } } - if (getDiagnosticOpts().ShowCarets) { - // We can have multiple diagnostics sharing one diagnostic client. - // Get the total number of warnings/errors from the client. - unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); - unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); - - if (NumWarnings) - OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); - if (NumWarnings && NumErrors) - OS << " and "; - if (NumErrors) - OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); - if (NumWarnings || NumErrors) { - OS << " generated"; - if (getLangOpts().CUDA) { - if (!getLangOpts().CUDAIsDevice) { - OS << " when compiling for host"; - } else { - OS << " when compiling for " << getTargetOpts().CPU; - } - } - OS << ".\n"; - } - } + printDiagnosticStats(); if (getFrontendOpts().ShowStats) { if (hasFileManager()) { @@ -1112,6 +1093,36 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { return !getDiagnostics().getClient()->getNumErrors(); } +void CompilerInstance::printDiagnosticStats() { + if (!getDiagnosticOpts().ShowCarets) + return; + + raw_ostream &OS = getVerboseOutputStream(); + + // We can have multiple diagnostics sharing one diagnostic client. + // Get the total number of warnings/errors from the client. + unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); + unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); + + if (NumWarnings) + OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); + if (NumWarnings && NumErrors) + OS << " and "; + if (NumErrors) + OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); + if (NumWarnings || NumErrors) { + OS << " generated"; + if (getLangOpts().CUDA) { + if (!getLangOpts().CUDAIsDevice) { + OS << " when compiling for host"; + } else { + OS << " when compiling for " << getTargetOpts().CPU; + } + } + OS << ".\n"; + } +} + void CompilerInstance::LoadRequestedPlugins() { // Load any requested plugins. for (const std::string &Path : getFrontendOpts().Plugins) { @@ -1194,16 +1205,6 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, // Note the name of the module we're building. Invocation->getLangOpts().CurrentModule = std::string(ModuleName); - // Make sure that the failed-module structure has been allocated in - // the importing instance, and propagate the pointer to the newly-created - // instance. - PreprocessorOptions &ImportingPPOpts - = ImportingInstance.getInvocation().getPreprocessorOpts(); - if (!ImportingPPOpts.FailedModules) - ImportingPPOpts.FailedModules = - std::make_shared<PreprocessorOptions::FailedModulesSet>(); - PPOpts.FailedModules = ImportingPPOpts.FailedModules; - // If there is a module map file, build the module using the module map. // Set up the inputs/outputs so that we build the module from its umbrella // header. @@ -1257,6 +1258,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, SourceMgr.pushModuleBuildStack(ModuleName, FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Make sure that the failed-module structure has been allocated in + // the importing instance, and propagate the pointer to the newly-created + // instance. + if (!ImportingInstance.hasFailedModulesSet()) + ImportingInstance.createFailedModulesSet(); + Instance.setFailedModulesSet(ImportingInstance.getFailedModulesSetPtr()); + // If we're collecting module dependencies, we need to share a collector // between all of the module CompilerInstances. Other than that, we don't // want to produce any dependency output from the module build. @@ -1284,6 +1292,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, diag::remark_module_build_done) << ModuleName; + // Propagate the statistics to the parent FileManager. + if (!FrontendOpts.ModulesShareFileManager) + ImportingInstance.getFileManager().AddStats(Instance.getFileManager()); + if (Crashed) { // Clear the ASTConsumer if it hasn't been already, in case it owns streams // that must be closed before clearing output files. @@ -1325,9 +1337,24 @@ static bool compileModule(CompilerInstance &ImportingInstance, // Get or create the module map that we'll use to build this module. ModuleMap &ModMap = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + SourceManager &SourceMgr = ImportingInstance.getSourceManager(); bool Result; - if (OptionalFileEntryRef ModuleMapFile = - ModMap.getContainingModuleMapFile(Module)) { + if (FileID ModuleMapFID = ModMap.getContainingModuleMapFileID(Module); + ModuleMapFID.isValid()) { + // We want to use the top-level module map. If we don't, the compiling + // instance may think the containing module map is a top-level one, while + // the importing instance knows it's included from a parent module map via + // the extern directive. This mismatch could bite us later. + SourceLocation Loc = SourceMgr.getIncludeLoc(ModuleMapFID); + while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) { + ModuleMapFID = SourceMgr.getFileID(Loc); + Loc = SourceMgr.getIncludeLoc(ModuleMapFID); + } + + OptionalFileEntryRef ModuleMapFile = + SourceMgr.getFileEntryRefForID(ModuleMapFID); + assert(ModuleMapFile && "Top-level module map with no FileID"); + // Canonicalize compilation to start with the public module map. This is // vital for submodules declarations in the private module maps to be // correctly parsed when depending on a top level module in the public one. @@ -1584,6 +1611,14 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, } } +static void checkConfigMacros(Preprocessor &PP, Module *M, + SourceLocation ImportLoc) { + clang::Module *TopModule = M->getTopLevelModule(); + for (const StringRef ConMacro : TopModule->ConfigMacros) { + checkConfigMacro(PP, ConMacro, M, ImportLoc); + } +} + /// Write a new timestamp file with the given path. static void writeTimestampFile(StringRef TimestampFile) { std::error_code EC; @@ -1822,6 +1857,13 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( Module *M = HS.lookupModule(ModuleName, ImportLoc, true, !IsInclusionDirective); + // Check for any configuration macros that have changed. This is done + // immediately before potentially building a module in case this module + // depends on having one of its configuration macros defined to successfully + // build. If this is not done the user will never see the warning. + if (M) + checkConfigMacros(getPreprocessor(), M, ImportLoc); + // Select the source and filename for loading the named module. std::string ModuleFilename; ModuleSource Source = @@ -1950,10 +1992,8 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( return nullptr; } - // Check whether we have already attempted to build this module (but - // failed). - if (getPreprocessorOpts().FailedModules && - getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { + // Check whether we have already attempted to build this module (but failed). + if (FailedModules && FailedModules->hasAlreadyFailed(ModuleName)) { getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); return nullptr; @@ -1964,8 +2004,8 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( ModuleFilename)) { assert(getDiagnostics().hasErrorOccurred() && "undiagnosed error in compileModuleAndReadAST"); - if (getPreprocessorOpts().FailedModules) - getPreprocessorOpts().FailedModules->addFailed(ModuleName); + if (FailedModules) + FailedModules->addFailed(ModuleName); return nullptr; } @@ -1999,12 +2039,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) { // Use the cached result, which may be nullptr. Module = *MaybeModule; + // Config macros are already checked before building a module, but they need + // to be checked at each import location in case any of the config macros + // have a new value at the current `ImportLoc`. + if (Module) + checkConfigMacros(getPreprocessor(), Module, ImportLoc); } else if (ModuleName == getLangOpts().CurrentModule) { // This is the module we're building. Module = PP->getHeaderSearchInfo().lookupModule( ModuleName, ImportLoc, /*AllowSearch*/ true, /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); + // Config macros do not need to be checked here for two reasons. + // * This will always be textual inclusion, and thus the config macros + // actually do impact the content of the header. + // * `Preprocessor::HandleHeaderIncludeOrImport` will never call this + // function as the `#include` or `#import` is textual. + MM.cacheModuleLoad(*Path[0].first, Module); } else { ModuleLoadResult Result = findOrCompileModuleAndReadAST( @@ -2139,18 +2190,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, TheASTReader->makeModuleVisible(Module, Visibility, ImportLoc); } - // Check for any configuration macros that have changed. - clang::Module *TopModule = Module->getTopLevelModule(); - for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) { - checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I], - Module, ImportLoc); - } - // Resolve any remaining module using export_as for this one. getPreprocessor() .getHeaderSearchInfo() .getModuleMap() - .resolveLinkAsDependencies(TopModule); + .resolveLinkAsDependencies(Module->getTopLevelModule()); LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(Module); |