[cfe-commits] r138715 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CXX/special/class.temporary/p1.cpp

John McCall rjmccall at apple.com
Sat Aug 27 19:17:13 CDT 2011


On Aug 27, 2011, at 4:15 PM, Johannes Schaub wrote:
> John McCall wrote:
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=138715&r1=138714&r2=138715&view=diff
>> 
> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++
>> cfe/trunk/lib/Sema/SemaExpr.cpp Sat Aug 27 17:06:17 2011 @@ -443,9 +443,15
>> @@
>>   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.
> 
> 4.1p2 of the C++11 FDIS says:
> 
> "When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a 
> subexpression thereof (Clause 5) the value contained in the referenced 
> object is not accessed. Otherwise ...". 
> 
> C++03 is much less precise on the entire conversion wrt class types, but 
> said if the expression occurs within the operand of a sizeof "the value 
> contained in the referenced object is not accessed". I think the FDIS text 
> will be a good reference to put on that comment.

I'm not sure how this applies.  I agree that the lvalue-to-rvalue conversion,
if well-formed, does not access the object if it appears in an unevaluated
context.  However, the conversion is not necessarily well-formed, and
normally that's checked even in unevaluated contexts.

That is to say, the following is clearly ill-formed, even though the access
appears in an unevaluated context:
  class A { private: static int foo(); } 
  size_t test() { return sizeof(A::foo()); }

Whereas this is apparently well-formed according to (universal?) precedent:
  extern void foo(...);
  class A { private: A(const A&); };
  size_t test(A a) { return sizeof(foo(a)); }
even though the analogous case in an evaluated context would be ill-formed.

John.


More information about the cfe-commits mailing list