diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/ASTMerge.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 58 | ||||
-rw-r--r-- | lib/Frontend/ChainedIncludesSource.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 388 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 59 | ||||
-rw-r--r-- | lib/Frontend/DependencyFile.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/DiagnosticRenderer.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/FrontendAction.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 131 | ||||
-rw-r--r-- | lib/Frontend/FrontendOptions.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 9 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/LogDiagnosticPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 91 | ||||
-rw-r--r-- | lib/Frontend/SerializedDiagnosticPrinter.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnostic.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticBuffer.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/VerifyDiagnosticConsumer.cpp | 90 |
20 files changed, 657 insertions, 238 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 936bd2f8a4..4a63d76a73 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -463,6 +463,10 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "<class template> " << *CTD << '\n'; break; } + case Decl::OMPThreadPrivate: { + Out << "<omp threadprivate> " << '"' << *I << "\"\n"; + break; + } default: Out << "DeclKind: " << DK << '"' << *I << "\"\n"; llvm_unreachable("decl unhandled"); diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index bfb30836d8..b6c644eba7 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -34,7 +34,7 @@ bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, void ASTMergeAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); CI.getDiagnostics().getClient()->BeginSourceFile( - CI.getASTContext().getLangOpts()); + CI.getASTContext().getLangOpts()); CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &CI.getASTContext()); IntrusiveRefCntPtr<DiagnosticIDs> @@ -42,8 +42,9 @@ void ASTMergeAction::ExecuteAction() { for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { IntrusiveRefCntPtr<DiagnosticsEngine> Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), - CI.getDiagnostics().getClient(), - /*ShouldOwnClient=*/false)); + new ForwardingDiagnosticConsumer( + *CI.getDiagnostics().getClient()), + /*ShouldOwnClient=*/true)); ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, CI.getFileSystemOpts(), false); if (!Unit) diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 4a956ff3ab..8bd5172454 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -236,6 +236,11 @@ ASTUnit::ASTUnit(bool _MainFileIsAST) } ASTUnit::~ASTUnit() { + // If we loaded from an AST file, balance out the BeginSourceFile call. + if (MainFileIsAST && getDiagnostics().getClient()) { + getDiagnostics().getClient()->EndSourceFile(); + } + clearFileLevelDecls(); // Clean up the temporary files and the preamble file. @@ -581,25 +586,24 @@ private: } }; + /// \brief Diagnostic consumer that saves each diagnostic it is given. class StoredDiagnosticConsumer : public DiagnosticConsumer { SmallVectorImpl<StoredDiagnostic> &StoredDiags; - + SourceManager *SourceMgr; + public: explicit StoredDiagnosticConsumer( SmallVectorImpl<StoredDiagnostic> &StoredDiags) - : StoredDiags(StoredDiags) { } - + : StoredDiags(StoredDiags), SourceMgr(0) { } + + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP = 0) { + if (PP) + SourceMgr = &PP->getSourceManager(); + } + virtual void HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); - - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { - // Just drop any diagnostics that come from cloned consumers; they'll - // have different source managers anyway. - // FIXME: We'd like to be able to capture these somehow, even if it's just - // file/line/column, because they could occur when parsing module maps or - // building modules on-demand. - return new IgnoringDiagConsumer(); - } }; /// \brief RAII object that optionally captures diagnostics, if @@ -635,7 +639,11 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(Level, Info); - StoredDiags.push_back(StoredDiagnostic(Level, Info)); + // Only record the diagnostic if it's part of the source manager we know + // about. This effectively drops diagnostics from modules we're building. + // FIXME: In the long run, ee don't want to drop source managers from modules. + if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) + StoredDiags.push_back(StoredDiagnostic(Level, Info)); } ASTDeserializationListener *ASTUnit::getDeserializationListener() { @@ -662,8 +670,7 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags, Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics); Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(), Client, - /*ShouldOwnClient=*/true, - /*ShouldCloneClient=*/false); + /*ShouldOwnClient=*/true); } else if (CaptureDiagnostics) { Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics)); } @@ -801,6 +808,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, break; case ASTReader::Failure: + case ASTReader::Missing: case ASTReader::OutOfDate: case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: @@ -834,6 +842,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, ReaderPtr->InitializeSema(*AST->TheSema); AST->Reader = ReaderPtr; + // Tell the diagnostic client that we have started a source file. + AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP); + return AST.take(); } @@ -1026,16 +1037,17 @@ public: } -static void checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> & - StoredDiagnostics) { +static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) { + return StoredDiag.getLocation().isValid(); +} + +static void +checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) { // Get rid of stored diagnostics except the ones from the driver which do not // have a source location. - for (unsigned I = 0; I < StoredDiagnostics.size(); ++I) { - if (StoredDiagnostics[I].getLocation().isValid()) { - StoredDiagnostics.erase(StoredDiagnostics.begin()+I); - --I; - } - } + StoredDiags.erase( + std::remove_if(StoredDiags.begin(), StoredDiags.end(), isNonDriverDiag), + StoredDiags.end()); } static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp index f414f93812..cde84caade 100644 --- a/lib/Frontend/ChainedIncludesSource.cpp +++ b/lib/Frontend/ChainedIncludesSource.cpp @@ -47,6 +47,7 @@ static ASTReader *createASTReader(CompilerInstance &CI, return Reader.take(); case ASTReader::Failure: + case ASTReader::Missing: case ASTReader::OutOfDate: case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: @@ -112,8 +113,6 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { OwningPtr<ASTConsumer> consumer; consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0, /*isysroot=*/"", &OS)); - Clang->getPreprocessor().setPPMutationListener( - consumer->GetPPMutationListener()); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(consumer.take()); @@ -144,6 +143,7 @@ ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { Clang->getASTConsumer().GetASTDeserializationListener())); if (!Reader) return 0; + Clang->setModuleManager(static_cast<ASTReader*>(Reader.get())); Clang->getASTContext().setExternalSource(Reader); } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index ce6572aa1b..cf856fc2ab 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -44,6 +44,8 @@ #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" +#include <sys/stat.h> +#include <time.h> using namespace clang; @@ -62,7 +64,8 @@ void CompilerInstance::setInvocation(CompilerInvocation *Value) { bool CompilerInstance::shouldBuildGlobalModuleIndex() const { return (BuildGlobalModuleIndex || - (ModuleManager && ModuleManager->isGlobalIndexUnavailable())) && + (ModuleManager && ModuleManager->isGlobalIndexUnavailable() && + getFrontendOpts().GenerateGlobalModuleIndex)) && !ModuleBuildFailed; } @@ -152,18 +155,15 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, } void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client, - bool ShouldOwnClient, - bool ShouldCloneClient) { + bool ShouldOwnClient) { Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client, - ShouldOwnClient, ShouldCloneClient, - &getCodeGenOpts()); + ShouldOwnClient, &getCodeGenOpts()); } IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, DiagnosticConsumer *Client, bool ShouldOwnClient, - bool ShouldCloneClient, const CodeGenOptions *CodeGenOpts) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> @@ -172,10 +172,7 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, // Create the diagnostic client for reporting errors or for // implementing -verify. if (Client) { - if (ShouldCloneClient) - Diags->setClient(Client->clone(*Diags), ShouldOwnClient); - else - Diags->setClient(Client, ShouldOwnClient); + Diags->setClient(Client, ShouldOwnClient); } else Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); @@ -338,6 +335,7 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path, // Unrecoverable failure: don't even try to process the input file. break; + case ASTReader::Missing: case ASTReader::OutOfDate: case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: @@ -864,9 +862,10 @@ static void compileModule(CompilerInstance &ImportingInstance, // module. CompilerInstance Instance; Instance.setInvocation(&*Invocation); - Instance.createDiagnostics(&ImportingInstance.getDiagnosticClient(), - /*ShouldOwnClient=*/true, - /*ShouldCloneClient=*/true); + + Instance.createDiagnostics(new ForwardingDiagnosticConsumer( + ImportingInstance.getDiagnosticClient()), + /*ShouldOwnClient=*/true); // Note that this module is part of the module build stack, so that we // can detect cycles in the module graph. @@ -888,6 +887,7 @@ static void compileModule(CompilerInstance &ImportingInstance, llvm::CrashRecoveryContext CRC; CompileModuleMapData Data = { Instance, CreateModuleAction }; CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); + // Delete the temporary module map file. // FIXME: Even though we're executing under crash protection, it would still @@ -904,6 +904,183 @@ static void compileModule(CompilerInstance &ImportingInstance, } } +/// \brief Diagnose differences between the current definition of the given +/// configuration macro and the definition provided on the command line. +static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, + Module *Mod, SourceLocation ImportLoc) { + IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro); + SourceManager &SourceMgr = PP.getSourceManager(); + + // If this identifier has never had a macro definition, then it could + // not have changed. + if (!Id->hadMacroDefinition()) + return; + + // If this identifier does not currently have a macro definition, + // check whether it had one on the command line. + if (!Id->hasMacroDefinition()) { + MacroDirective::DefInfo LatestDef = + PP.getMacroDirectiveHistory(Id)->getDefinition(); + for (MacroDirective::DefInfo Def = LatestDef; Def; + Def = Def.getPreviousDefinition()) { + FileID FID = SourceMgr.getFileID(Def.getLocation()); + if (FID.isInvalid()) + continue; + + // We only care about the predefines buffer. + if (FID != PP.getPredefinesFileID()) + continue; + + // This macro was defined on the command line, then #undef'd later. + // Complain. + PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) + << true << ConfigMacro << Mod->getFullModuleName(); + if (LatestDef.isUndefined()) + PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here) + << true; + return; + } + + // Okay: no definition in the predefines buffer. + return; + } + + // This identifier has a macro definition. Check whether we had a definition + // on the command line. + MacroDirective::DefInfo LatestDef = + PP.getMacroDirectiveHistory(Id)->getDefinition(); + MacroDirective::DefInfo PredefinedDef; + for (MacroDirective::DefInfo Def = LatestDef; Def; + Def = Def.getPreviousDefinition()) { + FileID FID = SourceMgr.getFileID(Def.getLocation()); + if (FID.isInvalid()) + continue; + + // We only care about the predefines buffer. + if (FID != PP.getPredefinesFileID()) + continue; + + PredefinedDef = Def; + break; + } + + // If there was no definition for this macro in the predefines buffer, + // complain. + if (!PredefinedDef || + (!PredefinedDef.getLocation().isValid() && + PredefinedDef.getUndefLocation().isValid())) { + PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) + << false << ConfigMacro << Mod->getFullModuleName(); + PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) + << false; + return; + } + + // If the current macro definition is the same as the predefined macro + // definition, it's okay. + if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() || + LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP, + /*Syntactically=*/true)) + return; + + // The macro definitions differ. + PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) + << false << ConfigMacro << Mod->getFullModuleName(); + PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here) + << false; +} + +/// \brief Write a new timestamp file with the given path. +static void writeTimestampFile(StringRef TimestampFile) { + std::string ErrorInfo; + llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo, + llvm::raw_fd_ostream::F_Binary); +} + +/// \brief Prune the module cache of modules that haven't been accessed in +/// a long time. +static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { + struct stat StatBuf; + llvm::SmallString<128> TimestampFile; + TimestampFile = HSOpts.ModuleCachePath; + llvm::sys::path::append(TimestampFile, "modules.timestamp"); + + // Try to stat() the timestamp file. + if (::stat(TimestampFile.c_str(), &StatBuf)) { + // If the timestamp file wasn't there, create one now. + if (errno == ENOENT) { + writeTimestampFile(TimestampFile); + } + return; + } + + // Check whether the time stamp is older than our pruning interval. + // If not, do nothing. + time_t TimeStampModTime = StatBuf.st_mtime; + time_t CurrentTime = time(0); + if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval)) + return; + + // Write a new timestamp file so that nobody else attempts to prune. + // There is a benign race condition here, if two Clang instances happen to + // notice at the same time that the timestamp is out-of-date. + writeTimestampFile(TimestampFile); + + // Walk the entire module cache, looking for unused module files and module + // indices. + llvm::error_code EC; + SmallString<128> ModuleCachePathNative; + llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative); + for (llvm::sys::fs::directory_iterator + 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) + continue; + + // Walk all of the files within this directory. + bool RemovedAllFiles = true; + for (llvm::sys::fs::directory_iterator File(Dir->path(), EC), FileEnd; + File != FileEnd && !EC; File.increment(EC)) { + // We only care about module and global module index files. + if (llvm::sys::path::extension(File->path()) != ".pcm" && + llvm::sys::path::filename(File->path()) != "modules.idx") { + RemovedAllFiles = false; + continue; + } + + // Look at this file. If we can't stat it, there's nothing interesting + // there. + if (::stat(File->path().c_str(), &StatBuf)) { + RemovedAllFiles = false; + continue; + } + + // If the file has been used recently enough, leave it there. + time_t FileAccessTime = StatBuf.st_atime; + if (CurrentTime - FileAccessTime <= + time_t(HSOpts.ModuleCachePruneAfter)) { + RemovedAllFiles = false; + continue; + } + + // Remove the file. + bool Existed; + if (llvm::sys::fs::remove(File->path(), Existed) || !Existed) { + RemovedAllFiles = false; + } + } + + // If we removed all of the files in the directory, remove the directory + // itself. + if (RemovedAllFiles) { + bool Existed; + llvm::sys::fs::remove(Dir->path(), Existed); + } + } +} + ModuleLoadResult CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleIdPath Path, @@ -916,7 +1093,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Make the named module visible. if (LastModuleImportResult) ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility, - ImportLoc); + ImportLoc, /*Complain=*/false); return LastModuleImportResult; } @@ -945,93 +1122,19 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } else ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName); - if (ModuleFileName.empty()) { - getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) - << ModuleName - << SourceRange(ImportLoc, ModuleNameLoc); - LastModuleImportLoc = ImportLoc; - LastModuleImportResult = ModuleLoadResult(); - return LastModuleImportResult; - } - - const FileEntry *ModuleFile - = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false, - /*CacheFailure=*/false); - bool BuildingModule = false; - if (!ModuleFile && Module) { - // The module is not cached, but we have a module map from which we can - // build the module. - - // Check whether there is a cycle in the module graph. - ModuleBuildStack Path = getSourceManager().getModuleBuildStack(); - ModuleBuildStack::iterator Pos = Path.begin(), PosEnd = Path.end(); - for (; Pos != PosEnd; ++Pos) { - if (Pos->first == ModuleName) - break; - } - - if (Pos != PosEnd) { - SmallString<256> CyclePath; - for (; Pos != PosEnd; ++Pos) { - CyclePath += Pos->first; - CyclePath += " -> "; - } - CyclePath += ModuleName; - - getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) - << ModuleName << CyclePath; - return ModuleLoadResult(); - } - - // Check whether we have already attempted to build this module (but - // failed). - if (getPreprocessorOpts().FailedModules && - getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { - getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) - << ModuleName - << SourceRange(ImportLoc, ModuleNameLoc); - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - BuildingModule = true; - compileModule(*this, ModuleNameLoc, Module, ModuleFileName); - ModuleFile = FileMgr->getFile(ModuleFileName, /*OpenFile=*/false, - /*CacheFailure=*/false); - - if (!ModuleFile && getPreprocessorOpts().FailedModules) - getPreprocessorOpts().FailedModules->addFailed(ModuleName); - } - - if (!ModuleFile) { - getDiagnostics().Report(ModuleNameLoc, - BuildingModule? diag::err_module_not_built - : diag::err_module_not_found) - << ModuleName - << SourceRange(ImportLoc, ModuleNameLoc); - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - - // If there is already a module file associated with this module, make sure - // it is the same as the module file we're looking for. Otherwise, we - // have two module files for the same module. - if (const FileEntry *CurModuleFile = Module? Module->getASTFile() : 0) { - if (CurModuleFile != ModuleFile) { - getDiagnostics().Report(ModuleNameLoc, diag::err_module_file_conflict) - << ModuleName - << CurModuleFile->getName() - << ModuleFile->getName(); - ModuleBuildFailed = true; - return ModuleLoadResult(); - } - } - // If we don't already have an ASTReader, create one now. if (!ModuleManager) { if (!hasASTContext()) createASTContext(); + // If we're not recursively building a module, check whether we + // need to prune the module cache. + if (getSourceManager().getModuleBuildStack().empty() && + getHeaderSearchOpts().ModuleCachePruneInterval > 0 && + getHeaderSearchOpts().ModuleCachePruneAfter > 0) { + pruneModuleCache(getHeaderSearchOpts()); + } + std::string Sysroot = getHeaderSearchOpts().Sysroot; const PreprocessorOptions &PPOpts = getPreprocessorOpts(); ModuleManager = new ASTReader(getPreprocessor(), *Context, @@ -1044,8 +1147,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, getASTConsumer().GetASTDeserializationListener()); getASTContext().setASTMutationListener( getASTConsumer().GetASTMutationListener()); - getPreprocessor().setPPMutationListener( - getASTConsumer().GetPPMutationListener()); } OwningPtr<ExternalASTSource> Source; Source.reset(ModuleManager); @@ -1056,21 +1157,53 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleManager->StartTranslationUnit(&getASTConsumer()); } - // Try to load the module we found. - unsigned ARRFlags = ASTReader::ARR_None; - if (Module) - ARRFlags |= ASTReader::ARR_OutOfDate; - switch (ModuleManager->ReadAST(ModuleFile->getName(), - serialization::MK_Module, ImportLoc, - ARRFlags)) { + // Try to load the module file. + unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing; + switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module, + ImportLoc, ARRFlags)) { case ASTReader::Success: break; case ASTReader::OutOfDate: { - // The module file is out-of-date. Rebuild it. - getFileManager().invalidateCache(ModuleFile); + // 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::Missing: { + // The module file is (now) missing. Build it. + + // If we don't have a module, we don't know how to build the module file. + // Complain and return. + if (!Module) { + getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) + << ModuleName + << SourceRange(ImportLoc, ModuleNameLoc); + ModuleBuildFailed = true; + return ModuleLoadResult(); + } + + // Check whether there is a cycle in the module graph. + ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack(); + ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end(); + for (; Pos != PosEnd; ++Pos) { + if (Pos->first == ModuleName) + break; + } + + if (Pos != PosEnd) { + SmallString<256> CyclePath; + for (; Pos != PosEnd; ++Pos) { + CyclePath += Pos->first; + CyclePath += " -> "; + } + CyclePath += ModuleName; + + getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle) + << ModuleName << CyclePath; + return ModuleLoadResult(); + } // Check whether we have already attempted to build this module (but // failed). @@ -1083,15 +1216,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return ModuleLoadResult(); } + // Try to compile the module. compileModule(*this, ModuleNameLoc, Module, ModuleFileName); - // Try loading the module again. - ModuleFile = FileMgr->getFile(ModuleFileName, /*OpenFile=*/false, - /*CacheFailure=*/false); - if (!ModuleFile || - ModuleManager->ReadAST(ModuleFileName, + // Try to read the module file, now that we've compiled it. + ASTReader::ASTReadResult ReadResult + = ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module, ImportLoc, - ASTReader::ARR_None) != ASTReader::Success) { + ASTReader::ARR_Missing); + if (ReadResult != ASTReader::Success) { + if (ReadResult == ASTReader::Missing) { + getDiagnostics().Report(ModuleNameLoc, + Module? diag::err_module_not_built + : diag::err_module_not_found) + << ModuleName + << SourceRange(ImportLoc, ModuleNameLoc); + } + if (getPreprocessorOpts().FailedModules) getPreprocessorOpts().FailedModules->addFailed(ModuleName); KnownModules[Path[0].first] = 0; @@ -1125,10 +1266,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, .findModule((Path[0].first->getName())); } - if (Module) { - Module->setASTFile(ModuleFile); - } - // Cache the result of this top-level module lookup for later. Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } @@ -1220,9 +1357,17 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, return ModuleLoadResult(); } - ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc); + ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc, + /*Complain=*/true); } - + + // 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); + } + // If this module import was due to an inclusion directive, create an // implicit import declaration to capture it in the AST. if (IsInclusionDirective && hasASTContext()) { @@ -1242,7 +1387,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, void CompilerInstance::makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc){ - ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc); + SourceLocation ImportLoc, + bool Complain){ + ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc, Complain); } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3c5954a696..42ea96f0f2 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" +#include "llvm/Support/system_error.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -68,6 +69,9 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, if (A->getOption().matches(options::OPT_O0)) return 0; + if (A->getOption().matches(options::OPT_Ofast)) + return 3; + assert (A->getOption().matches(options::OPT_O)); StringRef S(A->getValue()); @@ -80,8 +84,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, return DefaultOpt; } -static unsigned getOptimizationLevelSize(ArgList &Args, InputKind IK, - DiagnosticsEngine &Diags) { +static unsigned getOptimizationLevelSize(ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O)) { switch (A->getValue()[0]) { @@ -281,6 +284,7 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) { static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) { Opts.BlockCommandNames = Args.getAllArgValues(OPT_fcomment_block_commands); + Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments); } static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, @@ -317,23 +321,24 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); - Opts.ModulesAutolink = Args.hasArg(OPT_fmodules_autolink); Opts.DisableLLVMOpts = Args.hasArg(OPT |