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

Douglas Gregor dgregor at apple.com
Tue Apr 2 20:17:59 PDT 2013


On Mar 25, 2013, at 3:18 PM, Argyrios Kyrtzidis <kyrtzidis at apple.com> wrote:

> On 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).
>> 
>> 
>> 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;
> 
> You can use something like
> 
> if (FID != PP.getPredefinesFileID())
>  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;
> 
> Same here.


r178616, thanks!

	- Doug




More information about the cfe-commits mailing list