Changed it to retain current behavior (never enable rtti just because of a
sanitizer), but fix the failing case (we were assuming -cc1 would care about
-fno-sanitize=).
Refactored the code so the rtti/no-rtti decision was made in one place, and the
other code that cares just asks the ToolChain.
http://reviews.llvm.org/D7525
Files:
include/clang/Driver/ToolChain.h
lib/Driver/SanitizerArgs.cpp
lib/Driver/ToolChain.cpp
lib/Driver/Tools.cpp
test/Driver/fsanitize.c
test/Driver/rtti-options.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Driver/ToolChain.h
===================================================================
--- include/clang/Driver/ToolChain.h
+++ include/clang/Driver/ToolChain.h
@@ -22,6 +22,7 @@
namespace llvm {
namespace opt {
+ class Arg;
class ArgList;
class DerivedArgList;
class InputArgList;
@@ -53,6 +54,13 @@
RLT_Libgcc
};
+ enum RTTIMode {
+ RM_NotComputed,
+ RM_Enabled,
+ RM_DisabledExplicitly,
+ RM_DisabledImplicitly
+ };
+
private:
const Driver &D;
const llvm::Triple Triple;
@@ -74,6 +82,7 @@
Tool *getLink() const;
Tool *getClangAs() const;
+ RTTIMode CachedRTTIMode;
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
protected:
@@ -134,6 +143,9 @@
const SanitizerArgs& getSanitizerArgs() const;
+ // Returns the RTTIMode for the toolchain with the current arguments.
+ RTTIMode getRTTIMode() const { return CachedRTTIMode; }
+
// Tool access.
/// TranslateArgs - Create a new derived argument list for any argument
Index: lib/Driver/SanitizerArgs.cpp
===================================================================
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -171,6 +171,8 @@
// Used to deduplicate diagnostics.
unsigned Kinds = 0;
unsigned NotSupported = getToolchainUnsupportedKinds(TC);
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+
const Driver &D = TC.getDriver();
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
@@ -193,6 +195,17 @@
}
Add &= ~NotSupported;
+ // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
+ // so we don't error out if -fno-rtti and -fsanitize=undefined were
+ // passed.
+ if (Add & static_cast<unsigned>(SanitizeKind::Vptr) &&
+ RTTIMode == ToolChain::RM_DisabledExplicitly) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize=vptr" << "-fno-rtti";
+ // Bail out since we already have an error to deal with
+ return;
+ }
+
Add = expandGroups(Add);
// Group expansion may have enabled a sanitizer which is disabled later.
Add &= ~AllRemove;
@@ -209,6 +222,15 @@
}
addAllOf(Sanitizers, Kinds);
+ // Warn that we're disabling the vptr sanitizer if -fno-rtti and
+ // -fsanitize=undefined were passed.
+ if (Sanitizers.has(SanitizerKind::Vptr) &&
+ (RTTIMode == ToolChain::RM_DisabledImplicitly ||
+ RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
+ Sanitizers.set(SanitizerKind::Vptr, 0);
+ }
+
// Parse -f(no-)?sanitize-recover flags.
unsigned RecoverableKinds = RecoverableByDefault;
unsigned DiagnosedUnrecoverableKinds = 0;
Index: lib/Driver/ToolChain.cpp
===================================================================
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -26,14 +26,43 @@
using namespace clang;
using namespace llvm::opt;
+static ToolChain::RTTIMode calculateRTTIMode(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
+ options::OPT_fno_rtti))
+ return ToolChain::RM_DisabledExplicitly;
+
+ // -frtti is default, except for the PS4 CPU.
+ if (Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti,
+ !Triple.isPS4CPU()))
+ return ToolChain::RM_Enabled;
+
+ // On the PS4, turning on c++ exceptions turns on rtti.
+ // We're assuming that, if we see -fexceptions, rtti gets turned on.
+ Arg *Exceptions = Args.getLastArg(
+ options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions, options::OPT_fno_exceptions);
+ if (Triple.isPS4CPU()) {
+ if (Exceptions &&
+ (Exceptions->getOption().matches(options::OPT_fexceptions) ||
+ Exceptions->getOption().matches(options::OPT_fcxx_exceptions))) {
+ return ToolChain::RM_Enabled;
+ } else {
+ return ToolChain::RM_DisabledImplicitly;
+ }
+ } else {
+ return ToolChain::RM_Enabled; // Enabled implicitly
+ }
+}
+
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
- : D(D), Triple(T), Args(Args) {
+ : D(D), Triple(T), Args(Args),
+ CachedRTTIMode(calculateRTTIMode(Args, Triple)) {
if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
if (!isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
- << A->getValue()
- << A->getAsString(Args);
+ << A->getValue() << A->getAsString(Args);
}
ToolChain::~ToolChain() {
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1932,16 +1932,17 @@
return false;
}
-/// addExceptionArgs - Adds exception related arguments to the driver command
-/// arguments. There's a master flag, -fexceptions and also language specific
-/// flags to enable/disable C++ and Objective-C exceptions.
-/// This makes it possible to for example disable C++ exceptions but enable
-/// Objective-C exceptions.
+/// Adds exception related arguments to the driver command arguments.
+/// There's a master flag, -fexceptions and also language specific flags to
+/// enable/disable C++ and Objective-C exceptions./ This makes it possible to
+/// for example disable C++ exceptions but enable Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
- const llvm::Triple &Triple,
- bool KernelOrKext,
+ const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+ const llvm::Triple &Triple = TC.getTriple();
+
if (KernelOrKext) {
// -mkernel and -fapple-kext imply no exceptions, so claim exception related
// arguments now to avoid warnings about unused arguments.
@@ -1971,15 +1972,27 @@
if (types::isCXX(InputType)) {
bool CXXExceptionsEnabled =
Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
- if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
- options::OPT_fno_cxx_exceptions,
- options::OPT_fexceptions,
- options::OPT_fno_exceptions))
+ Arg *A = Args.getLastArg(
+ options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions, options::OPT_fno_exceptions);
+ if (A)
CXXExceptionsEnabled =
A->getOption().matches(options::OPT_fcxx_exceptions) ||
A->getOption().matches(options::OPT_fexceptions);
if (CXXExceptionsEnabled) {
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+ if (Triple.isPS4CPU()) {
+ assert(A && "On the PS4 exceptions should only be enabled if passing "
+ "an argument");
+ if (RTTIMode == ToolChain::RM_DisabledExplicitly)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-rtti" << A->getAsString(Args);
+ else if (RTTIMode == ToolChain::RM_Enabled &&
+ !Args.hasArg(options::OPT_frtti))
+ D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
+ }
+
CmdArgs.push_back("-fcxx-exceptions");
EH = true;
@@ -4006,56 +4019,11 @@
false))
CmdArgs.push_back("-fno-elide-constructors");
- // -frtti is default, except for the PS4 CPU.
- if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti,
- !Triple.isPS4CPU()) ||
- KernelOrKext) {
- bool IsCXX = types::isCXX(InputType);
- bool RTTIEnabled = false;
- Arg *NoRTTIArg = Args.getLastArg(
- options::OPT_mkernel, options::OPT_fapple_kext, options::OPT_fno_rtti);
-
- // PS4 requires rtti when exceptions are enabled. If -fno-rtti was
- // explicitly passed, error out. Otherwise enable rtti and emit a
- // warning.
- Arg *Exceptions = Args.getLastArg(
- options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
- options::OPT_fexceptions, options::OPT_fno_exceptions);
- if (Triple.isPS4CPU() && Exceptions) {
- bool CXXExceptions =
- (IsCXX &&
- Exceptions->getOption().matches(options::OPT_fexceptions)) ||
- Exceptions->getOption().matches(options::OPT_fcxx_exceptions);
- if (CXXExceptions) {
- if (NoRTTIArg)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << NoRTTIArg->getAsString(Args) << Exceptions->getAsString(Args);
- else {
- RTTIEnabled = true;
- D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
- }
- }
- }
+ ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
- // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
- if (Sanitize.sanitizesVptr()) {
- // If rtti was explicitly disabled and the vptr sanitizer is on, error
- // out. Otherwise, warn that vptr will be disabled unless -frtti is
- // passed.
- if (NoRTTIArg) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
- } else {
- D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
- // All sanitizer switches have been pushed. This -fno-sanitize
- // will override any -fsanitize={vptr,undefined} passed before it.
- CmdArgs.push_back("-fno-sanitize=vptr");
- }
- }
-
- if (!RTTIEnabled)
- CmdArgs.push_back("-fno-rtti");
- }
+ if (RTTIMode == ToolChain::RM_DisabledExplicitly ||
+ RTTIMode == ToolChain::RM_DisabledImplicitly)
+ CmdArgs.push_back("-fno-rtti");
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums,
@@ -4233,7 +4201,7 @@
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
+ addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext,
objcRuntime, CmdArgs);
if (getToolChain().UseSjLjExceptions())
Index: test/Driver/fsanitize.c
===================================================================
--- test/Driver/fsanitize.c
+++ test/Driver/fsanitize.c
@@ -31,8 +31,9 @@
// CHECK-UNDEFINED-TRAP-ON-ERROR-VPTR: '-fsanitize=vptr' not allowed with '-fsanitize-undefined-trap-on-error'
// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
// CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with '-fno-rtti'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-DISABLED
+// CHECK-VPTR-DISABLED: implicitly disabling vptr sanitizer because rtti wasn't enabled
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANA-SANT
// CHECK-SANA-SANT: '-fsanitize=address' not allowed with '-fsanitize=thread'
Index: test/Driver/rtti-options.cpp
===================================================================
--- test/Driver/rtti-options.cpp
+++ test/Driver/rtti-options.cpp
@@ -9,13 +9,13 @@
// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s
-// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s
+// RUN: %clang -### -c -target x86_64-unknown-unknown -fsanitize=undefined -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s
// Exceptions + no/default rtti
// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR-CXX %s
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits