summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--clang/include/clang/Basic/Module.h16
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp18
-rw-r--r--clang/lib/Lex/PPDirectives.cpp7
-rw-r--r--clang/lib/Serialization/ASTReader.cpp1
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp1
-rw-r--r--clang/test/Modules/Inputs/Module.framework/Headers/NotInModule.h1
-rw-r--r--clang/test/Modules/auto-module-import.m9
9 files changed, 44 insertions, 12 deletions
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ceef843409c..5efba22529a 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -139,6 +139,8 @@ def err_missing_umbrella_header : Error<
def err_no_submodule : Error<"no submodule named %0 in module '%1'">;
def err_no_submodule_suggest : Error<
"no submodule named %0 in module '%1'; did you mean '%2'?">;
+def warn_missing_submodule : Warning<"missing submodule '%0'">,
+ InGroup<IncompleteUmbrella>;
def err_module_map_temp_file : Error<
"unable to write temporary module map file '%0'">, DefaultFatal;
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index d9c078f8806..bb88d48b38f 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -88,6 +88,7 @@ def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types">;
+def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index aef2db0feda..96b716e0cee 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -58,6 +58,9 @@ public:
/// \brief The headers that are part of this module.
llvm::SmallVector<const FileEntry *, 2> Headers;
+ /// \brief Whether this module was loaded from a module file.
+ unsigned IsFromModuleFile : 1;
+
/// \brief Whether this is a framework module.
unsigned IsFramework : 1;
@@ -131,17 +134,18 @@ public:
explicit Module(StringRef Name, SourceLocation DefinitionLoc,
bool IsFramework)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(),
- IsFramework(IsFramework), IsExplicit(false), InferSubmodules(false),
- InferExplicitSubmodules(false), InferExportWildcard(false),
- NameVisibility(Hidden) { }
+ IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(false),
+ InferSubmodules(false), InferExplicitSubmodules(false),
+ InferExportWildcard(false), NameVisibility(Hidden) { }
/// \brief Construct a new module or submodule.
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
- Umbrella(), IsFramework(IsFramework), IsExplicit(IsExplicit),
- InferSubmodules(false), InferExplicitSubmodules(false),
- InferExportWildcard(false),NameVisibility(Hidden) { }
+ Umbrella(), IsFromModuleFile(false), IsFramework(IsFramework),
+ IsExplicit(IsExplicit), InferSubmodules(false),
+ InferExplicitSubmodules(false), InferExportWildcard(false),
+ NameVisibility(Hidden) { }
~Module();
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 66238d0fc9f..12d368501ce 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1270,9 +1270,23 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
// Make the named module visible, if it's not already part of the module
// we are parsing.
- if (ModuleName != getLangOpts().CurrentModule)
+ if (ModuleName != getLangOpts().CurrentModule) {
+ if (!Module->IsFromModuleFile) {
+ // We have an umbrella header or directory that doesn't actually include
+ // all of the headers within the directory it covers. Complain about
+ // this missing submodule and recover by forgetting that we ever saw
+ // this submodule.
+ // FIXME: Should we detect this at module load time? It seems fairly
+ // expensive (and rare).
+ getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
+ << Module->getFullModuleName()
+ << SourceRange(Path.front().second, Path.back().second);
+
+ return 0;
+ }
ModuleManager->makeModuleVisible(Module, Visibility);
-
+ }
+
// If this module import was due to an inclusion directive, create an
// implicit import declaration to capture it in the AST.
if (IsInclusionDirective && hasASTContext()) {
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 7c8bfd7e7cd..4d700aef03b 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -1388,11 +1388,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If this was an #__include_macros directive, only make macros visible.
Module::NameVisibilityKind Visibility
= (IncludeKind == 3)? Module::MacrosVisible : Module::AllVisible;
- TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
- /*IsIncludeDirective=*/true);
+ Module *Imported
+ = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
+ /*IsIncludeDirective=*/true);
// If this header isn't part of the module we're building, we're done.
- if (!BuildingImportedModule)
+ if (!BuildingImportedModule && Imported)
return;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 1efc95408b3..9fc2962d27c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -3086,6 +3086,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
return Failure;
}
+ CurrentModule->IsFromModuleFile = true;
CurrentModule->InferSubmodules = InferSubmodules;
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
CurrentModule->InferExportWildcard = InferExportWildcard;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1776b97bb03..6883dbe3294 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1877,7 +1877,6 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
for (ASTContext::import_iterator I = Context->local_import_begin(),
IEnd = Context->local_import_end();
I != IEnd; ++I) {
- assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
if (Module *ImportedFrom
= ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),
SrcMgr))) {
diff --git a/clang/test/Modules/Inputs/Module.framework/Headers/NotInModule.h b/clang/test/Modules/Inputs/Module.framework/Headers/NotInModule.h
new file mode 100644
index 00000000000..6b15791eb2c
--- /dev/null
+++ b/clang/test/Modules/Inputs/Module.framework/Headers/NotInModule.h
@@ -0,0 +1 @@
+int not_in_module;
diff --git a/clang/test/Modules/auto-module-import.m b/clang/test/Modules/auto-module-import.m
index 21e79687610..d14f9e90304 100644
--- a/clang/test/Modules/auto-module-import.m
+++ b/clang/test/Modules/auto-module-import.m
@@ -62,3 +62,12 @@ int getModulePrivate() { return module_private; }
int getNoUmbrellaAPrivate() { return no_umbrella_A_private; }
int getNoUmbrellaBPrivateFail() { return no_umbrella_B_private; } // expected-error{{use of undeclared identifier 'no_umbrella_B_private'; did you mean 'no_umbrella_A_private'?}}
+
+// Test inclusion of headers that are under an umbrella directory but
+// not actually part of the module.
+#include <Module/NotInModule.h> // expected-warning{{treating #include as an import of module 'Module.NotInModule'}} \
+ // expected-warning{{missing submodule 'Module.NotInModule'}}
+
+int getNotInModule() {
+ return not_in_module;
+}
OpenPOWER on IntegriCloud