Index: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td @@ -160,6 +160,12 @@ InGroup>; def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">, InGroup>; +def warn_drv_enabling_rtti_with_exceptions : Warning< + "implicitly enabling rtti for exception handling">, + InGroup>; +def warn_drv_disabling_vptr_no_rtti_default : Warning< + "implicitly disabling vptr sanitizer because rtti wasn't enabled">, + InGroup>; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -3956,20 +3956,48 @@ false)) CmdArgs.push_back("-fno-elide-constructors"); - // -frtti is default. - if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || + // -frtti is default, except for the PS4 CPU. + if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, + !Triple.isPS4CPU()) || KernelOrKext) { - CmdArgs.push_back("-fno-rtti"); + 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. + if (Triple.isPS4CPU()) { + if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, + options::OPT_fexceptions)) { + if (NoRTTIArg) + D.Diag(diag::err_drv_argument_not_allowed_with) + << NoRTTIArg->getAsString(Args) << A->getAsString(Args); + else { + RTTIEnabled = true; + D.Diag(diag::warn_drv_enabling_rtti_with_exceptions); + } + } + } // -fno-rtti cannot usefully be combined with -fsanitize=vptr. if (Sanitize.sanitizesVptr()) { - std::string NoRttiArg = - Args.getLastArg(options::OPT_mkernel, - options::OPT_fapple_kext, - options::OPT_fno_rtti)->getAsString(Args); - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fsanitize=vptr" << NoRttiArg; + // 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"); } // -fshort-enums=0 is default for all architectures except Hexagon. Index: cfe/trunk/test/Driver/rtti-options.cpp =================================================================== --- cfe/trunk/test/Driver/rtti-options.cpp +++ cfe/trunk/test/Driver/rtti-options.cpp @@ -0,0 +1,52 @@ +// Check that we emit warnings/errors for different combinations of +// exceptions, rtti, and vptr sanitizer flags when targetting the PS4. +// No warnings/errors should be emitted for unknown, except if combining +// the vptr sanitizer with -fno-rtti + +// -fsanitize=vptr +// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// 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-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 + +// Exceptions + no/default rtti +// RUN: %clang -### -c -target x86_64-scei-ps4 -fexceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERROR-CXX %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fexceptions %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-WARN %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-WARN %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fexceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fexceptions %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s + +// -frtti + exceptions +// RUN: %clang -### -c -target x86_64-scei-ps4 -fexceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fexceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fcxx-exceptions -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s + +// -f{no-,}rtti/default +// RUN: %clang -### -c -target x86_64-scei-ps4 -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s +// RUN: %clang -### -c -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s +// RUN: %clang -### -c -target x86_64-unknown-unknown -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RTTI %s +// RUN: %clang -### -c -target x86_64-unknown-unknown %s 2>&1 | FileCheck -check-prefix=CHECK-RTTI %s + +// CHECK-SAN-WARN: implicitly disabling vptr sanitizer because rtti wasn't enabled +// CHECK-SAN-ERROR: invalid argument '-fsanitize=vptr' not allowed with '-fno-rtti' +// CHECK-EXC-WARN: implicitly enabling rtti for exception handling +// CHECK-EXC-ERROR: invalid argument '-fno-rtti' not allowed with '-fexceptions' +// CHECK-EXC-ERROR-CXX: invalid argument '-fno-rtti' not allowed with '-fcxx-exceptions' +// CHECK-RTTI-NOT: "-fno-rtti" +// CHECK-NO-RTTI-NOT: "-frtti" + +// CHECK-OK-NOT: {{warning:|error:}}