summaryrefslogtreecommitdiffstats
path: root/include/clang/Lex
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2018-01-05 02:33:18 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2018-01-05 02:33:18 +0000
commit0b1c4572180545492c8054f21904e38bc3e5f575 (patch)
treeed7f670972811ad82cb062662c41ebf7e2ddafb7 /include/clang/Lex
parent30940fe1ee6e7de897e4f8353561e1fe41a0e3e9 (diff)
Reapply r321781: [Modules] Allow modules specified by -fmodule-map-file to shadow implicitly found ones
When modules come from module map files explicitly specified by -fmodule-map-file= arguments, allow those to override/shadow modules with the same name that are found implicitly by header search. If such a module is looked up by name (e.g. @import), we will always find the one from -fmodule-map-file. If we try to use a shadowed module by including one of its headers report an error. This enables developers to force use of a specific copy of their module to be used if there are multiple copies that would otherwise be visible, for example if they develop modules that are installed in the default search paths. Patch originally by Ben Langmuir, http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151116/143425.html Based on cfe-dev discussion: http://lists.llvm.org/pipermail/cfe-dev/2015-November/046164.html Differential Revision: https://reviews.llvm.org/D31269 rdar://problem/23612102 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321855 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Lex')
-rw-r--r--include/clang/Lex/HeaderSearch.h1
-rw-r--r--include/clang/Lex/ModuleMap.h36
2 files changed, 32 insertions, 5 deletions
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 6b9dbfcd1e..73a5af1913 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -726,6 +726,7 @@ private:
LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
bool IsSystem,
const DirectoryEntry *Dir,
+ bool IsExplicitlyProvided,
FileID ID = FileID(),
unsigned *Offset = nullptr);
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 41ed8e49b6..9632ca6ce2 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -98,6 +98,9 @@ class ModuleMap {
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
+ /// Shadow modules created while building this module map.
+ llvm::SmallVector<Module*, 2> ShadowModules;
+
/// \brief The number of modules we have created in total.
unsigned NumCreatedModules = 0;
@@ -195,6 +198,17 @@ private:
/// header.
llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
+ /// \brief The set of modules provided explicitly (e.g. by -fmodule-map-file),
+ /// which are allowed to shadow other implicitly discovered modules.
+ llvm::DenseSet<const Module *> ExplicitlyProvidedModules;
+
+ bool mayShadowModuleBeingParsed(Module *ExistingModule,
+ bool IsExplicitlyProvided) {
+ assert(!ExistingModule->Parent && "expected top-level module");
+ return !IsExplicitlyProvided &&
+ ExplicitlyProvidedModules.count(ExistingModule);
+ }
+
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
/// \brief Whether this is a system module.
@@ -475,9 +489,9 @@ public:
///
/// \returns The found or newly-created module, along with a boolean value
/// that will be true if the module is newly-created.
- std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
- bool IsFramework,
- bool IsExplicit);
+ std::pair<Module *, bool>
+ findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
+ bool IsExplicit, bool UsesExplicitModuleMapFile = false);
/// \brief Create a 'global module' for a C++ Modules TS module interface
/// unit.
@@ -502,6 +516,11 @@ public:
Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
bool IsSystem, Module *Parent);
+ /// \brief Create a new top-level module that is shadowed by
+ /// \p ShadowingModule.
+ Module *createShadowedModule(StringRef Name, bool IsFramework,
+ Module *ShadowingModule);
+
/// \brief Retrieve the module map file containing the definition of the given
/// module.
///
@@ -587,6 +606,8 @@ public:
/// \brief Marks this header as being excluded from the given module.
void excludeHeader(Module *Mod, Module::Header Header);
+ void setExplicitlyProvided(Module *Mod);
+
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
@@ -606,10 +627,15 @@ public:
/// \param ExternModuleLoc The location of the "extern module" declaration
/// that caused us to load this module map file, if any.
///
+ /// \param IsExplicitlyProvided Whether this module map file was provided
+ /// explicitly by the user (e.g. -fmodule-map-file), rather than found
+ /// implicitly.
+ ///
/// \returns true if an error occurred, false otherwise.
bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *HomeDir, FileID ID = FileID(),
- unsigned *Offset = nullptr,
+ const DirectoryEntry *HomeDir,
+ bool IsExplicitlyProvided = false,
+ FileID ID = FileID(), unsigned *Offset = nullptr,
SourceLocation ExternModuleLoc = SourceLocation());
/// \brief Dump the contents of the module map, for debugging purposes.