r174560 - Introduce -fmodules-ignore-macro=NNN to ignore a macro when building/loading modules.

Douglas Gregor dgregor at apple.com
Wed Feb 6 16:21:12 PST 2013


Author: dgregor
Date: Wed Feb  6 18:21:12 2013
New Revision: 174560

URL: http://llvm.org/viewvc/llvm-project?rev=174560&view=rev
Log:
Introduce -fmodules-ignore-macro=NNN to ignore a macro when building/loading modules.

The use of this flag enables a modules optimization where a given set
of macros can be labeled as "ignored" by the modules
system. Definitions of those macros will be completely ignored when
building the module hash and will be stripped when actually building
modules. The overall effect is that this flag can be used to
drastically reduce the number of

Eventually, we'll want modules to tell us what set of macros they
respond to (the "configuration macros"), and anything not in that set
will be excluded. However, that requires a lot of per-module
information that must be accurate, whereas this option can be used
more readily.

Fixes the rest of <rdar://problem/13165109>.


Modified:
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Lex/HeaderSearchOptions.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/test/Modules/ignored_macros.m

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Wed Feb  6 18:21:12 2013
@@ -501,6 +501,8 @@ def fmodules_autolink : Flag <["-"], "fm
   HelpText<"Enable autolinking of the libraries for imported modules">;
 def fno_modules_autolink : Flag <["-"], "fno-modules-autolink">, Group<f_Group>,
   HelpText<"Disable autolinking of the libraries for imported modules">;
+def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Ignore the definition of the given macro when building and loading modules">;
 def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
 
 def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;

