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
case CK_Dependent:
case CK_LValueToRValue:
case CK_NoOp:
case CK_PointerToBoolean:
case CK_IntegralToBoolean:

View File

@ -43,6 +43,11 @@ enum CastKind {
/// reinterpret_casts of l-value expressions to reference types.
/// bool b; reinterpret_cast<char&>(b) = 'a';
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
/// (possibly) adding qualifiers.

View File

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

View File

@ -2650,6 +2650,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
Dst.Add(*I);
return;
case CK_LValueToRValue:
case CK_NoOp:
case CK_FunctionToPointerDecay:
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!");
case CK_NoOp:
if (E->getSubExpr()->Classify(getContext()).getKind()
!= Expr::Classification::CL_PRValue) {
if (!E->getSubExpr()->isRValue()) {
LValue LV = EmitLValue(E->getSubExpr());
if (LV.isPropertyRef() || LV.isKVCRef()) {
QualType QT = E->getSubExpr()->getType();
@ -1805,6 +1804,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
}
// Fall through to synthesize a temporary.
case CK_LValueToRValue:
case CK_BitCast:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:

View File

@ -250,8 +250,6 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
switch (E->getCastKind()) {
default: assert(0 && "Unhandled cast kind!");
case CK_Dynamic: {
assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?");
LValue LV = CGF.EmitCheckedLValue(E->getSubExpr());
@ -286,6 +284,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
case CK_NoOp:
case CK_LValueToRValue:
case CK_UserDefinedConversion:
case CK_ConstructorConversion:
assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(),
@ -293,10 +292,45 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
"Implicit cast types must be compatible");
Visit(E->getSubExpr());
break;
case CK_LValueBitCast:
llvm_unreachable("there are no lvalue bit-casts on aggregates");
llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
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

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

View File

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