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

Douglas Gregor dgregor at apple.com
Tue Mar 19 18:53:52 PDT 2013


It's my bug. I forgot to deserialize the new Module bit in the submodule definition. I'm AFK but can fix in a few hours ;(

Sent from my iPhone

On Mar 19, 2013, at 5:52 PM, David Blaikie <dblaikie at gmail.com> wrote:

> 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