r233323 - [modules] Restrict the module use-declaration to only appear in top-level
Richard Smith
richard-llvm at metafoo.co.uk
Thu Mar 26 15:10:02 PDT 2015
Author: rsmith
Date: Thu Mar 26 17:10:01 2015
New Revision: 233323
URL: http://llvm.org/viewvc/llvm-project?rev=233323&view=rev
Log:
[modules] Restrict the module use-declaration to only appear in top-level
modules, and allow sub-modules of a module with a use-declaration to make use
of the nominated modules.
Added:
cfe/trunk/test/Modules/Inputs/diagnostics-aux.modulemap
Modified:
cfe/trunk/docs/Modules.rst
cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
cfe/trunk/include/clang/Basic/Module.h
cfe/trunk/lib/Basic/Module.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/test/Modules/Inputs/declare-use/module.map
cfe/trunk/test/Modules/diagnostics.modulemap
Modified: cfe/trunk/docs/Modules.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/docs/Modules.rst (original)
+++ cfe/trunk/docs/Modules.rst Thu Mar 26 17:10:01 2015
@@ -429,7 +429,7 @@ tls
A specific target feature (e.g., ``sse4``, ``avx``, ``neon``) is available.
-**Example**: The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
+**Example:** The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
.. parsed-literal::
@@ -470,11 +470,16 @@ A header with the ``umbrella`` specifier
A header with the ``private`` specifier may not be included from outside the module itself.
-A header with the ``textual`` specifier will not be included when the module is built, and will be textually included if it is named by a ``#include`` directive. However, it is considered to be part of the module for the purpose of checking *use-declaration*\s.
+A header with the ``textual`` specifier will not be compiled when the module is
+built, and will be textually included if it is named by a ``#include``
+directive. However, it is considered to be part of the module for the purpose
+of checking *use-declaration*\s, and must still be a lexically-valid header
+file. In the future, we intend to pre-tokenize such headers and include the
+token sequence within the prebuilt module representation.
A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module, even if an ``umbrella`` header or directory would otherwise make it part of the module.
-**Example**: The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header.
+**Example:** The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header.
.. parsed-literal::
@@ -536,7 +541,7 @@ For each header included by the umbrella
* Contain a single *header-declaration* naming that header
* Contain a single *export-declaration* ``export *``, if the \ *inferred-submodule-declaration* contains the \ *inferred-submodule-member* ``export *``
-**Example**: If the subdirectory "MyLib" contains the headers ``A.h`` and ``B.h``, then the following module map:
+**Example:** If the subdirectory "MyLib" contains the headers ``A.h`` and ``B.h``, then the following module map:
.. parsed-literal::
@@ -579,7 +584,7 @@ An *export-declaration* specifies which
The *export-declaration* names a module or a set of modules that will be re-exported to any translation unit that imports the enclosing module. Each imported module that matches the *wildcard-module-id* up to, but not including, the first ``*`` will be re-exported.
-**Example**:: In the following example, importing ``MyLib.Derived`` also provides the API for ``MyLib.Base``:
+**Example:** In the following example, importing ``MyLib.Derived`` also provides the API for ``MyLib.Base``:
.. parsed-literal::
@@ -623,14 +628,16 @@ Note that, if ``Derived.h`` includes ``B
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*.
+A *use-declaration* specifies another module that the current top-level module
+intends to use. When the option *-fmodules-decluse* is specified, a module can
+only use other modules that are explicitly specified in this way.
.. 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.
+**Example:** In the following example, use of A from C is not declared, so will trigger a warning.
.. parsed-literal::
@@ -647,7 +654,9 @@ A *use-declaration* specifies one of the
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.
+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.
Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Thu Mar 26 17:10:01 2015
@@ -579,7 +579,9 @@ def err_mmap_module_id : Error<
def err_mmap_expected_library_name : Error<
"expected %select{library|framework}0 name as a string">;
def err_mmap_config_macro_submodule : Error<
- "configuration macros are only allowed on top-level modules">;
+ "configuration macros are only allowed in top-level modules">;
+def err_mmap_use_decl_submodule : Error<
+ "use declarations are only allowed in top-level modules">;
def err_mmap_expected_config_macro : Error<
"expected configuration macro name after ','">;
def err_mmap_expected_conflicts_comma : Error<
Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Thu Mar 26 17:10:01 2015
@@ -399,6 +399,10 @@ public:
/// \brief The top-level headers associated with this module.
ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr);
+ /// \brief Determine whether this module has declared its intention to
+ /// directly use another module.
+ bool directlyUses(const Module *Requested) const;
+
/// \brief Add the given feature requirement to the list of features
/// required by this module.
///
Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Thu Mar 26 17:10:01 2015
@@ -158,6 +158,19 @@ ArrayRef<const FileEntry *> Module::getT
return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
}
+bool Module::directlyUses(const Module *Requested) const {
+ auto *Top = getTopLevelModule();
+
+ // A top-level module implicitly uses itself.
+ if (Requested->isSubModuleOf(Top))
+ return true;
+
+ for (auto *Use : Top->DirectUses)
+ if (Requested->isSubModuleOf(Use))
+ return true;
+ return false;
+}
+
void Module::addRequirement(StringRef Feature, bool RequiredState,
const LangOptions &LangOpts,
const TargetInfo &Target) {
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Thu Mar 26 17:10:01 2015
@@ -205,16 +205,6 @@ ModuleMap::findHeaderInUmbrellaDirs(cons
return KnownHeader();
}
-// Returns true if RequestingModule directly uses RequestedModule.
-static bool directlyUses(const Module *RequestingModule,
- const Module *RequestedModule) {
- for (const Module* DirectUse : RequestingModule->DirectUses) {
- if (RequestedModule->isSubModuleOf(DirectUse))
- return true;
- }
- return false;
-}
-
static bool violatesPrivateInclude(Module *RequestingModule,
const FileEntry *IncFileEnt,
ModuleMap::ModuleHeaderRole Role,
@@ -238,6 +228,9 @@ static bool violatesPrivateInclude(Modul
}
#endif
return IsPrivateRole &&
+ // FIXME: Should we map RequestingModule to its top-level module here
+ // too? This check is redundant with the isSubModuleOf check in
+ // diagnoseHeaderInclusion.
RequestedModule->getTopLevelModule() != RequestingModule;
}
@@ -279,7 +272,7 @@ void ModuleMap::diagnoseHeaderInclusion(
// If uses need to be specified explicitly, we are only allowed to return
// modules that are explicitly used by the requesting module.
if (RequestingModule && LangOpts.ModulesDeclUse &&
- !directlyUses(RequestingModule, Header.getModule())) {
+ !RequestingModule->directlyUses(Header.getModule())) {
NotUsed = Header.getModule();
continue;
}
@@ -368,7 +361,7 @@ ModuleMap::findModuleForHeader(const Fil
// If uses need to be specified explicitly, we are only allowed to return
// modules that are explicitly used by the requesting module.
if (RequestingModule && LangOpts.ModulesDeclUse &&
- !directlyUses(RequestingModule, I->getModule()))
+ !RequestingModule->directlyUses(I->getModule()))
continue;
if (!Result || isBetterKnownHeader(*I, Result))
@@ -1918,18 +1911,21 @@ void ModuleMapParser::parseExportDecl()
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module uses declaration.
+/// \brief Parse a module use declaration.
///
-/// uses-declaration:
-/// 'uses' wildcard-module-id
+/// use-declaration:
+/// 'use' wildcard-module-id
void ModuleMapParser::parseUseDecl() {
assert(Tok.is(MMToken::UseKeyword));
- consumeToken();
+ auto KWLoc = consumeToken();
// Parse the module-id.
ModuleId ParsedModuleId;
parseModuleId(ParsedModuleId);
- ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
+ if (ActiveModule->Parent)
+ Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
+ else
+ ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
}
/// \brief Parse a link declaration.
Modified: 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=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/declare-use/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/declare-use/module.map Thu Mar 26 17:10:01 2015
@@ -3,7 +3,7 @@ module XA {
}
module XB {
- header "b.h"
+ module B { header "b.h" }
}
module XC {
@@ -43,7 +43,7 @@ module XG {
}
module XH {
- header "h.h"
+ module H { header "h.h" }
header "h1.h"
header "s.h"
use XC
Added: cfe/trunk/test/Modules/Inputs/diagnostics-aux.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/diagnostics-aux.modulemap?rev=233323&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/diagnostics-aux.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/diagnostics-aux.modulemap Thu Mar 26 17:10:01 2015
@@ -0,0 +1 @@
+module foo {}
Modified: cfe/trunk/test/Modules/diagnostics.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/diagnostics.modulemap?rev=233323&r1=233322&r2=233323&view=diff
==============================================================================
--- cfe/trunk/test/Modules/diagnostics.modulemap (original)
+++ cfe/trunk/test/Modules/diagnostics.modulemap Thu Mar 26 17:10:01 2015
@@ -1,12 +1,14 @@
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%s -fsyntax-only -x c++ /dev/null 2>&1
-//
-// RUN: cp %s %t-duplicate.modulemap
-// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%s -fmodule-map-file=%t-duplicate.modulemap -fsyntax-only -x c++ /dev/null 2>&1 | FileCheck --check-prefix=CHECK-DUPLICATE %s
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/diagnostics-aux.modulemap -fmodule-map-file=%s -fsyntax-only -x c++ /dev/null 2>&1 | FileCheck %s
// PR22299: Ensure we can produce diagnostics for duplicate modules from -fmodule-map-file=.
//
-// CHECK-DUPLICATE: duplicate.modulemap:[[@LINE+2]]:8: error: redefinition of module 'foo'
-// CHECK-DUPLICATE: diagnostics.modulemap:[[@LINE+1]]:8: note: previously defined here
+// CHECK: diagnostics.modulemap:[[@LINE+2]]:8: error: redefinition of module 'foo'
+// CHECK: diagnostics-aux.modulemap:1:8: note: previously defined here
module foo {}
//* Check that we accept BCPL comments properly, not just as an extension. */
+
+module bad_use {
+ // CHECK: diagnostics.modulemap:[[@LINE+1]]:22: error: use declarations are only allowed in top-level modules
+ module submodule { use foo }
+}
More information about the cfe-commits
mailing list