diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-11-29 23:55:25 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-11-29 23:55:25 +0000 |
commit | 463d90986ec54c62bf8fe31193ef5db701db48a5 (patch) | |
tree | 70dae4bd00311bdd08f2e1f4007c7042375dea12 /include/clang | |
parent | db748a380ab89b1c0b6e751e55291f57605cccce (diff) |
Keep track of modules that have failed to build. If we encounter an
import of that module elsewhere, don't try to build the module again:
it won't work, and the experience is quite dreadful. We track this
information somewhat globally, shared among all of the related
CompilerInvocations used to build modules on-the-fly, so that a
particular Clang instance will only try to build a given module once.
Fixes <rdar://problem/12552849>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168961 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 9 | ||||
-rw-r--r-- | include/clang/Frontend/CompilerInstance.h | 11 | ||||
-rw-r--r-- | include/clang/Lex/ModuleLoader.h | 32 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorOptions.h | 23 |
4 files changed, 61 insertions, 14 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 5e409bd7ed..ac9a0461b8 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -830,11 +830,12 @@ public: /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) { + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) { // ASTUnit doesn't know how to load modules (not that this matters). - return 0; + return ModuleLoadResult(); } }; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 2f3dc3f808..2861511dd1 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -94,7 +94,7 @@ class CompilerInstance : public ModuleLoader { /// \brief The semantic analysis object. OwningPtr<Sema> TheSema; - + /// \brief The frontend timer OwningPtr<llvm::Timer> FrontendTimer; @@ -111,7 +111,7 @@ class CompilerInstance : public ModuleLoader { /// \brief The result of the last module import. /// - Module *LastModuleImportResult; + ModuleLoadResult LastModuleImportResult; /// \brief Holds information about the output file. /// @@ -645,9 +645,10 @@ public: /// } - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective); + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective); }; } // end namespace clang diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 36d03c0aa2..3a5f41d510 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -17,16 +17,37 @@ #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" namespace clang { class IdentifierInfo; - +class Module; + /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > ModuleIdPath; - + +/// \brief Describes the result of attempting to load a module. +class ModuleLoadResult { + llvm::PointerIntPair<Module *, 1, bool> Storage; + +public: + ModuleLoadResult() : Storage() { } + + ModuleLoadResult(Module *module, bool missingExpected) + : Storage(module, missingExpected) { } + + operator Module *() const { return Storage.getPointer(); } + + /// \brief Determines whether the module, which failed to load, was + /// actually a submodule that we expected to see (based on implying the + /// submodule from header structure), but didn't materialize in the actual + /// module. + bool isMissingExpected() const { return Storage.getInt(); } +}; + /// \brief Abstract interface for a module loader. /// /// This abstract interface describes a module loader, which is responsible @@ -55,9 +76,10 @@ public: /// /// \returns If successful, returns the loaded module. Otherwise, returns /// NULL to indicate that the module could not be loaded. - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) = 0; + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; }; } diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index e5fe373793..857161ddc0 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -13,6 +13,7 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include <cassert> #include <string> #include <utility> @@ -126,7 +127,29 @@ public: /// to do so (e.g., if on-demand module construction moves out-of-process), /// we can add a cc1-level option to do so. SmallVector<std::string, 2> ModuleBuildPath; + + /// \brief Records the set of modules + class FailedModulesSet : public llvm::RefCountedBase<FailedModulesSet> { + llvm::StringSet<> Failed; + + public: + bool hasAlreadyFailed(StringRef module) { + return Failed.count(module) > 0; + } + + void addFailed(StringRef module) { + Failed.insert(module); + } + }; + /// \brief The set of modules that failed to build. + /// + /// This pointer will be shared among all of the compiler instances created + /// to (re)build modules, so that once a module fails to build anywhere, + /// other instances will see that the module has failed and won't try to + /// build it again. + llvm::IntrusiveRefCntPtr<FailedModulesSet> FailedModules; + typedef std::vector<std::pair<std::string, std::string> >::iterator remapped_file_iterator; typedef std::vector<std::pair<std::string, std::string> >::const_iterator |