diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticFrontendKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Basic/Module.h | 16 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/Module.framework/Headers/NotInModule.h | 1 | ||||
-rw-r--r-- | clang/test/Modules/auto-module-import.m | 9 |
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; +} |