Don't trap when passing non-POD arguments to variadic functions in MS-compatibility mode
Clang warns (treated as error by default, but still ignored in system headers) when passing non-POD arguments to variadic functions, and generates a trap instruction to crash the program if that code is ever run. Unfortunately, MSVC happily generates code for such calls without a warning, and there is code in system headers that use it. This makes Clang not insert the trap instruction when in -fms-compatibility mode, while still generating the warning/error message. Differential Revision: http://reviews.llvm.org/D5492 llvm-svn: 218640
This commit is contained in:
parent
b166d45730
commit
d9dd4d29b7
|
@ -7737,6 +7737,7 @@ public:
|
|||
VAK_Valid,
|
||||
VAK_ValidInCXX11,
|
||||
VAK_Undefined,
|
||||
VAK_MSVCUndefined,
|
||||
VAK_Invalid
|
||||
};
|
||||
|
||||
|
|
|
@ -3569,6 +3569,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
|
|||
break;
|
||||
|
||||
case Sema::VAK_Undefined:
|
||||
case Sema::VAK_MSVCUndefined:
|
||||
EmitFormatDiagnostic(
|
||||
S.PDiag(diag::warn_non_pod_vararg_with_format_string)
|
||||
<< S.getLangOpts().CPlusPlus11
|
||||
|
|
|
@ -800,6 +800,9 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
|
|||
if (Ty->isObjCObjectType())
|
||||
return VAK_Invalid;
|
||||
|
||||
if (getLangOpts().MSVCCompat)
|
||||
return VAK_MSVCUndefined;
|
||||
|
||||
// FIXME: In C++11, these cases are conditionally-supported, meaning we're
|
||||
// permitted to reject them. We should consider doing so.
|
||||
return VAK_Undefined;
|
||||
|
@ -829,6 +832,7 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
|
|||
break;
|
||||
|
||||
case VAK_Undefined:
|
||||
case VAK_MSVCUndefined:
|
||||
DiagRuntimeBehavior(
|
||||
E->getLocStart(), nullptr,
|
||||
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple i686-pc-win32 -fms-compatibility -emit-llvm -o - %s | FileCheck %s -check-prefix=X86 -check-prefix=CHECK
|
||||
// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple x86_64-pc-win32 -fms-compatibility -emit-llvm -o - %s | FileCheck %s -check-prefix=X64 -check-prefix=CHECK
|
||||
|
||||
struct X {
|
||||
X();
|
||||
~X();
|
||||
int data;
|
||||
};
|
||||
|
||||
void vararg(...);
|
||||
|
||||
void test(X x) {
|
||||
// CHECK-LABEL: define void @"\01?test@@YAXUX@@@Z"
|
||||
|
||||
// X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }>
|
||||
// X86: call void (<{ %struct.X }>*, ...)* bitcast (void (...)* @"\01?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
|
||||
|
||||
// X64: %[[valptr:[^ ]*]] = getelementptr %struct.X* %{{[^ ]*}}, i32 0, i32 0
|
||||
// X64: %[[val:[^ ]*]] = load i32* %[[valptr]]
|
||||
// X64: call void (...)* @"\01?vararg@@YAXZZ"(i32 %[[val]])
|
||||
|
||||
// CHECK-NOT: llvm.trap
|
||||
vararg(x);
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
|
||||
|
||||
// Check that the warning is still there under -fms-compatibility.
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs -fms-compatibility
|
||||
|
||||
extern char version[];
|
||||
|
||||
class C {
|
||||
|
|
Loading…
Reference in New Issue