r177466 - <rdar://problem/10796651> Introduce configuration macros into module maps.

David Blaikie dblaikie at gmail.com
Tue Mar 19 17:52:22 PDT 2013


On Tue, Mar 19, 2013 at 5:22 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Author: dgregor
> Date: Tue Mar 19 19:22:05 2013
> New Revision: 177466
>
> URL: http://llvm.org/viewvc/llvm-project?rev=177466&view=rev
> Log:
> <rdar://problem/10796651> Introduce configuration macros into module maps.
>
> Configuration macros are macros that are intended to alter how a
> module works, such that we need to build different module variants
> for different values of these macros. A module can declare its
> configuration macros, in which case we will complain if the definition
> of a configation macro on the command line (or lack thereof) differs
> from the current preprocessor state at the point where the module is
> imported. This should eliminate some surprises when enabling modules,
> because "#define CONFIG_MACRO ..." followed by "#include
> <module/header.h>" would silently ignore the CONFIG_MACRO setting. At
> least it will no longer be silent about it.
>
> Configuration macros are eventually intended to help reduce the number
> of module variants that need to be built. When the list of
> configuration macros for a module is exhaustive, we only need to
> consider the settings for those macros when building/finding the
> module, which can help isolate modules for various project-specific -D
> flags that should never affect how modules are build (but currently do).

Looks like this might be breaking some things
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-debian-fast/builds/542
(though my revision was blamed, the previous build was from before
your commit - not sure what went wrong with the blame range there)

> Added:
>     cfe/trunk/test/Modules/Inputs/config.h
>     cfe/trunk/test/Modules/config_macros.m
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
>     cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>     cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
>     cfe/trunk/include/clang/Basic/Module.h
>     cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>     cfe/trunk/lib/Basic/Module.cpp
>     cfe/trunk/lib/Frontend/CompilerInstance.cpp
>     cfe/trunk/lib/Lex/ModuleMap.cpp
>     cfe/trunk/lib/Serialization/ASTReader.cpp
>     cfe/trunk/lib/Serialization/ASTWriter.cpp
>     cfe/trunk/test/Modules/Inputs/module.map
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Tue Mar 19 19:22:05 2013
> @@ -137,5 +137,11 @@ def warn_missing_submodule : Warning<"mi
>  def err_module_map_temp_file : Error<
>    "unable to write temporary module map file '%0'">, DefaultFatal;
>  def err_module_unavailable : Error<"module '%0' requires feature '%1'">;
> -
> +def warn_module_config_macro_undef : Warning<
> +  "%select{definition|#undef}0 of configuration macro '%1' has no effect on "
> +  "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line "
> +  "to configure the module">,
> +  InGroup<ConfigMacros>;
> +def note_module_def_undef_here : Note<
> +  "macro was %select{defined|#undef'd}0 here">;
>  }
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Mar 19 19:22:05 2013
> @@ -47,6 +47,7 @@ def CastAlign : DiagGroup<"cast-align">;
>  def : DiagGroup<"cast-qual">;
>  def : DiagGroup<"char-align">;
>  def Comment : DiagGroup<"comment">;
> +def ConfigMacros : DiagGroup<"config-macros">;
>  def : DiagGroup<"ctor-dtor-privacy">;
>  def GNUDesignator : DiagGroup<"gnu-designator">;
>
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Tue Mar 19 19:22:05 2013
> @@ -532,6 +532,10 @@ def err_mmap_export_module_id : Error<
>    "expected an exported 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<
> +  "configuration macros are only allowed on top-level modules">;
> +def err_mmap_expected_config_macro : Error<
> +  "expected configuration macro name after ','">;
>  def err_mmap_missing_module_unqualified : Error<
>    "no module named '%0' visible from '%1'">;
>  def err_mmap_missing_module_qualified : Error<
>
> Modified: cfe/trunk/include/clang/Basic/Module.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Module.h (original)
> +++ cfe/trunk/include/clang/Basic/Module.h Tue Mar 19 19:22:05 2013
> @@ -119,7 +119,14 @@ public:
>    /// \brief Whether, when inferring submodules, the inferr submodules should
>    /// export all modules they import (e.g., the equivalent of "export *").
>    unsigned InferExportWildcard : 1;
> -
> +
> +  /// \brief Whether the set of configuration macros is exhaustive.
> +  ///
> +  /// When the set of configuration macros is exhaustive, meaning
> +  /// that no identifier not in this list should affect how the module is
> +  /// built.
> +  unsigned ConfigMacrosExhaustive : 1;
> +
>    /// \brief Describes the visibility of the various names within a
>    /// particular module.
>    enum NameVisibilityKind {
> @@ -190,6 +197,10 @@ public:
>    /// an entity from this module is used.
>    llvm::SmallVector<LinkLibrary, 2> LinkLibraries;
>
> +  /// \brief The set of "configuration macros", which are macros that
> +  /// (intentionally) change how this module is built.
> +  std::vector<std::string> ConfigMacros;
> +
>    /// \brief Construct a top-level module.
>    explicit Module(StringRef Name, SourceLocation DefinitionLoc,
>                    bool IsFramework)
> @@ -197,7 +208,8 @@ public:
>        IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
>        IsExplicit(false), IsSystem(false),
>        InferSubmodules(false), InferExplicitSubmodules(false),
> -      InferExportWildcard(false), NameVisibility(Hidden) { }
> +      InferExportWildcard(false), ConfigMacrosExhaustive(false),
> +      NameVisibility(Hidden) { }
>
>    /// \brief Construct a new module or submodule.
>    Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
> @@ -328,7 +340,7 @@ public:
>    ///
>    /// \returns The submodule if found, or NULL otherwise.
>    Module *findSubmodule(StringRef Name) const;
> -
> +
>    typedef std::vector<Module *>::iterator submodule_iterator;
>    typedef std::vector<Module *>::const_iterator submodule_const_iterator;
>
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Mar 19 19:22:05 2013
> @@ -609,7 +609,9 @@ namespace clang {
>        /// from this submodule.
>        SUBMODULE_EXCLUDED_HEADER = 9,
>        /// \brief Specifies a library or framework to link against.
> -      SUBMODULE_LINK_LIBRARY = 10
> +      SUBMODULE_LINK_LIBRARY = 10,
> +      /// \brief Specifies a configuration macro for this module.
> +      SUBMODULE_CONFIG_MACRO = 11
>      };
>
>      /// \brief Record types used within a comments block.
>
> Modified: cfe/trunk/lib/Basic/Module.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Basic/Module.cpp (original)
> +++ cfe/trunk/lib/Basic/Module.cpp Tue Mar 19 19:22:05 2013
> @@ -279,7 +279,19 @@ void Module::print(raw_ostream &OS, unsi
>      OS.write_escaped(UmbrellaDir->getName());
>      OS << "\"\n";
>    }
> -
> +
> +  if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
> +    OS.indent(Indent + 2);
> +    OS << "config_macros ";
> +    if (ConfigMacrosExhaustive)
> +      OS << "[exhausive]";
> +    for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
> +      if (I)
> +        OS << ", ";
> +      OS << ConfigMacros[I];
> +    }
> +  }
> +
>    for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
>      OS.indent(Indent + 2);
>      OS << "header \"";
>
> Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
> +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Tue Mar 19 19:22:05 2013
> @@ -905,6 +905,96 @@ static void compileModule(CompilerInstan
>    }
>  }
>
> +/// \brief Diagnose differences between the current definition of the given
> +/// configuration macro and the definition provided on the command line.
> +static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
> +                             Module *Mod, SourceLocation ImportLoc) {
> +  IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
> +  SourceManager &SourceMgr = PP.getSourceManager();
> +
> +  // If this identifier has never had a macro definition, then it could
> +  // not have changed.
> +  if (!Id->hadMacroDefinition())
> +    return;
> +
> +  // If this identifier does not currently have a macro definition,
> +  // check whether it had one on the command line.
> +  if (!Id->hasMacroDefinition()) {
> +    MacroDirective *UndefMD = PP.getMacroDirectiveHistory(Id);
> +    for (MacroDirective *MD = UndefMD; MD; MD = MD->getPrevious()) {
> +
> +      FileID FID = SourceMgr.getFileID(MD->getLocation());
> +      if (FID.isInvalid())
> +        continue;
> +
> +      const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FID);
> +      if (!Buffer)
> +        continue;
> +
> +      // We only care about the predefines buffer.
> +      if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>"))
> +        continue;
> +
> +      // This macro was defined on the command line, then #undef'd later.
> +      // Complain.
> +      PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
> +        << true << ConfigMacro << Mod->getFullModuleName();
> +      if (UndefMD->getUndefLoc().isValid())
> +        PP.Diag(UndefMD->getUndefLoc(), diag::note_module_def_undef_here)
> +          << true;
> +      return;
> +    }
> +
> +    // Okay: no definition in the predefines buffer.
> +    return;
> +  }
> +
> +  // This identifier has a macro definition. Check whether we had a definition
> +  // on the command line.
> +  MacroDirective *DefMD = PP.getMacroDirective(Id);
> +  MacroDirective *PredefinedMD = 0;
> +  for (MacroDirective *MD = DefMD; MD; MD = MD->getPrevious()) {
> +    FileID FID = SourceMgr.getFileID(MD->getLocation());
> +    if (FID.isInvalid())
> +      continue;
> +
> +    const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FID);
> +    if (!Buffer)
> +      continue;
> +
> +    // We only care about the predefines buffer.
> +    if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>"))
> +      continue;
> +
> +    PredefinedMD = MD;
> +    break;
> +  }
> +
> +  // If there was no definition for this macro in the predefines buffer,
> +  // complain.
> +  if (!PredefinedMD ||
> +      (!PredefinedMD->getLocation().isValid() &&
> +       PredefinedMD->getUndefLoc().isValid())) {
> +    PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
> +      << false << ConfigMacro << Mod->getFullModuleName();
> +    PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
> +      << false;
> +    return;
> +  }
> +
> +  // If the current macro definition is the same as the predefined macro
> +  // definition, it's okay.
> +  if (DefMD == PredefinedMD ||
> +      DefMD->getInfo()->isIdenticalTo(*PredefinedMD->getInfo(), PP))
> +    return;
> +
> +  // The macro definitions differ.
> +  PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
> +    << false << ConfigMacro << Mod->getFullModuleName();
> +  PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
> +    << false;
> +}
> +
>  ModuleLoadResult
>  CompilerInstance::loadModule(SourceLocation ImportLoc,
>                               ModuleIdPath Path,
> @@ -1177,7 +1267,14 @@ CompilerInstance::loadModule(SourceLocat
>
>      ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
>    }
> -
> +
> +  // Check for any configuration macros that have changed.
> +  clang::Module *TopModule = Module->getTopLevelModule();
> +  for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
> +    checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
> +                     Module, ImportLoc);
> +  }
> +
>    // If this module import was due to an inclusion directive, create an
>    // implicit import declaration to capture it in the AST.
>    if (IsInclusionDirective && hasASTContext()) {
>
> Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
> +++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Mar 19 19:22:05 2013
> @@ -643,6 +643,7 @@ namespace clang {
>    struct MMToken {
>      enum TokenKind {
>        Comma,
> +      ConfigMacros,
>        EndOfFile,
>        HeaderKeyword,
>        Identifier,
> @@ -687,10 +688,13 @@ namespace clang {
>
>    /// \brief The set of attributes that can be attached to a module.
>    struct Attributes {
> -    Attributes() : IsSystem() { }
> +    Attributes() : IsSystem(), IsExhaustive() { }
>
>      /// \brief Whether this is a system module.
>      unsigned IsSystem : 1;
> +
> +    /// \brief Whether this is an exhaustive set of configuration macros.
> +    unsigned IsExhaustive : 1;
>    };
>
>
> @@ -739,6 +743,7 @@ namespace clang {
>      void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
>      void parseExportDecl();
>      void parseLinkDecl();
> +    void parseConfigMacros();
>      void parseInferredModuleDecl(bool Framework, bool Explicit);
>      bool parseOptionalAttributes(Attributes &Attrs);
>
> @@ -776,11 +781,12 @@ retry:
>      Tok.StringData = LToken.getRawIdentifierData();
>      Tok.StringLength = LToken.getLength();
>      Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
> -                 .Case("header", MMToken::HeaderKeyword)
> +                 .Case("config_macros", MMToken::ConfigMacros)
>                   .Case("exclude", MMToken::ExcludeKeyword)
>                   .Case("explicit", MMToken::ExplicitKeyword)
>                   .Case("export", MMToken::ExportKeyword)
>                   .Case("framework", MMToken::FrameworkKeyword)
> +                 .Case("header", MMToken::HeaderKeyword)
>                   .Case("link", MMToken::LinkKeyword)
>                   .Case("module", MMToken::ModuleKeyword)
>                   .Case("requires", MMToken::RequiresKeyword)
> @@ -937,7 +943,9 @@ namespace {
>      /// \brief An unknown attribute.
>      AT_unknown,
>      /// \brief The 'system' attribute.
> -    AT_system
> +    AT_system,
> +    /// \brief The 'exhaustive' attribute.
> +    AT_exhaustive
>    };
>  }
>
> @@ -1094,7 +1102,11 @@ void ModuleMapParser::parseModuleDecl()
>      case MMToken::RBrace:
>        Done = true;
>        break;
> -
> +
> +    case MMToken::ConfigMacros:
> +      parseConfigMacros();
> +      break;
> +
>      case MMToken::ExplicitKeyword:
>      case MMToken::FrameworkKeyword:
>      case MMToken::ModuleKeyword:
> @@ -1489,6 +1501,59 @@ void ModuleMapParser::parseLinkDecl() {
>                                                              IsFramework));
>  }
>
> +/// \brief Parse a configuration macro declaration.
> +///
> +///   module-declaration:
> +///     'config_macros' attributes[opt] config-macro-list?
> +///
> +///   config-macro-list:
> +///     identifier (',' identifier)?
> +void ModuleMapParser::parseConfigMacros() {
> +  assert(Tok.is(MMToken::ConfigMacros));
> +  SourceLocation ConfigMacrosLoc = consumeToken();
> +
> +  // Only top-level modules can have configuration macros.
> +  if (ActiveModule->Parent) {
> +    Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
> +  }
> +
> +  // Parse the optional attributes.
> +  Attributes Attrs;
> +  parseOptionalAttributes(Attrs);
> +  if (Attrs.IsExhaustive && !ActiveModule->Parent) {
> +    ActiveModule->ConfigMacrosExhaustive = true;
> +  }
> +
> +  // If we don't have an identifier, we're done.
> +  if (!Tok.is(MMToken::Identifier))
> +    return;
> +
> +  // Consume the first identifier.
> +  if (!ActiveModule->Parent) {
> +    ActiveModule->ConfigMacros.push_back(Tok.getString().str());
> +  }
> +  consumeToken();
> +
> +  do {
> +    // If there's a comma, consume it.
> +    if (!Tok.is(MMToken::Comma))
> +      break;
> +    consumeToken();
> +
> +    // We expect to see a macro name here.
> +    if (!Tok.is(MMToken::Identifier)) {
> +      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
> +      break;
> +    }
> +
> +    // Consume the macro name.
> +    if (!ActiveModule->Parent) {
> +      ActiveModule->ConfigMacros.push_back(Tok.getString().str());
> +    }
> +    consumeToken();
> +  } while (true);
> +}
> +
>  /// \brief Parse an inferred module declaration (wildcard modules).
>  ///
>  ///   module-declaration:
> @@ -1668,6 +1733,7 @@ bool ModuleMapParser::parseOptionalAttri
>      // Decode the attribute name.
>      AttributeKind Attribute
>        = llvm::StringSwitch<AttributeKind>(Tok.getString())
> +          .Case("exhaustive", AT_exhaustive)
>            .Case("system", AT_system)
>            .Default(AT_unknown);
>      switch (Attribute) {
> @@ -1679,6 +1745,10 @@ bool ModuleMapParser::parseOptionalAttri
>      case AT_system:
>        Attrs.IsSystem = true;
>        break;
> +
> +    case AT_exhaustive:
> +      Attrs.IsExhaustive = true;
> +      break;
>      }
>      consumeToken();
>
> @@ -1730,6 +1800,7 @@ bool ModuleMapParser::parseModuleMapFile
>        break;
>
>      case MMToken::Comma:
> +    case MMToken::ConfigMacros:
>      case MMToken::ExcludeKeyword:
>      case MMToken::ExportKeyword:
>      case MMToken::HeaderKeyword:
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Mar 19 19:22:05 2013
> @@ -3718,6 +3718,18 @@ bool ASTReader::ReadSubmoduleBlock(Modul
>        CurrentModule->LinkLibraries.push_back(
>                                           Module::LinkLibrary(Blob, Record[0]));
>        break;
> +
> +    case SUBMODULE_CONFIG_MACRO:
> +      if (First) {
> +        Error("missing submodule metadata record at beginning of block");
> +        return true;
> +      }
> +
> +      if (!CurrentModule)
> +        break;
> +
> +      CurrentModule->ConfigMacros.push_back(Blob.str());
> +      break;
>      }
>    }
>  }
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Mar 19 19:22:05 2013
> @@ -2135,6 +2135,7 @@ void ASTWriter::WriteSubmodules(Module *
>    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...
>    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
>    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
> +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...
>    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
>    unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev);
>
> @@ -2174,6 +2175,11 @@ void ASTWriter::WriteSubmodules(Module *
>    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));     // Name
>    unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(Abbrev);
>
> +  Abbrev = new BitCodeAbbrev();
> +  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO));
> +  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));    // Macro name
> +  unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(Abbrev);
> +
>    // Write the submodule metadata block.
>    RecordData Record;
>    Record.push_back(getNumberOfModules(WritingModule));
> @@ -2204,6 +2210,7 @@ void ASTWriter::WriteSubmodules(Module *
>      Record.push_back(Mod->InferSubmodules);
>      Record.push_back(Mod->InferExplicitSubmodules);
>      Record.push_back(Mod->InferExportWildcard);
> +    Record.push_back(Mod->ConfigMacrosExhaustive);
>      Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
>
>      // Emit the requirements.
> @@ -2288,6 +2295,14 @@ void ASTWriter::WriteSubmodules(Module *
>                                  Mod->LinkLibraries[I].Library);
>      }
>
> +    // Emit the configuration macros.
> +    for (unsigned I = 0, N =  Mod->ConfigMacros.size(); I != N; ++I) {
> +      Record.clear();
> +      Record.push_back(SUBMODULE_CONFIG_MACRO);
> +      Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record,
> +                                Mod->ConfigMacros[I]);
> +    }
> +
>      // Queue up the submodules of this module.
>      for (Module::submodule_iterator Sub = Mod->submodule_begin(),
>                                   SubEnd = Mod->submodule_end();
>
> Added: cfe/trunk/test/Modules/Inputs/config.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/config.h?rev=177466&view=auto
> ==============================================================================
> --- cfe/trunk/test/Modules/Inputs/config.h (added)
> +++ cfe/trunk/test/Modules/Inputs/config.h Tue Mar 19 19:22:05 2013
> @@ -0,0 +1,7 @@
> +#ifdef WANT_FOO
> +int* foo();
> +#endif
> +
> +#ifdef WANT_BAR
> +char *bar();
> +#endif
>
> Modified: cfe/trunk/test/Modules/Inputs/module.map
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=177466&r1=177465&r2=177466&view=diff
> ==============================================================================
> --- cfe/trunk/test/Modules/Inputs/module.map (original)
> +++ cfe/trunk/test/Modules/Inputs/module.map Tue Mar 19 19:22:05 2013
> @@ -183,3 +183,8 @@ module cxx_inline_namespace {
>  module cxx_linkage_cache {
>    header "cxx-linkage-cache.h"
>  }
> +
> +module config {
> +  header "config.h"
> +  config_macros [exhaustive] WANT_FOO, WANT_BAR
> +}
>
> Added: cfe/trunk/test/Modules/config_macros.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/config_macros.m?rev=177466&view=auto
> ==============================================================================
> --- cfe/trunk/test/Modules/config_macros.m (added)
> +++ cfe/trunk/test/Modules/config_macros.m Tue Mar 19 19:22:05 2013
> @@ -0,0 +1,28 @@
> + at import config;
> +
> +int *test_foo() {
> +  return foo();
> +}
> +
> +char *test_bar() {
> +  return bar(); // expected-warning{{implicit declaration of function 'bar' is invalid in C99}} \
> +                // expected-warning{{incompatible integer to pointer conversion}}
> +}
> +
> +#undef WANT_FOO // expected-note{{macro was #undef'd here}}
> + at import config; // expected-warning{{#undef of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-UWANT_FOO' on the command line to configure the module}}
> +
> +#define WANT_FOO 2 // expected-note{{macro was defined here}}
> + at import config; // expected-warning{{definition of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-DWANT_FOO=...' on the command line to configure the module}}
> +
> +#undef WANT_FOO
> +#define WANT_FOO 1
> + at import config; // okay
> +
> +#define WANT_BAR 1 // expected-note{{macro was defined here}}
> + at import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}}
> +
> +// RUN: rm -rf %t
> +// RUN: %clang_cc1 -fmodules -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.map
> +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -DWANT_FOO=1 %s -verify
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list