forked from OSchip/llvm-project
Reinstate the scalar-cast-to-const-reference improvements, this time
with the proper spelling of "non-class prvalue". Silly me, I think class rvalues were xvalues rather than prvalues! Hah hah hah. llvm-svn: 108443
This commit is contained in:
parent
cb2b662283
commit
cdb466e58f
|
@ -1749,8 +1749,48 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
|
|||
/// cast from scalar to union.
|
||||
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
||||
switch (E->getCastKind()) {
|
||||
default:
|
||||
case CastExpr::CK_ToVoid:
|
||||
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
|
||||
|
||||
case CastExpr::CK_NoOp:
|
||||
if (E->getSubExpr()->Classify(getContext()).getKind()
|
||||
!= Expr::Classification::CL_PRValue) {
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
if (LV.isPropertyRef()) {
|
||||
QualType QT = E->getSubExpr()->getType();
|
||||
RValue RV = EmitLoadOfPropertyRefLValue(LV, QT);
|
||||
assert(!RV.isScalar() && "EmitCastLValue-scalar cast of property ref");
|
||||
llvm::Value *V = RV.getAggregateAddr();
|
||||
return LValue::MakeAddr(V, MakeQualifiers(QT));
|
||||
}
|
||||
return LV;
|
||||
}
|
||||
// Fall through to synthesize a temporary.
|
||||
|
||||
case CastExpr::CK_Unknown:
|
||||
case CastExpr::CK_BitCast:
|
||||
case CastExpr::CK_ArrayToPointerDecay:
|
||||
case CastExpr::CK_FunctionToPointerDecay:
|
||||
case CastExpr::CK_NullToMemberPointer:
|
||||
case CastExpr::CK_IntegralToPointer:
|
||||
case CastExpr::CK_PointerToIntegral:
|
||||
case CastExpr::CK_VectorSplat:
|
||||
case CastExpr::CK_IntegralCast:
|
||||
case CastExpr::CK_IntegralToFloating:
|
||||
case CastExpr::CK_FloatingToIntegral:
|
||||
case CastExpr::CK_FloatingCast:
|
||||
case CastExpr::CK_DerivedToBaseMemberPointer:
|
||||
case CastExpr::CK_BaseToDerivedMemberPointer:
|
||||
case CastExpr::CK_MemberPointerToBoolean:
|
||||
case CastExpr::CK_AnyPointerToBlockPointerCast: {
|
||||
// These casts only produce lvalues when we're binding a reference to a
|
||||
// temporary realized from a (converted) pure rvalue. Emit the expression
|
||||
// as a value, copy it into a temporary, and return an lvalue referring to
|
||||
// that temporary.
|
||||
llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
|
||||
EmitAnyExprToMem(E, V, false, false);
|
||||
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
|
||||
}
|
||||
|
||||
case CastExpr::CK_Dynamic: {
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
|
@ -1760,17 +1800,6 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
|||
MakeQualifiers(E->getType()));
|
||||
}
|
||||
|
||||
case CastExpr::CK_NoOp: {
|
||||
LValue LV = EmitLValue(E->getSubExpr());
|
||||
if (LV.isPropertyRef()) {
|
||||
QualType QT = E->getSubExpr()->getType();
|
||||
RValue RV = EmitLoadOfPropertyRefLValue(LV, QT);
|
||||
assert(!RV.isScalar() && "EmitCastLValue - scalar cast of property ref");
|
||||
llvm::Value *V = RV.getAggregateAddr();
|
||||
return LValue::MakeAddr(V, MakeQualifiers(QT));
|
||||
}
|
||||
return LV;
|
||||
}
|
||||
case CastExpr::CK_ConstructorConversion:
|
||||
case CastExpr::CK_UserDefinedConversion:
|
||||
case CastExpr::CK_AnyPointerToObjCPointerCast:
|
||||
|
@ -1826,6 +1855,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
|||
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled lvalue cast kind?");
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitNullInitializationLValue(
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s
|
||||
|
||||
// PR6024
|
||||
extern int i;
|
||||
|
||||
// CHECK: define i32* @_Z16lvalue_noop_castv() nounwind
|
||||
const int &lvalue_noop_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: store i32 17, i32*
|
||||
return (const int&)17;
|
||||
else if (i == 1)
|
||||
// CHECK: store i32 17, i32*
|
||||
return static_cast<const int&>(17);
|
||||
// CHECK: store i32 17, i32*
|
||||
return 17;
|
||||
}
|
||||
|
||||
// CHECK: define i16* @_Z20lvalue_integral_castv()
|
||||
const short &lvalue_integral_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: store i16 17, i16*
|
||||
return (const short&)17;
|
||||
else if (i == 1)
|
||||
// CHECK: store i16 17, i16*
|
||||
return static_cast<const short&>(17);
|
||||
// CHECK: store i16 17, i16*
|
||||
return 17;
|
||||
}
|
||||
|
||||
// CHECK: define i16* @_Z29lvalue_floating_integral_castv()
|
||||
const short &lvalue_floating_integral_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: store i16 17, i16*
|
||||
return (const short&)17.5;
|
||||
else if (i == 1)
|
||||
// CHECK: store i16 17, i16*
|
||||
return static_cast<const short&>(17.5);
|
||||
// CHECK: store i16 17, i16*
|
||||
return 17.5;
|
||||
}
|
||||
|
||||
// CHECK: define float* @_Z29lvalue_integral_floating_castv()
|
||||
const float &lvalue_integral_floating_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return (const float&)17;
|
||||
else if (i == 1)
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return static_cast<const float&>(17);
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return 17;
|
||||
}
|
||||
|
||||
// CHECK: define float* @_Z20lvalue_floating_castv()
|
||||
const float &lvalue_floating_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return (const float&)17.0;
|
||||
else if (i == 1)
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return static_cast<const float&>(17.0);
|
||||
// CHECK: store float 1.700000e+01, float*
|
||||
return 17.0;
|
||||
}
|
||||
|
||||
int get_int();
|
||||
|
||||
// CHECK: define i8* @_Z24lvalue_integer_bool_castv()
|
||||
const bool &lvalue_integer_bool_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: call i32 @_Z7get_intv()
|
||||
// CHECK: store i8
|
||||
return (const bool&)get_int();
|
||||
else if (i == 1)
|
||||
// CHECK: call i32 @_Z7get_intv()
|
||||
// CHECK: store i8
|
||||
return static_cast<const bool&>(get_int());
|
||||
// CHECK: call i32 @_Z7get_intv()
|
||||
// CHECK: store i8
|
||||
return get_int();
|
||||
}
|
||||
|
||||
float get_float();
|
||||
|
||||
// CHECK: define i8* @_Z25lvalue_floating_bool_castv()
|
||||
const bool &lvalue_floating_bool_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: call float @_Z9get_floatv()
|
||||
// CHECK: fcmp une float
|
||||
// CHECK: store i8
|
||||
return (const bool&)get_float();
|
||||
else if (i == 1)
|
||||
// CHECK: call float @_Z9get_floatv()
|
||||
// CHECK: fcmp une float
|
||||
// CHECK: store i8
|
||||
return static_cast<const bool&>(get_float());
|
||||
// CHECK: call float @_Z9get_floatv()
|
||||
// CHECK: fcmp une float
|
||||
// CHECK: store i8
|
||||
return get_float();
|
||||
}
|
||||
|
||||
struct X { };
|
||||
typedef int X::*pm;
|
||||
typedef int (X::*pmf)(int);
|
||||
|
||||
pm get_pointer_to_member_data();
|
||||
pmf get_pointer_to_member_function();
|
||||
|
||||
// CHECK: define i8* @_Z26lvalue_ptrmem_to_bool_castv()
|
||||
const bool &lvalue_ptrmem_to_bool_cast() {
|
||||
if (i == 0)
|
||||
// CHECK: call i64 @_Z26get_pointer_to_member_datav()
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return (const bool&)get_pointer_to_member_data();
|
||||
else if (i == 1)
|
||||
// CHECK: call i64 @_Z26get_pointer_to_member_datav()
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return static_cast<const bool&>(get_pointer_to_member_data());
|
||||
// CHECK: call i64 @_Z26get_pointer_to_member_datav()
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return get_pointer_to_member_data();
|
||||
}
|
||||
|
||||
// CHECK: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v
|
||||
const bool &lvalue_ptrmem_to_bool_cast2() {
|
||||
if (i == 0)
|
||||
// CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return (const bool&)get_pointer_to_member_function();
|
||||
else if (i == 1)
|
||||
// CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return static_cast<const bool&>(get_pointer_to_member_function());
|
||||
// CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
|
||||
// CHECK: store i8
|
||||
// CHECK: store i8*
|
||||
return get_pointer_to_member_function();
|
||||
}
|
||||
|
||||
_Complex double get_complex_double();
|
||||
|
||||
// CHECK: {{define.*_Z2f1v}}
|
||||
const _Complex float &f1() {
|
||||
if (i == 0)
|
||||
// CHECK: {{call.*_Z18get_complex_doublev}}
|
||||
// CHECK: fptrunc
|
||||
// CHECK: fptrunc
|
||||
// CHECK: store float
|
||||
// CHECK: store float
|
||||
return (const _Complex float&)get_complex_double();
|
||||
else if (i == 1)
|
||||
// CHECK: {{call.*_Z18get_complex_doublev}}
|
||||
// CHECK: fptrunc
|
||||
// CHECK: fptrunc
|
||||
// CHECK: store float
|
||||
// CHECK: store float
|
||||
return static_cast<const _Complex float&>(get_complex_double());
|
||||
// CHECK: {{call.*_Z18get_complex_doublev}}
|
||||
// CHECK: fptrunc
|
||||
// CHECK: fptrunc
|
||||
// CHECK: store float
|
||||
// CHECK: store float
|
||||
return get_complex_double();
|
||||
}
|
Loading…
Reference in New Issue