diff options
author | John McCall <rjmccall@apple.com> | 2011-08-27 22:06:17 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-08-27 22:06:17 +0000 |
commit | 96a914a50cb8c01be8a3b7481cc4791e19c4285b (patch) | |
tree | 47f97a09ee8727cb1389d5543fb661429a3674f1 /lib/Sema/SemaExpr.cpp | |
parent | b8607398a5e1e552f82a86d1d8c3a4031ac4c946 (diff) |
Disable the l-value to r-value conversion on C++ class types passed
to varargs functions in unevaluated contexts. AFAICT, there is no
standards justification for this, but it matches what other compilers do
and therefore preserves compatibility with certain template metaprogramming
idioms.
Should fix self-host.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138715 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 65c9cccaf1..6327ee71db 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -443,9 +443,15 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { if (Ty->isSpecificBuiltinType(BuiltinType::Float)) E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); - // C++ includes lvalue-to-rvalue conversion as a default argument - // promotion. If we have a gl-value, initialize a temporary. - if (getLangOptions().CPlusPlus && E->isGLValue()) { + // C++ performs lvalue-to-rvalue conversion as a default argument + // promotion. If we still have a gl-value after usual unary + // conversion, we must have an l-value of class type, so we need to + // initialize a temporary. For compatibility reasons, however, we + // don't want to do this in unevaluated contexts; otherwise we + // reject metaprograms which work by passing uncopyable l-values to + // variadic functions. + if (getLangOptions().CPlusPlus && E->isGLValue() && + ExprEvalContexts.back().Context != Unevaluated) { ExprResult Temp = PerformCopyInitialization( InitializedEntity::InitializeTemporary(E->getType()), E->getExprLoc(), |