diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-05-21 16:27:21 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-05-21 16:27:21 +0000 |
commit | 253cadfe681611bebb1addc47911b2f3f2bc2088 (patch) | |
tree | c28b46c9f58b55118d9aa6690a96528c10895332 | |
parent | 8e8f59bdfbbcde8c6bcee4774ae337bcdd9647a1 (diff) | |
download | bcm5719-llvm-253cadfe681611bebb1addc47911b2f3f2bc2088.tar.gz bcm5719-llvm-253cadfe681611bebb1addc47911b2f3f2bc2088.zip |
Implement C++0x semantics for passing non-POD classes through varargs.
llvm-svn: 131792
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 30 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp | 17 |
3 files changed, 44 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d96b40ac7ee..92a8228f141 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3324,8 +3324,8 @@ def err_cannot_pass_objc_interface_to_vararg : Error< "%select{function|block|method}1">; def warn_cannot_pass_non_pod_arg_to_vararg : Warning< - "cannot pass object of non-POD type %0 through variadic " - "%select{function|block|method|constructor}1; call will abort at runtime">, + "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic" + " %select{function|block|method|constructor}2; call will abort at runtime">, InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; def err_typecheck_call_invalid_ordered_compare : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5afd263ea13..6bccdaeb246 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -455,12 +455,32 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, << E->getType() << CT)) return ExprError(); - if (!E->getType()->isPODType() && - DiagRuntimeBehavior(E->getLocStart(), 0, + // 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) + // having a non-trivial copy constructor, a non-trivial move constructor, + // or a non-trivial destructor, with no corresponding parameter, + // is conditionally-supported with implementation-defined semantics. + bool TrivialEnough = false; + if (getLangOptions().CPlusPlus0x && !E->getType()->isDependentType()) { + if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) { + if (Record->hasTrivialCopyConstructor() && + Record->hasTrivialMoveConstructor() && + Record->hasTrivialDestructor()) + TrivialEnough = true; + } + } + + if (TrivialEnough) { + // Nothing to diagnose. This is okay. + } else if (DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << E->getType() << CT)) - return ExprError(); - + << getLangOptions().CPlusPlus0x << E->getType() + << CT)) + return ExprError(); + } + return Owned(E); } diff --git a/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp new file mode 100644 index 00000000000..bb4726dd330 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +struct X1 { + X1(); +}; + +struct X2 { + X2(); + ~X2(); +}; + +void vararg(...); + +void f(X1 x1, X2 x2) { + vararg(x1); // okay + vararg(x2); // expected-error{{cannot pass object of non-trivial type 'X2' through variadic function; call will abort at runtime}} +} |