Introduce an r-value to l-value cast kind. I'm not promising anything

about the reliability of this yet.

llvm-svn: 120422
This commit is contained in:
John McCall 2010-11-30 10:13:06 +00:00
parent a048c30215
commit 824fd1dcff
8 changed files with 102 additions and 42 deletions

View File

@ -2055,6 +2055,7 @@ private:
// fallthrough to check for null base path // fallthrough to check for null base path
case CK_Dependent: case CK_Dependent:
case CK_LValueToRValue:
case CK_NoOp: case CK_NoOp:
case CK_PointerToBoolean: case CK_PointerToBoolean:
case CK_IntegralToBoolean: case CK_IntegralToBoolean:

View File

@ -44,6 +44,11 @@ enum CastKind {
/// bool b; reinterpret_cast<char&>(b) = 'a'; /// bool b; reinterpret_cast<char&>(b) = 'a';
CK_LValueBitCast, CK_LValueBitCast,
/// CK_LValueToRValue - A conversion which causes the extraction of
/// an r-value from the operand gl-value. The result of an r-value
/// conversion is always unqualified.
CK_LValueToRValue,
/// CK_NoOp - A conversion which does not affect the type other than /// CK_NoOp - A conversion which does not affect the type other than
/// (possibly) adding qualifiers. /// (possibly) adding qualifiers.
/// int -> int /// int -> int

View File

@ -822,6 +822,8 @@ const char *CastExpr::getCastKindName() const {
return "BitCast"; return "BitCast";
case CK_LValueBitCast: case CK_LValueBitCast:
return "LValueBitCast"; return "LValueBitCast";
case CK_LValueToRValue:
return "LValueToRValue";
case CK_NoOp: case CK_NoOp:
return "NoOp"; return "NoOp";
case CK_BaseToDerived: case CK_BaseToDerived:

View File

@ -2650,6 +2650,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
Dst.Add(*I); Dst.Add(*I);
return; return;
case CK_LValueToRValue:
case CK_NoOp: case CK_NoOp:
case CK_FunctionToPointerDecay: case CK_FunctionToPointerDecay:
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {

View File

@ -1789,8 +1789,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
llvm_unreachable("dependent cast kind in IR gen!"); llvm_unreachable("dependent cast kind in IR gen!");
case CK_NoOp: case CK_NoOp:
if (E->getSubExpr()->Classify(getContext()).getKind() if (!E->getSubExpr()->isRValue()) {
!= Expr::Classification::CL_PRValue) {
LValue LV = EmitLValue(E->getSubExpr()); LValue LV = EmitLValue(E->getSubExpr());
if (LV.isPropertyRef() || LV.isKVCRef()) { if (LV.isPropertyRef() || LV.isKVCRef()) {
QualType QT = E->getSubExpr()->getType(); QualType QT = E->getSubExpr()->getType();
@ -1805,6 +1804,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
} }
// Fall through to synthesize a temporary. // Fall through to synthesize a temporary.
case CK_LValueToRValue:
case CK_BitCast: case CK_BitCast:
case CK_ArrayToPointerDecay: case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay: case CK_FunctionToPointerDecay:

View File

@ -250,8 +250,6 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
} }
switch (E->getCastKind()) { switch (E->getCastKind()) {
default: assert(0 && "Unhandled cast kind!");
case CK_Dynamic: { case CK_Dynamic: {
assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?"); assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?");
LValue LV = CGF.EmitCheckedLValue(E->getSubExpr()); LValue LV = CGF.EmitCheckedLValue(E->getSubExpr());
@ -286,6 +284,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
} }
case CK_NoOp: case CK_NoOp:
case CK_LValueToRValue:
case CK_UserDefinedConversion: case CK_UserDefinedConversion:
case CK_ConstructorConversion: case CK_ConstructorConversion:
assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(),
@ -295,8 +294,43 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break; break;
case CK_LValueBitCast: case CK_LValueBitCast:
llvm_unreachable("there are no lvalue bit-casts on aggregates"); llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
break; break;
case CK_Dependent:
case CK_BitCast:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToPointer:
case CK_NullToMemberPointer:
case CK_BaseToDerivedMemberPointer:
case CK_DerivedToBaseMemberPointer:
case CK_MemberPointerToBoolean:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
case CK_PointerToBoolean:
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingToBoolean:
case CK_FloatingCast:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
case CK_FloatingRealToComplex:
case CK_FloatingComplexToReal:
case CK_FloatingComplexToBoolean:
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
case CK_IntegralRealToComplex:
case CK_IntegralComplexToReal:
case CK_IntegralComplexToBoolean:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
llvm_unreachable("cast kind invalid for aggregate types");
} }
} }

