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