<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>