View File

@ -1102,6 +1102,10 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
llvm_unreachable("scalar cast to non-scalar value"); llvm_unreachable("scalar cast to non-scalar value");
break; break;
case CK_LValueToRValue:
assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
return Visit(const_cast<Expr*>(E));
case CK_IntegralToPointer: { case CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E)); Value *Src = Visit(const_cast<Expr*>(E));

View File

@ -247,21 +247,27 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
DefaultFunctionArrayConversion(E); DefaultFunctionArrayConversion(E);
QualType Ty = E->getType(); // C++ [conv.lval]p1:
assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type"); // A glvalue of a non-function, non-array type T can be
if (!Ty->isDependentType() && Ty.hasQualifiers() && // converted to a prvalue.
(!getLangOptions().CPlusPlus || !Ty->isRecordType()) && if (E->isGLValue()) {
E->isLValue()) {
// C++ [conv.lval]p1: // C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the rvalue is the // [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the // cv-unqualified version of T. Otherwise, the type of the
// rvalue is T // rvalue is T.
// //
// C99 6.3.2.1p2: // C99 6.3.2.1p2:
// If the lvalue has qualified type, the value has the unqualified // If the lvalue has qualified type, the value has the unqualified
// version of the type of the lvalue; otherwise, the value has the // version of the type of the lvalue; otherwise, the value has the
// type of the lvalue. // type of the lvalue.
ImpCastExprToType(E, Ty.getUnqualifiedType(), CK_NoOp); QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
if (T.hasQualifiers() && !T->isDependentType() &&
(!getLangOptions().CPlusPlus || !T->isRecordType()))
T = T.getUnqualifiedType();
ImpCastExprToType(E, T, CK_LValueToRValue);
} }
} }
@ -271,36 +277,43 @@ void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
/// sometimes surpressed. For example, the array->pointer conversion doesn't /// sometimes surpressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators. /// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called. /// In these instances, this routine should *not* be called.
Expr *Sema::UsualUnaryConversions(Expr *&Expr) { Expr *Sema::UsualUnaryConversions(Expr *&E) {
QualType Ty = Expr->getType(); // First, convert to an r-value.
DefaultFunctionArrayLvalueConversion(E);
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
// C99 6.3.1.1p2: // Try to perform integral promotions if the object has a theoretically
// // promotable type.
// The following may be used in an expression wherever an int or if (Ty->isIntegralOrUnscopedEnumerationType()) {
// unsigned int may be used: // C99 6.3.1.1p2:
// - an object or expression with an integer type whose integer //
// conversion rank is less than or equal to the rank of int // The following may be used in an expression wherever an int or
// and unsigned int. // unsigned int may be used:
// - A bit-field of type _Bool, int, signed int, or unsigned int. // - an object or expression with an integer type whose integer
// // conversion rank is less than or equal to the rank of int
// If an int can represent all values of the original type, the // and unsigned int.
// value is converted to an int; otherwise, it is converted to an // - A bit-field of type _Bool, int, signed int, or unsigned int.
// unsigned int. These are called the integer promotions. All //
// other types are unchanged by the integer promotions. // If an int can represent all values of the original type, the
QualType PTy = Context.isPromotableBitField(Expr); // value is converted to an int; otherwise, it is converted to an
if (!PTy.isNull()) { // unsigned int. These are called the integer promotions. All
ImpCastExprToType(Expr, PTy, CK_IntegralCast); // other types are unchanged by the integer promotions.
return Expr;
} QualType PTy = Context.isPromotableBitField(E);
if (Ty->isPromotableIntegerType()) { if (!PTy.isNull()) {
QualType PT = Context.getPromotedIntegerType(Ty); ImpCastExprToType(E, PTy, CK_IntegralCast);
ImpCastExprToType(Expr, PT, CK_IntegralCast); return E;
return Expr; }
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
ImpCastExprToType(E, PT, CK_IntegralCast);
return E;
}
} }
DefaultFunctionArrayLvalueConversion(Expr); return E;
return Expr;
} }
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that /// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that