diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-17 01:17:46 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-17 01:17:46 +0000 |
commit | 58219e7f27641bb3c635f17e79b7edc0a955a188 (patch) | |
tree | c87afa280a91a3a39843d6bdf83c54412789b2ea /lib | |
parent | 883692ebd421c40b44e2c2665e5f54dade5621bc (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1655c9105f..33102ccc04 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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); |