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

Argyrios Kyrtzidis kyrtzidis at apple.com
Mon Mar 25 15:18:57 PDT 2013


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.

-Argyrios



More information about the cfe-commits mailing list