Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ 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: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -1986,7 +1986,6 @@ if (CXXExceptionsEnabled) { CmdArgs.push_back("-fcxx-exceptions"); - EH = true; } } @@ -3956,20 +3955,54 @@ false)) CmdArgs.push_back("-fno-elide-constructors"); - // -frtti is default. - if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || + ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); + + // Handle GCC-style exception args. + if (!C.getDriver().IsCLMode()) + addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext, + objcRuntime, CmdArgs); + + // -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) { + RTTIEnabled = true; + D.Diag(diag::warn_drv_enabling_rtti_with_exceptions); + } else + D.Diag(diag::err_drv_argument_not_allowed_with) + << NoRTTIArg->getAsString(Args) << A->getAsString(Args); + } + } // -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. @@ -4064,8 +4097,6 @@ if (Args.hasArg(options::OPT_fno_inline_functions)) CmdArgs.push_back("-fno-inline-functions"); - ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); - // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and // legacy is the default. Except for deployment taget of 10.5, // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch @@ -4146,11 +4177,6 @@ } } - // Handle GCC-style exception args. - if (!C.getDriver().IsCLMode()) - addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext, - objcRuntime, CmdArgs); - if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); Index: test/Driver/rewrite-legacy-objc.m =================================================================== --- test/Driver/rewrite-legacy-objc.m +++ test/Driver/rewrite-legacy-objc.m @@ -3,11 +3,11 @@ // TEST0: clang{{.*}}" "-cc1" // TEST0: "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. -// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option" +// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fobjc-exceptions" "-fexceptions" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fmax-type-align=16" "-fdiagnostics-show-option" // TEST0: rewrite-legacy-objc.m" // RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.9.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST1 %s // RUN: %clang -no-canonical-prefixes -target i386-apple-macosx10.6.0 -rewrite-legacy-objc %s -o - -### 2>&1 | \ // RUN: FileCheck -check-prefix=TEST2 %s -// TEST1: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fobjc-subscripting-legacy-runtime" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option" -// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fmax-type-align=16" "-fdiagnostics-show-option" +// TEST1: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fobjc-exceptions" "-fobjc-subscripting-legacy-runtime" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fmax-type-align=16" "-fdiagnostics-show-option" +// TEST2: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx-fragile" "-fobjc-exceptions" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fmax-type-align=16" "-fdiagnostics-show-option" Index: test/Driver/rewrite-objc.m =================================================================== --- test/Driver/rewrite-objc.m +++ test/Driver/rewrite-objc.m @@ -3,4 +3,4 @@ // TEST0: clang{{.*}}" "-cc1" // TEST0: "-rewrite-objc" // FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead. -// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fobjc-exceptions" "-fexceptions" "-fmax-type-align=16" "-fdiagnostics-show-option" +// TEST0: "-fmessage-length" "0" "-stack-protector" "1" "-mstackrealign" "-fblocks" "-fobjc-runtime=macosx" "-fobjc-exceptions" "-fexceptions" "-fencode-extended-block-signature" "-fno-objc-infer-related-result-type" "-fmax-type-align=16" "-fdiagnostics-show-option" Index: test/Driver/rtti-options.cpp =================================================================== --- /dev/null +++ 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-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-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-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-ERR %s +// RUN: %clang -### -c -target x86_64-scei-ps4 -fcxx-exceptions -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-EXC-ERR-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:}} Index: test/Driver/xcore-opts.c =================================================================== --- test/Driver/xcore-opts.c +++ test/Driver/xcore-opts.c @@ -19,9 +19,9 @@ // CHECK: "-v" // CHECK: "L1Arg" "L2Arg" -// CHECK-EXCEP: "-fno-use-cxa-atexit" // CHECK-EXCEP: "-fcxx-exceptions" // CHECK-EXCEP: "-fexceptions" +// CHECK-EXCEP: "-fno-use-cxa-atexit" // CHECK-EXCEP: "-fno-common" // CHECK-EXCEP: xcc" "-o" // CHECK-EXCEP-NOT: "-fexceptions" @@ -31,4 +31,3 @@ // CHECK-G0: xcc" // CHECK-G0-NOT: "-g" // CHECK-G0: xcc" -