On Mar 25, 2013, at 3:18 PM, Argyrios Kyrtzidis <[email protected]> wrote:
> 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. r178616, thanks! - Doug _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
