aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-11-29 23:55:25 +0000
committerDouglas Gregor <dgregor@apple.com>2012-11-29 23:55:25 +0000
commit463d90986ec54c62bf8fe31193ef5db701db48a5 (patch)
tree70dae4bd00311bdd08f2e1f4007c7042375dea12 /include/clang
parentdb748a380ab89b1c0b6e751e55291f57605cccce (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.h9
-rw-r--r--include/clang/Frontend/CompilerInstance.h11
-rw-r--r--include/clang/Lex/ModuleLoader.h32
-rw-r--r--include/clang/Lex/PreprocessorOptions.h23
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