On Mar 19, 2013, at 5:22 PM, Douglas Gregor <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
