diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-05-21 19:26:31 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-05-21 19:26:31 +0000 |
commit | 930a9abb7eb171d706c9e17a27bbcd267f0d9b3d (patch) | |
tree | 2c722de4132a04dc7fa6465b79b5cd62240a9087 /lib/Sema/SemaExpr.cpp | |
parent | 4d509341bd5db06a517daa311379f52bb540bc34 (diff) |
Fix our handling of the warning when one tries to pass a
non-POD/non-trivial object throuugh a C-style varargs. The warning
itself was default-mapped to error, but can be downgraded, but we were
treating it in Sema like a hard error, silently dropping the call.
Instead, treat this problem like a warning, and do what the warning
says we do: abort at runtime. To do so, we fake up a __builtin_trap()
expression that gets evaluated as part of the argument.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131805 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6bccdaeb24..ce929d58ee 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -449,13 +449,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) return Owned(E); + // Don't allow one to pass an Objective-C interface to a vararg. if (E->getType()->isObjCObjectType() && - DiagRuntimeBehavior(E->getLocStart(), 0, - PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << E->getType() << CT)) + DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << E->getType() << CT)) return ExprError(); - - // C++ [expr.call]p7 prohibits non-POD types. + if (!E->getType()->isPODType()) { // C++0x [expr.call]p7: // Passing a potentially-evaluated argument of class type (Clause 9) @@ -477,8 +477,28 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, } else if (DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) << getLangOptions().CPlusPlus0x << E->getType() - << CT)) - return ExprError(); + << CT)) { + // Turn this into a trap. + CXXScopeSpec SS; + UnqualifiedId Name; + Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), + E->getLocStart()); + ExprResult TrapFn = ActOnIdExpression(TUScope, SS, Name, true, false); + if (TrapFn.isInvalid()) + return ExprError(); + + ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(), + MultiExprArg(), E->getLocEnd()); + if (Call.isInvalid()) + return ExprError(); + + ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma, + Call.get(), E); + if (Comma.isInvalid()) + return ExprError(); + + E = Comma.get(); + } } return Owned(E); |