зеркало из https://github.com/microsoft/clang-1.git
Change the behavior of the lvalue-to-rvalue conversion for varargs in PotentiallyPotentiallyEvaluated contexts so that we model it in a sane way in most cases, and give up for the edge case which hopefully doesn't matter too much.
In preparation for correctly treating sizeof() as a PotentiallyPotentiallyEvaluated context. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148271 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
883692ebd4
Коммит
58219e7f27
|
@ -4318,6 +4318,10 @@ def err_cannot_pass_objc_interface_to_vararg : Error<
|
|||
"cannot pass object with interface type %0 by-value through variadic "
|
||||
"%select{function|block|method}1">;
|
||||
|
||||
def err_cannot_pass_non_pod_to_vararg_ppe : Error<
|
||||
"passing object of type %0 to variadic call in a context "
|
||||
"which is potentially evaluatable, but not obviously "
|
||||
"potentially evaluatable, is not yet implemented">;
|
||||
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
|
||||
"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">,
|
||||
|
|
|
@ -486,17 +486,34 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
|
|||
// has a class type, the conversion copy-initializes a temporary
|
||||
// of type T from the glvalue and the result of the conversion
|
||||
// is a prvalue for the temporary.
|
||||
// FIXME: add some way to gate this entire thing for correctness in
|
||||
// potentially potentially evaluated contexts.
|
||||
if (getLangOptions().CPlusPlus && E->isGLValue() &&
|
||||
ExprEvalContexts.back().Context != Unevaluated) {
|
||||
ExprResult Temp = PerformCopyInitialization(
|
||||
InitializedEntity::InitializeTemporary(E->getType()),
|
||||
E->getExprLoc(),
|
||||
Owned(E));
|
||||
if (Temp.isInvalid())
|
||||
return ExprError();
|
||||
E = Temp.get();
|
||||
// This requirement has some strange effects for
|
||||
// PotentiallyPotentiallyEvaluated contexts; specifically, doing precisely
|
||||
// what the standard requires involves mutating the AST once we decide
|
||||
// whether an expression is potentially evaluated. Rather than actually try and
|
||||
// model this correctly, we just make sure to handle the important cases:
|
||||
// for types with a trivial copy constructor/destructor, we build the AST
|
||||
// as if it were potentially evaluated, and we give an error in other cases
|
||||
// if the context turns out to be potentially evaluatable.
|
||||
// FIXME: If anyone actually cares about this case, try to implement
|
||||
// it correctly, or at least improve the diagnostic output a bit.
|
||||
if (getLangOptions().CPlusPlus && E->isGLValue()) {
|
||||
if (ExprEvalContexts.back().Context == PotentiallyPotentiallyEvaluated &&
|
||||
E->getType()->isRecordType() &&
|
||||
(!E->getType().isTriviallyCopyableType(Context) ||
|
||||
E->getType().isDestructedType())) {
|
||||
ExprEvalContexts.back()
|
||||
.addDiagnostic(E->getExprLoc(),
|
||||
PDiag(diag::err_cannot_pass_non_pod_to_vararg_ppe)
|
||||
<< E->getType());
|
||||
} else if (ExprEvalContexts.back().Context != Unevaluated) {
|
||||
ExprResult Temp = PerformCopyInitialization(
|
||||
InitializedEntity::InitializeTemporary(E->getType()),
|
||||
E->getExprLoc(),
|
||||
Owned(E));
|
||||
if (Temp.isInvalid())
|
||||
return ExprError();
|
||||
E = Temp.get();
|
||||
}
|
||||
}
|
||||
|
||||
return Owned(E);
|
||||
|
|
|
@ -88,7 +88,8 @@ Base &get_base(...);
|
|||
int eat_base(...);
|
||||
|
||||
void test_typeid(Base &base) {
|
||||
(void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}}
|
||||
(void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} \
|
||||
// expected-error {{potentially evaluatable, but not obviously potentially evaluatable}}
|
||||
(void)typeid(eat_base(base)); // okay
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче