<p dir="ltr">Sure, thanks!</p>
<div class="gmail_quote">On 25 Oct 2014 17:31, "NAKAMURA Takumi" <<a href="mailto:geek4civic@gmail.com">geek4civic@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">2014-10-25 5:23 GMT+09:00 Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>>:<br>
> Author: rsmith<br>
> Date: Fri Oct 24 15:23:01 2014<br>
> New Revision: 220589<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=220589&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=220589&view=rev</a><br>
> Log:<br>
> [modules] Support combining 'textual' with 'private'.<br>
><br>
> Added:<br>
> cfe/trunk/test/Modules/Inputs/declare-use/m.h<br>
> - copied unchanged from r220460, cfe/trunk/test/Modules/Inputs/declare-use/m.h<br>
> cfe/trunk/test/Modules/Inputs/declare-use/m2.h<br>
> - copied unchanged from r220460, cfe/trunk/test/Modules/Inputs/declare-use/m2.h<br>
> Modified:<br>
> cfe/trunk/docs/Modules.rst<br>
> cfe/trunk/include/clang/Basic/Module.h<br>
> cfe/trunk/include/clang/Lex/ModuleMap.h<br>
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
> cfe/trunk/lib/Lex/ModuleMap.cpp<br>
> cfe/trunk/lib/Serialization/ASTReader.cpp<br>
> cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
> cfe/trunk/test/Modules/Inputs/declare-use/module.map<br>
> cfe/trunk/test/Modules/textual-headers.cpp<br>
><br>
> Modified: cfe/trunk/docs/Modules.rst<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/docs/Modules.rst (original)<br>
> +++ cfe/trunk/docs/Modules.rst Fri Oct 24 15:23:01 2014<br>
> @@ -445,9 +445,8 @@ A header declaration specifies that a pa<br>
> .. parsed-literal::<br>
><br>
> *header-declaration*:<br>
> - ``umbrella``:sub:`opt` ``header`` *string-literal*<br>
> - ``private`` ``header`` *string-literal*<br>
> - ``textual`` ``header`` *string-literal*<br>
> + ``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal*<br>
> + ``umbrella`` ``header`` *string-literal*<br>
> ``exclude`` ``header`` *string-literal*<br>
><br>
> A header declaration that does not contain ``exclude`` nor ``textual`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule.<br>
> @@ -464,14 +463,14 @@ A header with the ``private`` specifier<br>
><br>
> 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.<br>
><br>
> -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.<br>
> +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.<br>
><br>
> -**Example**: The C header ``assert.h`` is an excellent candidate for an excluded header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings).<br>
> +**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.<br>
><br>
> .. parsed-literal::<br>
><br>
> module std [system] {<br>
> - exclude header "assert.h"<br>
> + textual header "assert.h"<br>
> }<br>
><br>
> A given header shall not be referenced by more than one *header-declaration*.<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/Module.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/Module.h (original)<br>
> +++ cfe/trunk/include/clang/Basic/Module.h Fri Oct 24 15:23:01 2014<br>
> @@ -84,9 +84,6 @@ public:<br>
> /// \brief The headers that are part of this module.<br>
> SmallVector<const FileEntry *, 2> NormalHeaders;<br>
><br>
> - /// \brief The headers that are explicitly excluded from this module.<br>
> - SmallVector<const FileEntry *, 2> ExcludedHeaders;<br>
> -<br>
> /// \brief The headers that are logically part of this module but<br>
> /// must be textually included.<br>
> SmallVector<const FileEntry *, 2> TextualHeaders;<br>
> @@ -94,6 +91,13 @@ public:<br>
> /// \brief The headers that are private to this module.<br>
> SmallVector<const FileEntry *, 2> PrivateHeaders;<br>
><br>
> + /// \brief The headers that are private to this module and are to be<br>
> + /// included textually.<br>
> + SmallVector<const FileEntry *, 2> PrivateTextualHeaders;<br>
> +<br>
> + /// \brief The headers that are explicitly excluded from this module.<br>
> + SmallVector<const FileEntry *, 2> ExcludedHeaders;<br>
> +<br>
> /// \brief Information about a header directive as found in the module map<br>
> /// file.<br>
> struct HeaderDirective {<br>
><br>
> Modified: cfe/trunk/include/clang/Lex/ModuleMap.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Lex/ModuleMap.h (original)<br>
> +++ cfe/trunk/include/clang/Lex/ModuleMap.h Fri Oct 24 15:23:01 2014<br>
> @@ -65,20 +65,21 @@ private:<br>
> llvm::StringMap<Module *> Modules;<br>
><br>
> public:<br>
> - /// \brief Describes the role of a module header.<br>
> + /// \brief Flags describing the role of a module header.<br>
> enum ModuleHeaderRole {<br>
> /// \brief This header is normally included in the module.<br>
> - NormalHeader,<br>
> + NormalHeader = 0x0,<br>
> /// \brief This header is included but private.<br>
> - PrivateHeader,<br>
> + PrivateHeader = 0x1,<br>
> /// \brief This header is part of the module (for layering purposes) but<br>
> /// should be textually included.<br>
> - TextualHeader,<br>
> + TextualHeader = 0x2,<br>
> // Caution: Adding an enumerator needs other changes.<br>
> // Adjust the number of bits for KnownHeader::Storage.<br>
> // Adjust the bitfield HeaderFileInfo::HeaderRole size.<br>
> // Adjust the HeaderFileInfoTrait::ReadData streaming.<br>
> // Adjust the HeaderFileInfoTrait::EmitData streaming.<br>
> + // Adjust ModuleMap::addHeader.<br>
> };<br>
><br>
> /// \brief A header that is known to reside within a given module,<br>
><br>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Oct 24 15:23:01 2014<br>
> @@ -645,6 +645,9 @@ namespace clang {<br>
> /// \brief Specifies a header that is part of the module but must be<br>
> /// textually included.<br>
> SUBMODULE_TEXTUAL_HEADER = 14,<br>
> + /// \brief Specifies a header that is private to this submodule but<br>
> + /// must be textually included.<br>
> + SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,<br>
> };<br>
><br>
> /// \brief Record types used within a comments block.<br>
><br>
> Modified: cfe/trunk/lib/Lex/ModuleMap.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Lex/ModuleMap.cpp (original)<br>
> +++ cfe/trunk/lib/Lex/ModuleMap.cpp Fri Oct 24 15:23:01 2014<br>
> @@ -202,7 +202,7 @@ ModuleMap::findHeaderInUmbrellaDirs(cons<br>
> return KnownHeader();<br>
> }<br>
><br>
> -// Returns 'true' if 'RequestingModule directly uses 'RequestedModule'.<br>
> +// Returns true if RequestingModule directly uses RequestedModule.<br>
> static bool directlyUses(const Module *RequestingModule,<br>
> const Module *RequestedModule) {<br>
> return std::find(RequestingModule->DirectUses.begin(),<br>
> @@ -214,19 +214,19 @@ static bool violatesPrivateInclude(Modul<br>
> const FileEntry *IncFileEnt,<br>
> ModuleMap::ModuleHeaderRole Role,<br>
> Module *RequestedModule) {<br>
> - #ifndef NDEBUG<br>
> + bool IsPrivateRole = Role & ModuleMap::PrivateHeader;<br>
> +#ifndef NDEBUG<br>
> // Check for consistency between the module header role<br>
> // as obtained from the lookup and as obtained from the module.<br>
> // This check is not cheap, so enable it only for debugging.<br>
> - SmallVectorImpl<const FileEntry *> &PvtHdrs<br>
> - = RequestedModule->PrivateHeaders;<br>
> - SmallVectorImpl<const FileEntry *>::iterator Look<br>
> - = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt);<br>
> - bool IsPrivate = Look != PvtHdrs.end();<br>
> - assert((IsPrivate && Role == ModuleMap::PrivateHeader)<br>
> - || (!IsPrivate && Role != ModuleMap::PrivateHeader));<br>
> - #endif<br>
> - return Role == ModuleMap::PrivateHeader &&<br>
> + bool IsPrivate = false;<br>
> + for (auto *Hdrs : {&RequestedModule->PrivateHeaders,<br>
> + &RequestedModule->PrivateTextualHeaders})<br>
> + IsPrivate |=<br>
> + std::find(Hdrs->begin(), Hdrs->end(), IncFileEnt) != Hdrs->end();<br>
> + assert(IsPrivate == IsPrivateRole && "inconsistent headers and roles");<br>
> +#endif<br>
> + return IsPrivateRole &&<br>
> RequestedModule->getTopLevelModule() != RequestingModule;<br>
> }<br>
><br>
> @@ -316,13 +316,13 @@ ModuleMap::findModuleForHeader(const Fil<br>
> HeadersMap::iterator Known = findKnownHeader(File);<br>
><br>
> auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {<br>
> - if (!IncludeTextualHeaders && R.getRole() == ModuleMap::TextualHeader)<br>
> + if (!IncludeTextualHeaders && (R.getRole() & ModuleMap::TextualHeader))<br>
> return ModuleMap::KnownHeader();<br>
> return R;<br>
> };<br>
><br>
> if (Known != Headers.end()) {<br>
> - ModuleMap::KnownHeader Result = KnownHeader();<br>
> + ModuleMap::KnownHeader Result;<br>
><br>
> // Iterate over all modules that 'File' is part of to find the best fit.<br>
> for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),<br>
> @@ -343,14 +343,9 @@ ModuleMap::findModuleForHeader(const Fil<br>
> !directlyUses(RequestingModule, I->getModule()))<br>
> continue;<br>
><br>
> - Result = *I;<br>
> - // If 'File' is a public header of this module, this is as good as we<br>
> - // are going to get.<br>
> - // FIXME: If we have a RequestingModule, we should prefer the header from<br>
> - // that module.<br>
> - if (I->getRole() == ModuleMap::NormalHeader ||<br>
> - I->getRole() == ModuleMap::TextualHeader)<br>
> - break;<br>
> + // Prefer a public header over a private header.<br>
> + if (!Result || (Result.getRole() & ModuleMap::PrivateHeader))<br>
> + Result = *I;<br>
> }<br>
> return MakeResult(Result);<br>
> }<br>
> @@ -783,13 +778,12 @@ void ModuleMap::setUmbrellaDir(Module *M<br>
><br>
> void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,<br>
> ModuleHeaderRole Role) {<br>
> - if (Role == TextualHeader) {<br>
> - Mod->TextualHeaders.push_back(Header);<br>
> - } else {<br>
> - if (Role == PrivateHeader)<br>
> - Mod->PrivateHeaders.push_back(Header);<br>
> - else<br>
> - Mod->NormalHeaders.push_back(Header);<br>
> + auto HeaderLists = {&Mod->NormalHeaders, &Mod->PrivateHeaders,<br>
> + &Mod->TextualHeaders, &Mod->PrivateTextualHeaders};<br>
> + assert(Role >= 0 && Role < HeaderLists.size() && "unknown header role");<br>
> + HeaderLists.begin()[Role]->push_back(Header);<br>
> +<br>
> + if (!(Role & TextualHeader)) {<br>
> bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;<br>
> HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader);<br>
> }<br>
<br>
MSC17 (aka VS2012) doesn't like it.<br>
<a href="http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/11174" target="_blank">http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/11174</a><br>
<br>
May I rewrite it into like?<br>
<br>
switch ((int)Role) {<br>
default: llvm_unreachable("unknown header role");<br>
case NormalHeader: Mod->NormalHeaders.push_back(Header); break;<br>
case PrivateHeader: Mod->PrivateHeaders.push_back(Header); break;<br>
case TextualHeader: Mod->TextualHeaders.push_back(Header); break;<br>
case PrivateHeader | TextualHeader:<br>
Mod->PrivateTextualHeaders.push_back(Header); break;<br>
}<br>
<br>
> @@ -1475,16 +1469,9 @@ void ModuleMapParser::parseModuleDecl()<br>
> parseRequiresDecl();<br>
> break;<br>
><br>
> - case MMToken::TextualKeyword: {<br>
> - SourceLocation TextualLoc = consumeToken();<br>
> - if (Tok.is(MMToken::HeaderKeyword)) {<br>
> - parseHeaderDecl(MMToken::TextualKeyword, TextualLoc);<br>
> - } else {<br>
> - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)<br>
> - << "textual";<br>
> - }<br>
> + case MMToken::TextualKeyword:<br>
> + parseHeaderDecl(MMToken::TextualKeyword, consumeToken());<br>
> break;<br>
> - }<br>
><br>
> case MMToken::UmbrellaKeyword: {<br>
> SourceLocation UmbrellaLoc = consumeToken();<br>
> @@ -1494,31 +1481,17 @@ void ModuleMapParser::parseModuleDecl()<br>
> parseUmbrellaDirDecl(UmbrellaLoc);<br>
> break;<br>
> }<br>
> -<br>
> - case MMToken::ExcludeKeyword: {<br>
> - SourceLocation ExcludeLoc = consumeToken();<br>
> - if (Tok.is(MMToken::HeaderKeyword)) {<br>
> - parseHeaderDecl(MMToken::ExcludeKeyword, ExcludeLoc);<br>
> - } else {<br>
> - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)<br>
> - << "exclude";<br>
> - }<br>
> +<br>
> + case MMToken::ExcludeKeyword:<br>
> + parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());<br>
> break;<br>
> - }<br>
> -<br>
> - case MMToken::PrivateKeyword: {<br>
> - SourceLocation PrivateLoc = consumeToken();<br>
> - if (Tok.is(MMToken::HeaderKeyword)) {<br>
> - parseHeaderDecl(MMToken::PrivateKeyword, PrivateLoc);<br>
> - } else {<br>
> - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)<br>
> - << "private";<br>
> - }<br>
> +<br>
> + case MMToken::PrivateKeyword:<br>
> + parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());<br>
> break;<br>
> - }<br>
> -<br>
> +<br>
> case MMToken::HeaderKeyword:<br>
> - parseHeaderDecl(MMToken::HeaderKeyword, SourceLocation());<br>
> + parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());<br>
> break;<br>
><br>
> case MMToken::LinkKeyword:<br>
> @@ -1673,16 +1646,37 @@ static void appendSubframeworkPaths(Modu<br>
> /// \brief Parse a header declaration.<br>
> ///<br>
> /// header-declaration:<br>
> -/// 'exclude'[opt] 'header' string-literal<br>
> -/// 'private'[opt] 'header' string-literal<br>
> /// 'textual'[opt] 'header' string-literal<br>
> -/// 'umbrella'[opt] 'header' string-literal<br>
> +/// 'private' 'textual'[opt] 'header' string-literal<br>
> +/// 'exclude' 'header' string-literal<br>
> +/// 'umbrella' 'header' string-literal<br>
> ///<br>
> /// FIXME: Support 'private textual header'.<br>
> void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,<br>
> SourceLocation LeadingLoc) {<br>
> - assert(Tok.is(MMToken::HeaderKeyword));<br>
> - consumeToken();<br>
> + // We've already consumed the first token.<br>
> + ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;<br>
> + if (LeadingToken == MMToken::PrivateKeyword) {<br>
> + Role = ModuleMap::PrivateHeader;<br>
> + // 'private' may optionally be followed by 'textual'.<br>
> + if (Tok.is(MMToken::TextualKeyword)) {<br>
> + LeadingToken = Tok.Kind;<br>
> + consumeToken();<br>
> + }<br>
> + }<br>
> + if (LeadingToken == MMToken::TextualKeyword)<br>
> + Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);<br>
> +<br>
> + if (LeadingToken != MMToken::HeaderKeyword) {<br>
> + if (!Tok.is(MMToken::HeaderKeyword)) {<br>
> + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)<br>
> + << (LeadingToken == MMToken::PrivateKeyword ? "private" :<br>
> + LeadingToken == MMToken::ExcludeKeyword ? "exclude" :<br>
> + LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");<br>
> + return;<br>
> + }<br>
> + consumeToken();<br>
> + }<br>
><br>
> // Parse the header name.<br>
> if (!Tok.is(MMToken::StringLiteral)) {<br>
> @@ -1770,21 +1764,13 @@ void ModuleMapParser::parseHeaderDecl(MM<br>
> } else if (LeadingToken == MMToken::ExcludeKeyword) {<br>
> Map.excludeHeader(ActiveModule, File);<br>
> } else {<br>
> - // Record this header.<br>
> - ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;<br>
> - if (LeadingToken == MMToken::PrivateKeyword)<br>
> - Role = ModuleMap::PrivateHeader;<br>
> - else if (LeadingToken == MMToken::TextualKeyword)<br>
> - Role = ModuleMap::TextualHeader;<br>
> - else<br>
> - assert(LeadingToken == MMToken::HeaderKeyword);<br>
> -<br>
> // If there is a builtin counterpart to this file, add it now, before<br>
> // the "real" header, so we build the built-in one first when building<br>
> // the module.<br>
> if (BuiltinFile)<br>
> Map.addHeader(ActiveModule, BuiltinFile, Role);<br>
><br>
> + // Record this header.<br>
> Map.addHeader(ActiveModule, File, Role);<br>
> }<br>
> } else if (LeadingToken != MMToken::ExcludeKeyword) {<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Oct 24 15:23:01 2014<br>
> @@ -4461,26 +4461,19 @@ ASTReader::ReadSubmoduleBlock(ModuleFile<br>
> break;<br>
> }<br>
><br>
> - case SUBMODULE_HEADER: {<br>
> - // We lazily associate headers with their modules via the HeaderInfoTable.<br>
> + case SUBMODULE_HEADER:<br>
> + case SUBMODULE_EXCLUDED_HEADER:<br>
> + case SUBMODULE_PRIVATE_HEADER:<br>
> + // We lazily associate headers with their modules via the HeaderInfo table.<br>
> // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead<br>
> // of complete filenames or remove it entirely.<br>
> - break;<br>
> - }<br>
> -<br>
> - case SUBMODULE_EXCLUDED_HEADER: {<br>
> - // We lazily associate headers with their modules via the HeaderInfoTable.<br>
> - // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead<br>
> - // of complete filenames or remove it entirely.<br>
> - break;<br>
> - }<br>
> + break;<br>
><br>
> - case SUBMODULE_PRIVATE_HEADER: {<br>
> - // We lazily associate headers with their modules via the HeaderInfoTable.<br>
> - // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead<br>
> - // of complete filenames or remove it entirely.<br>
> - break;<br>
> - }<br>
> + case SUBMODULE_TEXTUAL_HEADER:<br>
> + case SUBMODULE_PRIVATE_TEXTUAL_HEADER:<br>
> + // FIXME: Textual headers are not marked in the HeaderInfo table. Load<br>
> + // them here.<br>
> + break;<br>
><br>
> case SUBMODULE_TOPHEADER: {<br>
> CurrentModule->addTopHeaderFilename(Blob);<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Oct 24 15:23:01 2014<br>
> @@ -2370,7 +2370,7 @@ void ASTWriter::WriteSubmodules(Module *<br>
> }<br>
><br>
> // Enter the submodule description block.<br>
> - Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/4);<br>
> + Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);<br>
><br>
> // Write the abbreviations needed for the submodules block.<br>
> using namespace llvm;<br>
> @@ -2431,6 +2431,11 @@ void ASTWriter::WriteSubmodules(Module *<br>
> unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(Abbrev);<br>
><br>
> Abbrev = new BitCodeAbbrev();<br>
> + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER));<br>
> + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name<br>
> + unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(Abbrev);<br>
> +<br>
> + Abbrev = new BitCodeAbbrev();<br>
> Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));<br>
> Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework<br>
> Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name<br>
> @@ -2504,40 +2509,25 @@ void ASTWriter::WriteSubmodules(Module *<br>
> }<br>
><br>
> // Emit the headers.<br>
> - for (unsigned I = 0, N = Mod->NormalHeaders.size(); I != N; ++I) {<br>
> - Record.clear();<br>
> - Record.push_back(SUBMODULE_HEADER);<br>
> - Stream.EmitRecordWithBlob(HeaderAbbrev, Record,<br>
> - Mod->NormalHeaders[I]->getName());<br>
> - }<br>
> - // Emit the excluded headers.<br>
> - for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {<br>
> - Record.clear();<br>
> - Record.push_back(SUBMODULE_EXCLUDED_HEADER);<br>
> - Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,<br>
> - Mod->ExcludedHeaders[I]->getName());<br>
> - }<br>
> - // Emit the textual headers.<br>
> - for (unsigned I = 0, N = Mod->TextualHeaders.size(); I != N; ++I) {<br>
> - Record.clear();<br>
> - Record.push_back(SUBMODULE_TEXTUAL_HEADER);<br>
> - Stream.EmitRecordWithBlob(TextualHeaderAbbrev, Record,<br>
> - Mod->TextualHeaders[I]->getName());<br>
> - }<br>
> - // Emit the private headers.<br>
> - for (unsigned I = 0, N = Mod->PrivateHeaders.size(); I != N; ++I) {<br>
> - Record.clear();<br>
> - Record.push_back(SUBMODULE_PRIVATE_HEADER);<br>
> - Stream.EmitRecordWithBlob(PrivateHeaderAbbrev, Record,<br>
> - Mod->PrivateHeaders[I]->getName());<br>
> - }<br>
> - ArrayRef<const FileEntry *><br>
> - TopHeaders = Mod->getTopHeaders(PP->getFileManager());<br>
> - for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {<br>
> - Record.clear();<br>
> - Record.push_back(SUBMODULE_TOPHEADER);<br>
> - Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record,<br>
> - TopHeaders[I]->getName());<br>
> + struct {<br>
> + unsigned Kind;<br>
> + unsigned Abbrev;<br>
> + ArrayRef<const FileEntry*> Headers;<br>
> + } HeaderLists[] = {<br>
> + {SUBMODULE_HEADER, HeaderAbbrev, Mod->NormalHeaders},<br>
> + {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Mod->TextualHeaders},<br>
> + {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Mod->PrivateHeaders},<br>
> + {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev,<br>
> + Mod->PrivateTextualHeaders},<br>
> + {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Mod->ExcludedHeaders},<br>
> + {SUBMODULE_TOPHEADER, TopHeaderAbbrev,<br>
> + Mod->getTopHeaders(PP->getFileManager())}<br>
> + };<br>
> + for (auto &HL : HeaderLists) {<br>
> + Record.clear();<br>
> + Record.push_back(HL.Kind);<br>
> + for (auto *H : HL.Headers)<br>
> + Stream.EmitRecordWithBlob(HL.Abbrev, Record, H->getName());<br>
> }<br>
><br>
> // Emit the imports.<br>
><br>
> Modified: cfe/trunk/test/Modules/Inputs/declare-use/module.map<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/module.map?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/declare-use/module.map?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Modules/Inputs/declare-use/module.map (original)<br>
> +++ cfe/trunk/test/Modules/Inputs/declare-use/module.map Fri Oct 24 15:23:01 2014<br>
> @@ -61,5 +61,10 @@ module XL {<br>
> textual header "l.h"<br>
> }<br>
><br>
> +module XM {<br>
> + private textual header "m.h"<br>
> + textual header "m2.h"<br>
> +}<br>
> +<br>
> module XS {<br>
> }<br>
><br>
> Modified: cfe/trunk/test/Modules/textual-headers.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/textual-headers.cpp?rev=220589&r1=220588&r2=220589&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/textual-headers.cpp?rev=220589&r1=220588&r2=220589&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Modules/textual-headers.cpp (original)<br>
> +++ cfe/trunk/test/Modules/textual-headers.cpp Fri Oct 24 15:23:01 2014<br>
> @@ -1,6 +1,6 @@<br>
> // RUN: rm -rf %t<br>
> // RUN: %clang_cc1 -fmodule-maps -fmodules-cache-path=%t -fmodules-strict-decluse -fmodule-name=XG -I %S/Inputs/declare-use %s -verify<br>
> -// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-strict-decluse -fmodule-name=XG -I %S/Inputs/declare-use %s -verify<br>
> +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-strict-decluse -fmodule-name=XG -I %S/Inputs/declare-use %s -verify -fno-modules-error-recovery<br>
><br>
> #define GIMME_A_K<br>
> #include "k.h"<br>
> @@ -8,4 +8,11 @@<br>
> #define GIMME_AN_L<br>
> #include "l.h" // expected-error {{module XG does not depend on a module exporting 'l.h'}}<br>
><br>
> +#include "m2.h" // expected-error {{module XG does not depend on a module exporting 'm2.h'}}<br>
> +const int use_m = m; // expected-error {{undeclared identifier}}<br>
> +<br>
> +#define GIMME_AN_M<br>
> +#include "m.h" // expected-error {{use of private header from outside its module: 'm.h'}}<br>
> +const int use_m_2 = m;<br>
> +<br>
> const int g = k + l;<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>