r191283 - Module use declarations (II)
Daniel Jasper
djasper at google.com
Tue Sep 24 02:14:15 PDT 2013
Author: djasper
Date: Tue Sep 24 04:14:14 2013
New Revision: 191283
URL: http://llvm.org/viewvc/llvm-project?rev=191283&view=rev
Log:
Module use declarations (II)
Review: http://llvm-reviews.chandlerc.com/D1546.
I have picked up this patch form Lawrence
(http://llvm-reviews.chandlerc.com/D1063) and did a few changes.
>From the original change description (updated as appropriate):
This patch adds a check that ensures that modules only use modules they
have so declared. To this end, it adds a statement on intended module
use to the module.map grammar:
use module-id
A module can then only use headers from other modules if it 'uses' them.
This enforcement is off by default, but may be turned on with the new
option -fmodules-decluse.
When enforcing the module semantics, we also need to consider a source
file part of a module. This is achieved with a compiler option
-fmodule-name=<module-id>.
The compiler at present only applies restrictions to the module directly
being built.
Added:
cfe/trunk/test/Modules/Inputs/declare-use/
cfe/trunk/test/Modules/Inputs/declare-use/a.h
cfe/trunk/test/Modules/Inputs/declare-use/b.h
cfe/trunk/test/Modules/Inputs/declare-use/c.h
cfe/trunk/test/Modules/Inputs/declare-use/d.h
cfe/trunk/test/Modules/Inputs/declare-use/e.h
cfe/trunk/test/Modules/Inputs/declare-use/f.h
cfe/trunk/test/Modules/Inputs/declare-use/g.h
cfe/trunk/test/Modules/Inputs/declare-use/g1.h
cfe/trunk/test/Modules/Inputs/declare-use/h.h
cfe/trunk/test/Modules/Inputs/declare-use/h1.h
cfe/trunk/test/Modules/Inputs/declare-use/module.map
cfe/trunk/test/Modules/declare-use1.cpp
cfe/trunk/test/Modules/declare-use2.cpp
Modified:
cfe/trunk/docs/Modules.rst
cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
cfe/trunk/include/clang/Basic/LangOptions.def
cfe/trunk/include/clang/Basic/Module.h
cfe/trunk/include/clang/Driver/Options.td
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/include/clang/Lex/Preprocessor.h
cfe/trunk/lib/Basic/Module.cpp
cfe/trunk/lib/Driver/Tools.cpp
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/lib/Lex/HeaderSearch.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/lib/Lex/PPDirectives.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
Modified: cfe/trunk/docs/Modules.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/docs/Modules.rst (original)
+++ cfe/trunk/docs/Modules.rst Tue Sep 24 04:14:14 2013
@@ -188,6 +188,12 @@ Command-line parameters
``-module-file-info <module file name>``
Debugging aid that prints information about a given module file (with a ``.pcm`` extension), including the language and preprocessor options that particular module variant was built with.
+``-fmodules-decluse``
+ Enable checking of module ``use`` declarations.
+
+``-fmodule-name=module-id``
+ Consider a source file as a part of the given module.
+
Module Map Language
===================
@@ -238,7 +244,7 @@ Module map files use a simplified form o
``conflict`` ``framework`` ``requires``
``exclude`` ``header`` ``private``
``explicit`` ``link`` ``umbrella``
- ``extern``
+ ``extern`` ``use``
Module map file
---------------
@@ -293,6 +299,7 @@ Modules can have a number of different k
*umbrella-dir-declaration*
*submodule-declaration*
*export-declaration*
+ *use-declaration*
*link-declaration*
*config-macros-declaration*
*conflict-declaration*
@@ -533,6 +540,36 @@ Note that, if ``Derived.h`` includes ``B
compatibility for programs that rely on transitive inclusion (i.e.,
all of them).
+Use declaration
+~~~~~~~~~~~~~~~
+A *use-declaration* specifies one of the other modules that the module is allowed to use. An import or include not matching one of these is rejected when the option *-fmodules-decluse*.
+
+.. parsed-literal::
+
+ *use-declaration*:
+ ``use`` *module-id*
+
+**Example**:: In the following example, use of A from C is not declared, so will trigger a warning.
+
+.. parsed-literal::
+
+ module A {
+ header "a.h"
+ }
+
+ module B {
+ header "b.h"
+ }
+
+ module C {
+ header "c.h"
+ use B
+ }
+
+When compiling a source file that implements a module, use the option ``-fmodule-name=``module-id to indicate that the source file is logically part of that module.
+
+The compiler at present only applies restrictions to the module directly being built.
+
Link declaration
~~~~~~~~~~~~~~~~
A *link-declaration* specifies a library or framework against which a program should be linked if the enclosing module is imported in any translation unit in that program.
Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Tue Sep 24 04:14:14 2013
@@ -554,8 +554,8 @@ def err_mmap_umbrella_dir_not_found : Er
"umbrella directory '%0' not found">;
def err_mmap_umbrella_clash : Error<
"umbrella for module '%0' already covers this directory">;
-def err_mmap_export_module_id : Error<
- "expected an exported module name or '*'">;
+def err_mmap_module_id : Error<
+ "expected a module name or '*'">;
def err_mmap_expected_library_name : Error<
"expected %select{library|framework}0 name as a string">;
def err_mmap_config_macro_submodule : Error<
@@ -610,7 +610,9 @@ def err_expected_id_building_module : Er
"expected a module name in '__building_module' expression">;
def error_use_of_private_header_outside_module : Error<
"use of private header from outside its module: '%0'">;
-
+def error_undeclared_use_of_module : Error<
+ "use of a module not declared used: '%0'">;
+
def warn_header_guard : Warning<
"%0 is used as a header guard here, followed by #define of a different macro">,
InGroup<DiagGroup<"header-guard">>;
Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Tue Sep 24 04:14:14 2013
@@ -94,6 +94,7 @@ BENIGN_LANGOPT(EmitAllDecls , 1, 0,
LANGOPT(MathErrno , 1, 1, "errno support for math functions")
BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time")
LANGOPT(Modules , 1, 0, "modules extension to C")
+LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Tue Sep 24 04:14:14 2013
@@ -183,6 +183,12 @@ public:
/// \brief The set of export declarations that have yet to be resolved.
SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
+ /// \brief The directly used modules.
+ SmallVector<Module *, 2> DirectUses;
+
+ /// \brief The set of use declarations that have yet to be resolved.
+ SmallVector<ModuleId, 2> UnresolvedDirectUses;
+
/// \brief A library or framework to link against when an entity from this
/// module is used.
struct LinkLibrary {
Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Tue Sep 24 04:14:14 2013
@@ -561,6 +561,9 @@ def fmodule_maps : Flag <["-"], "fmodule
HelpText<"Read module maps to understand the structure of library headers">;
def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Ignore the definition of the given macro when building and loading modules">;
+def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>,
+ HelpText<"Require declaration of modules used within a module">;
def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;
@@ -621,6 +624,8 @@ def fno_modules : Flag <["-"], "fno-modu
Flags<[DriverOption]>;
def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>,
Flags<[DriverOption]>;
+def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
+ Flags<[DriverOption]>;
def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Tue Sep 24 04:14:14 2013
@@ -55,6 +55,12 @@ class ModuleMap {
// The module that we are building; related to \c LangOptions::CurrentModule.
Module *CompilingModule;
+public:
+ // The module that the .cc source file is associated with.
+ Module *SourceModule;
+ std::string SourceModuleName;
+
+private:
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
@@ -299,6 +305,16 @@ public:
/// false otherwise.
bool resolveExports(Module *Mod, bool Complain);
+ /// \brief Resolve all of the unresolved uses in the given module.
+ ///
+ /// \param Mod The module whose uses should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving uses,
+ /// false otherwise.
+ bool resolveUses(Module *Mod, bool Complain);
+
/// \brief Resolve all of the unresolved conflicts in the given module.
///
/// \param Mod The module whose conflicts should be resolved.
Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Tue Sep 24 04:14:14 2013
@@ -1441,6 +1441,31 @@ private:
void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
void HandleMicrosoftImportDirective(Token &Tok);
+ // Module inclusion testing.
+ /// \brief Find the module for the source or header file that \p FilenameLoc
+ /// points to.
+ Module *getModuleForLocation(SourceLocation FilenameLoc);
+
+ /// \brief Verify that a private header is included only from within its
+ /// module.
+ bool violatesPrivateInclude(Module *RequestingModule,
+ const FileEntry *IncFileEnt,
+ ModuleMap::ModuleHeaderRole Role,
+ Module *RequestedModule);
+
+ /// \brief Verify that a module includes headers only from modules that it
+ /// has declared that it uses.
+ bool violatesUseDeclarations(Module *RequestingModule,
+ Module *RequestedModule);
+
+ /// \brief Verify that it is legal for the source file that \p FilenameLoc
+ /// points to to include the file \p Filename.
+ ///
+ /// Tries to reuse \p IncFileEnt and \p SuggestedModule.
+ void verifyModuleInclude(SourceLocation FilenameLoc, StringRef Filename,
+ const FileEntry *IncFileEnt,
+ ModuleMap::KnownHeader *SuggestedModule);
+
// Macro handling.
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
void HandleUndefDirective(Token &Tok);
Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Tue Sep 24 04:14:14 2013
@@ -362,6 +362,20 @@ void Module::print(raw_ostream &OS, unsi
OS << "\n";
}
+ for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "use ";
+ OS << DirectUses[I]->getFullModuleName();
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "use ";
+ printModuleId(OS, UnresolvedDirectUses[I]);
+ OS << "\n";
+ }
+
for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "link ";
Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Sep 24 04:14:14 2013
@@ -3034,6 +3034,13 @@ void Clang::ConstructJob(Compilation &C,
CmdArgs.push_back("-fmodule-maps");
}
+ // -fmodule-decluse checks that modules used are declared so (off by default).
+ if (Args.hasFlag(options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodule-decluse");
+ }
+
// If a module path was provided, pass it along. Otherwise, use a temporary
// directory.
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) {
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue Sep 24 04:14:14 2013
@@ -1280,6 +1280,7 @@ static void ParseLangArgs(LangOptions &O
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
Opts.Modules = Args.hasArg(OPT_fmodules);
+ Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Tue Sep 24 04:14:14 2013
@@ -22,6 +22,7 @@
#include "llvm/Support/Capacity.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#if defined(LLVM_ON_UNIX)
#include <limits.h>
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Sep 24 04:14:14 2013
@@ -387,6 +387,10 @@ ModuleMap::findOrCreateModule(StringRef
// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
IsExplicit);
+ if (LangOpts.CurrentModule == Name) {
+ SourceModule = Result;
+ SourceModuleName = Name;
+ }
if (!Parent) {
Modules[Name] = Result;
if (!LangOpts.CurrentModule.empty() && !CompilingModule &&
@@ -518,6 +522,10 @@ ModuleMap::inferFrameworkModule(StringRe
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false);
+ if (LangOpts.CurrentModule == ModuleName) {
+ SourceModule = Result;
+ SourceModuleName = ModuleName;
+ }
if (IsSystem)
Result->IsSystem = IsSystem;
@@ -653,6 +661,20 @@ bool ModuleMap::resolveExports(Module *M
return HadError;
}
+bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
+ bool HadError = false;
+ for (unsigned I = 0, N = Mod->UnresolvedDirectUses.size(); I != N; ++I) {
+ Module *DirectUse =
+ resolveModuleId(Mod->UnresolvedDirectUses[I], Mod, Complain);
+ if (DirectUse)
+ Mod->DirectUses.push_back(DirectUse);
+ else
+ HadError = true;
+ }
+ Mod->UnresolvedDirectUses.clear();
+ return HadError;
+}
+
bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
bool HadError = false;
for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
@@ -727,6 +749,7 @@ namespace clang {
Period,
PrivateKeyword,
UmbrellaKeyword,
+ UseKeyword,
RequiresKeyword,
Star,
StringLiteral,
@@ -819,6 +842,7 @@ namespace clang {
SourceLocation LeadingLoc);
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
void parseExportDecl();
+ void parseUseDecl();
void parseLinkDecl();
void parseConfigMacros();
void parseConflict();
@@ -873,6 +897,7 @@ retry:
.Case("private", MMToken::PrivateKeyword)
.Case("requires", MMToken::RequiresKeyword)
.Case("umbrella", MMToken::UmbrellaKeyword)
+ .Case("use", MMToken::UseKeyword)
.Default(MMToken::Identifier);
break;
@@ -1209,6 +1234,10 @@ void ModuleMapParser::parseModuleDecl()
case MMToken::ExportKeyword:
parseExportDecl();
break;
+
+ case MMToken::UseKeyword:
+ parseUseDecl();
+ break;
case MMToken::RequiresKeyword:
parseRequiresDecl();
@@ -1593,7 +1622,7 @@ void ModuleMapParser::parseExportDecl()
break;
}
- Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
+ Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
HadError = true;
return;
} while (true);
@@ -1604,6 +1633,38 @@ void ModuleMapParser::parseExportDecl()
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
+/// \brief Parse a module uses declaration.
+///
+/// uses-declaration:
+/// 'uses' wildcard-module-id
+void ModuleMapParser::parseUseDecl() {
+ assert(Tok.is(MMToken::UseKeyword));
+ consumeToken();
+ // Parse the module-id.
+ ModuleId ParsedModuleId;
+
+ do {
+ if (Tok.is(MMToken::Identifier)) {
+ ParsedModuleId.push_back(
+ std::make_pair(Tok.getString(), Tok.getLocation()));
+ consumeToken();
+
+ if (Tok.is(MMToken::Period)) {
+ consumeToken();
+ continue;
+ }
+
+ break;
+ }
+
+ Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
+ HadError = true;
+ return;
+ } while (true);
+
+ ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
+}
+
/// \brief Parse a link declaration.
///
/// module-declaration:
@@ -2001,6 +2062,7 @@ bool ModuleMapParser::parseModuleMapFile
case MMToken::Star:
case MMToken::StringLiteral:
case MMToken::UmbrellaKeyword:
+ case MMToken::UseKeyword:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
HadError = true;
consumeToken();
Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Tue Sep 24 04:14:14 2013
@@ -532,6 +532,88 @@ void Preprocessor::PTHSkipExcludedCondit
}
}
+Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
+ ModuleMap &ModMap = HeaderInfo.getModuleMap();
+ if (SourceMgr.isInMainFile(FilenameLoc)) {
+ if (Module *CurMod = getCurrentModule())
+ return CurMod; // Compiling a module.
+ return HeaderInfo.getModuleMap().SourceModule; // Compiling a source.
+ }
+ // Try to determine the module of the include directive.
+ FileID IDOfIncl = SourceMgr.getFileID(FilenameLoc);
+ if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) {
+ // The include comes from a file.
+ return ModMap.findModuleForHeader(EntryOfIncl).getModule();
+ } else {
+ // The include does not come from a file,
+ // so it is probably a module compilation.
+ return getCurrentModule();
+ }
+}
+
+bool Preprocessor::violatesPrivateInclude(
+ Module *RequestingModule,
+ const FileEntry *IncFileEnt,
+ ModuleMap::ModuleHeaderRole Role,
+ Module *RequestedModule) {
+ #ifndef NDEBUG
+ // Check for consistency between the module header role
+ // as obtained from the lookup and as obtained from the module.
+ // This check is not cheap, so enable it only for debugging.
+ SmallVectorImpl<const FileEntry *> &PvtHdrs
+ = RequestedModule->PrivateHeaders;
+ SmallVectorImpl<const FileEntry *>::iterator Look
+ = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt);
+ bool IsPrivate = Look != PvtHdrs.end();
+ assert((IsPrivate && Role == ModuleMap::PrivateHeader)
+ || (!IsPrivate && Role != ModuleMap::PrivateHeader));
+ #endif
+ return Role == ModuleMap::PrivateHeader &&
+ RequestedModule->getTopLevelModule() != RequestingModule;
+}
+
+bool Preprocessor::violatesUseDeclarations(
+ Module *RequestingModule,
+ Module *RequestedModule) {
+ ModuleMap &ModMap = HeaderInfo.getModuleMap();
+ ModMap.resolveUses(RequestingModule, /*Complain=*/false);
+ const SmallVectorImpl<Module *> &AllowedUses = RequestingModule->DirectUses;
+ SmallVectorImpl<Module *>::const_iterator Declared =
+ std::find(AllowedUses.begin(), AllowedUses.end(), RequestedModule);
+ return Declared == AllowedUses.end();
+}
+
+void Preprocessor::verifyModuleInclude(
+ SourceLocation FilenameLoc,
+ StringRef Filename,
+ const FileEntry *IncFileEnt,
+ ModuleMap::KnownHeader *SuggestedModule) {
+ Module *RequestingModule = getModuleForLocation(FilenameLoc);
+ Module *RequestedModule = SuggestedModule->getModule();
+ if (!RequestedModule)
+ RequestedModule = HeaderInfo.findModuleForHeader(IncFileEnt).getModule();
+
+ if (RequestingModule == RequestedModule)
+ return; // No faults wihin a module, or between files both not in modules.
+
+ if (RequestingModule != HeaderInfo.getModuleMap().SourceModule)
+ return; // No errors for indirect modules.
+ // This may be a bit of a problem for modules with no source files.
+
+ if (RequestedModule &&
+ violatesPrivateInclude(RequestingModule, IncFileEnt,
+ SuggestedModule->getRole(), RequestedModule))
+ Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
+ << Filename;
+
+ // FIXME: Add support for FixIts in module map files and offer adding the
+ // required use declaration.
+ if (RequestingModule && getLangOpts().ModulesDeclUse &&
+ violatesUseDeclarations(RequestingModule, RequestedModule))
+ Diag(FilenameLoc, diag::error_undeclared_use_of_module)
+ << Filename;
+}
+
const FileEntry *Preprocessor::LookupFile(
SourceLocation FilenameLoc,
StringRef Filename,
@@ -567,29 +649,8 @@ const FileEntry *Preprocessor::LookupFil
Filename, isAngled, FromDir, CurDir, CurFileEnt,
SearchPath, RelativePath, SuggestedModule, SkipCache);
if (FE) {
- if (SuggestedModule) {
- Module *RequestedModule = SuggestedModule->getModule();
- if (RequestedModule) {
- ModuleMap::ModuleHeaderRole Role = SuggestedModule->getRole();
- #ifndef NDEBUG
- // Check for consistency between the module header role
- // as obtained from the lookup and as obtained from the module.
- // This check is not cheap, so enable it only for debugging.
- SmallVectorImpl<const FileEntry *> &PvtHdrs
- = RequestedModule->PrivateHeaders;
- SmallVectorImpl<const FileEntry *>::iterator Look
- = std::find(PvtHdrs.begin(), PvtHdrs.end(), FE);
- bool IsPrivate = Look != PvtHdrs.end();
- assert((IsPrivate && Role == ModuleMap::PrivateHeader)
- || (!IsPrivate && Role != ModuleMap::PrivateHeader));
- #endif
- if (Role == ModuleMap::PrivateHeader) {
- if (RequestedModule->getTopLevelModule() != getCurrentModule())
- Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
- << Filename;
- }
- }
- }
+ if (SuggestedModule)
+ verifyModuleInclude(FilenameLoc, Filename, FE, SuggestedModule);
return FE;
}
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Tue Sep 24 04:14:14 2013
@@ -654,6 +654,7 @@ void Sema::ActOnEndOfTranslationUnit() {
// diagnostic client to deal with complaints in the module map at this
// point.
ModMap.resolveExports(Mod, /*Complain=*/false);
+ ModMap.resolveUses(Mod, /*Complain=*/false);
ModMap.resolveConflicts(Mod, /*Complain=*/false);
// Queue the submodules, so their exports will also be resolved.
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Sep 24 04:14:14 2013
@@ -3028,6 +3028,10 @@ ASTReader::ASTReadResult ASTReader::Read
}
}
UnresolvedModuleRefs.clear();
+
+ // FIXME: How do we load the 'use'd modules? They may not be submodules.
+ // Might be unnecessary as use declarations are only used to build the
+ // module itself.
InitializeContext();
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=191283&r1=191282&r2=191283&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Sep 24 04:14:14 2013
@@ -2421,6 +2421,10 @@ void ASTWriter::WriteSubmodules(Module *
Stream.EmitRecord(SUBMODULE_EXPORTS, Record);
}
+ //FIXME: How do we emit the 'use'd modules? They may not be submodules.
+ // Might be unnecessary as use declarations are only used to build the
+ // module itself.
+
// Emit the link libraries.
for (unsigned I = 0, N = Mod->LinkLibraries.size(); I != N; ++I) {
Record.clear();
Added: cfe/trunk/test/Modules/Inputs/declare-use/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/a.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/a.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+const int a = 2;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/b.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/b.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/b.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,4 @@
+#ifndef B_H
+#define B_H
+const int b = 3;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/c.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/c.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/c.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/c.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,6 @@
+#ifndef C_H
+#define C_H
+#include "a.h"
+#include "b.h"
+const int c = a+b;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/d.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/d.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/d.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/d.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,6 @@
+#ifndef D_H
+#define D_H
+#include "a.h"
+#include "b.h"
+const int d = a+b;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/e.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/e.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/e.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/e.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,6 @@
+#ifndef E_H
+#define E_H
+#include "a.h"
+#include "b.h"
+const int e = a*b;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/f.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/f.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/f.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/f.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,6 @@
+#ifndef F_H
+#define F_H
+#include "a.h"
+#include "b.h"
+const int f = a+b;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/g.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/g.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/g.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/g.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,6 @@
+#ifndef G_H
+#define G_H
+#include "c.h"
+#include "g1.h"
+const int g1 = aux_g*c*7;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/g1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/g1.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/g1.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/g1.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1 @@
+int aux_g = 11;
Added: cfe/trunk/test/Modules/Inputs/declare-use/h.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/h.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/h.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/h.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1,7 @@
+#ifndef H_H
+#define H_H
+#include "c.h"
+#include "d.h" // expected-error {{use of a module not declared used}}
+#include "h1.h"
+const int h1 = aux_h*c*7*d;
+#endif
Added: cfe/trunk/test/Modules/Inputs/declare-use/h1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/h1.h?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/h1.h (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/h1.h Tue Sep 24 04:14:14 2013
@@ -0,0 +1 @@
+int aux_h = 13;
Added: cfe/trunk/test/Modules/Inputs/declare-use/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/module.map?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/module.map (added)
+++ cfe/trunk/test/Modules/Inputs/declare-use/module.map Tue Sep 24 04:14:14 2013
@@ -0,0 +1,43 @@
+module A {
+ header "a.h"
+}
+
+module B {
+ header "b.h"
+}
+
+module C {
+ header "c.h"
+ use A
+}
+
+module D {
+ header "d.h"
+ use A
+}
+
+module E {
+ header "e.h"
+ use A
+ use B
+}
+
+module F {
+ header "f.h"
+ use A
+ use B
+}
+
+module G {
+ header "g.h"
+ header "g1.h"
+ use C
+ use E
+}
+
+module H {
+ header "h.h"
+ header "h1.h"
+ use C
+ use E
+}
Added: cfe/trunk/test/Modules/declare-use1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/declare-use1.cpp?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/declare-use1.cpp (added)
+++ cfe/trunk/test/Modules/declare-use1.cpp Tue Sep 24 04:14:14 2013
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=G -I %S/Inputs/declare-use %s -verify
+
+#include "g.h"
+#include "e.h"
+#include "f.h" // expected-error {{use of a module not declared used}}
+const int g2 = g1+e+f;
Added: cfe/trunk/test/Modules/declare-use2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/declare-use2.cpp?rev=191283&view=auto
==============================================================================
--- cfe/trunk/test/Modules/declare-use2.cpp (added)
+++ cfe/trunk/test/Modules/declare-use2.cpp Tue Sep 24 04:14:14 2013
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=H -I %S/Inputs/declare-use %s -verify
+
+#include "h.h"
+#include "e.h"
+#include "f.h" // expected-error {{use of a module not declared used}}
+const int h2 = h1+e+f;
More information about the cfe-commits
mailing list