summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2017-06-01 20:01:01 +0000
committerVedant Kumar <vsk@apple.com>2017-06-01 20:01:01 +0000
commitd2f497236f66527ad5d026e47887c63e540d6d5d (patch)
tree1069081f3f6442642965ff4240fd00790ed79c82 /lib
parent10aee78afb384ad8c70cb9e9183ff39c032e8caf (diff)
[Modules] Handle sanitizer feature mismatches when importing modules
This patch makes it an error to have a mismatch between the enabled sanitizers in a CU, and in any module being imported into the CU. Only mismatches between non-modular sanitizers are treated as errors. This patch also includes non-modular sanitizers in module hashes, in order to ensure module rebuilds occur when -fsanitize=X is toggled on and off for non-modular sanitizers, and to cut down on module rebuilds when the option is toggled for modular sanitizers. This fixes a longstanding issue with implicit modules and sanitizers, which Duncan originally diagnosed. When building with implicit modules it's possible to hit a scenario where modules are built without -fsanitize=address, and are subsequently imported into CUs with -fsanitize=address enabled. This causes strange failures at runtime. The case Duncan found affects libcxx, since its vector implementation behaves differently when ASan is enabled. Implicit module builds should "just work" when -fsanitize=X is toggled on and off across multiple compiler invocations, which is what this patch does. Differential Revision: https://reviews.llvm.org/D32724 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304463 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Basic/LangOptions.cpp4
-rw-r--r--lib/Frontend/CompilerInvocation.cpp7
-rw-r--r--lib/Serialization/ASTReader.cpp27
3 files changed, 35 insertions, 3 deletions
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index c8a774311e..db81507aa2 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -29,9 +29,7 @@ void LangOptions::resetNonModularOptions() {
Name = Default;
#include "clang/Basic/LangOptions.def"
- // FIXME: This should not be reset; modules can be different with different
- // sanitizer options (this affects __has_feature(address_sanitizer) etc).
- Sanitize.clear();
+ // These options do not affect AST generation.
SanitizerBlacklistFiles.clear();
XRayAlwaysInstrumentFiles.clear();
XRayNeverInstrumentFiles.clear();
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 47c763d293..1c590ce607 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -2700,6 +2700,13 @@ std::string CompilerInvocation::getModuleHash() const {
code = ext->hashExtension(code);
}
+ // Extend the signature with the enabled sanitizers, if at least one is
+ // enabled. Sanitizers which cannot affect AST generation aren't hashed.
+ SanitizerSet SanHash = LangOpts->Sanitize;
+ SanHash.clear(getPPTransparentSanitizers());
+ if (!SanHash.empty())
+ code = hash_combine(code, SanHash.Mask);
+
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index b7bbb9dc7b..125b045351 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -292,6 +292,33 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
return true;
}
+ // Sanitizer feature mismatches are treated as compatible differences. If
+ // compatible differences aren't allowed, we still only want to check for
+ // mismatches of non-modular sanitizers (the only ones which can affect AST
+ // generation).
+ if (!AllowCompatibleDifferences) {
+ SanitizerMask ModularSanitizers = getPPTransparentSanitizers();
+ SanitizerSet ExistingSanitizers = ExistingLangOpts.Sanitize;
+ SanitizerSet ImportedSanitizers = LangOpts.Sanitize;
+ ExistingSanitizers.clear(ModularSanitizers);
+ ImportedSanitizers.clear(ModularSanitizers);
+ if (ExistingSanitizers.Mask != ImportedSanitizers.Mask) {
+ const std::string Flag = "-fsanitize=";
+ if (Diags) {
+#define SANITIZER(NAME, ID) \
+ { \
+ bool InExistingModule = ExistingSanitizers.has(SanitizerKind::ID); \
+ bool InImportedModule = ImportedSanitizers.has(SanitizerKind::ID); \
+ if (InExistingModule != InImportedModule) \
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch) \
+ << InExistingModule << (Flag + NAME); \
+ }
+#include "clang/Basic/Sanitizers.def"
+ }
+ return true;
+ }
+ }
+
return false;
}