Modified: cfe/trunk/include/clang/Lex/HeaderSearchOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearchOptions.h?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearchOptions.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearchOptions.h Wed Feb  6 18:21:12 2013
@@ -12,7 +12,9 @@
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
+#include <string>
 #include <vector>
 
 namespace clang {
@@ -86,13 +88,17 @@ public:
 
   /// \brief The directory used for the module cache.
   std::string ModuleCachePath;
-  
+
   /// \brief Whether we should disable the use of the hash string within the
   /// module cache.
   ///
   /// Note: Only used for testing!
   unsigned DisableModuleHash : 1;
-  
+
+  /// \brief The set of macro names that should be ignored for the purposes
+  /// of computing the module hash.
+  llvm::SetVector<std::string> ModulesIgnoreMacros;
+
   /// Include the compiler builtin includes.
   unsigned UseBuiltinIncludes : 1;
 

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Wed Feb  6 18:21:12 2013
@@ -428,6 +428,9 @@ void Clang::AddPreprocessingOptions(Comp
     CmdArgs.push_back("-fmodule-cache-path");
     CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
   }
+
+  // Pass through all -fmodules-ignore-macro arguments.
+  Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
   
   // Parse additional include paths from environment variables.
   // FIXME: We should probably sink the logic for handling these from the

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Wed Feb  6 18:21:12 2013
@@ -743,6 +743,28 @@ static void doCompileMapModule(void *Use
   Data.Instance.ExecuteAction(Data.CreateModuleAction);
 }
 
+namespace {
+  /// \brief Function object that checks with the given macro definition should
+  /// be removed, because it is one of the ignored macros.
+  class RemoveIgnoredMacro {
+    const HeaderSearchOptions &HSOpts;
+
+  public:
+    explicit RemoveIgnoredMacro(const HeaderSearchOptions &HSOpts)
+      : HSOpts(HSOpts) { }
+
+    bool operator()(const std::pair<std::string, bool> &def) const {
+      // Dig out the macro name.
+      StringRef MacroName = def.first;
+      StringRef::size_type EqPos = MacroName.find('=');
+      if (EqPos != StringRef::npos)
+        MacroName = MacroName.substr(0, EqPos);
+
+      return HSOpts.ModulesIgnoreMacros.count(MacroName) > 0;
+    }
+  };
+}
+
 /// \brief Compile a module file for the given module, using the options 
 /// provided by the importing compiler instance.
 static void compileModule(CompilerInstance &ImportingInstance,
@@ -779,6 +801,14 @@ static void compileModule(CompilerInstan
   Invocation->getLangOpts()->resetNonModularOptions();
   PPOpts.resetNonModularOptions();
 
+  // Remove any macro definitions that are explicitly ignored by the module.
+  // They aren't supposed to affect how the module is built anyway.
+  const HeaderSearchOptions &HSOpts = Invocation->getHeaderSearchOpts();
+  PPOpts.Macros.erase(std::remove_if(PPOpts.Macros.begin(), PPOpts.Macros.end(),
+                                     RemoveIgnoredMacro(HSOpts)),
+                      PPOpts.Macros.end());
+
+
   // Note the name of the module we're building.
   Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
 

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Feb  6 18:21:12 2013
@@ -813,7 +813,13 @@ static void ParseHeaderSearchArgs(Header
   Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
   Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodule_cache_path);
   Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
-  
+
+  for (arg_iterator it = Args.filtered_begin(OPT_fmodules_ignore_macro),
+       ie = Args.filtered_end(); it != ie; ++it) {
+    const Arg *A = *it;
+    Opts.ModulesIgnoreMacros.insert(A->getValue());
+  }
+
   // Add -I..., -F..., and -index-header-map options in order.
   bool IsIndexHeaderMap = false;
   for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F, 
@@ -1600,6 +1606,7 @@ std::string CompilerInvocation::getModul
 
   // Extend the signature with preprocessor options.
   const PreprocessorOptions &ppOpts = getPreprocessorOpts();
+  const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
   code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
 
   std::vector<StringRef> MacroDefs;
@@ -1607,11 +1614,24 @@ std::string CompilerInvocation::getModul
             I = getPreprocessorOpts().Macros.begin(),
          IEnd = getPreprocessorOpts().Macros.end();
        I != IEnd; ++I) {
+    // If we're supposed to ignore this macro for the purposes of modules,
+    // don't put it into the hash.
+    if (!hsOpts.ModulesIgnoreMacros.empty()) {
+      // Dig out the macro name.
+      StringRef MacroName = I->first;
+      StringRef::size_type EqPos = MacroName.find('=');
+      if (EqPos != StringRef::npos)
+        MacroName = MacroName.substr(0, EqPos);
+
+      // Check whether we're ignoring this macro.
+      if (hsOpts.ModulesIgnoreMacros.count(MacroName))
+        continue;
+    }
+
     code = hash_combine(code, I->first, I->second);
   }
 
   // Extend the signature with the sysroot.
-  const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
   code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes,
                       hsOpts.UseStandardSystemIncludes,
                       hsOpts.UseStandardCXXIncludes,

Modified: cfe/trunk/test/Modules/ignored_macros.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ignored_macros.m?rev=174560&r1=174559&r2=174560&view=diff
==============================================================================
--- cfe/trunk/test/Modules/ignored_macros.m (original)
+++ cfe/trunk/test/Modules/ignored_macros.m Wed Feb  6 18:21:12 2013
@@ -1,15 +1,31 @@
-// First trial: pass -DIGNORED=1 to both. It should be ignored in both
+// First trial: pass -DIGNORED=1 to both. This should obviously work.
 // RUN: rm -rf %t.modules
 // RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
 // RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch %s -verify
 
-// Second trial: pass -DIGNORED=1 only to the second invocation.
+// Second trial: pass -DIGNORED=1 only to the second invocation. We
+// should detect the failure.
+//
 // RUN: rm -rf %t.modules
 // RUN: %clang_cc1 -fmodule-cache-path %t.modules -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
 // RUN: not %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch %s > %t.err 2>&1
 // RUN: FileCheck -check-prefix=CHECK-CONFLICT %s < %t.err
 // CHECK-CONFLICT: module 'ignored_macros' found in both
 
+// Third trial: pass -DIGNORED=1 only to the second invocation, but
+// make it ignored. There should be no failure, IGNORED is defined in
+// the translation unit but not the module.
+// RUN: rm -rf %t.modules
+// RUN: %clang_cc1 -fmodule-cache-path %t.modules -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
+// RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch -fmodules-ignore-macro=IGNORED %s -verify
+
+// Fourth trial: pass -DIGNORED=1 and -fmodules-ignore-macro=IGNORED
+// to both invocations, so modules will be built without the IGNORED
+// macro.
+// RUN: rm -rf %t.modules
+// RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules-ignore-macro=IGNORED -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
+// RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch -fmodules-ignore-macro=IGNORED -DNO_IGNORED_ANYWHERE -fmodules-ignore-macro=NO_IGNORED_ANYWHERE %s -verify
+
 // expected-no-diagnostics
 
 #ifndef HEADER
@@ -20,3 +36,7 @@
 @import ignored_macros;
 
 struct Point p;
+
+#ifdef NO_IGNORED_ANYWHERE
+void *has_ignored(int, int, int);
+#endif





More information about the cfe-commits mailing list