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