aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Driver/Options.td2
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h10
-rw-r--r--lib/Driver/Tools.cpp3
-rw-r--r--lib/Frontend/CompilerInstance.cpp30
-rw-r--r--lib/Frontend/CompilerInvocation.cpp24
-rw-r--r--test/Modules/ignored_macros.m24
6 files changed, 87 insertions, 6 deletions
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 35ea80307c..ae0ae84e17 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -501,6 +501,8 @@ def fmodules_autolink : Flag <["-"], "fmodules-autolink">, Group<f_Group>, Flags
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>;
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index 8fecd65726..c45884360d 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -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;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 71e50a5c9e..7932ba2827 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -428,6 +428,9 @@ void Clang::AddPreprocessingOptions(Compilation &C,
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
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index b6115ec6ff..356bf3171c 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -743,6 +743,28 @@ static void doCompileMapModule(void *UserData) {
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(CompilerInstance &ImportingInstance,
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();
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index a4597fd84d..34496ede26 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -813,7 +813,13 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
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::getModuleHash() const {
// 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::getModuleHash() const {
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,
diff --git a/test/Modules/ignored_macros.m b/test/Modules/ignored_macros.m
index 1f9c27c2a3..3d5f359b31 100644
--- a/test/Modules/ignored_macros.m
+++ b/test/Modules/ignored_macros.m
@@ -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