From 824fd1dcff88353a7b9754db28bcbc4d6d0cbed5 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 30 Nov 2010 10:13:06 +0000 Subject: [PATCH] Introduce an r-value to l-value cast kind. I'm not promising anything about the reliability of this yet. llvm-svn: 120422 --- clang/include/clang/AST/Expr.h | 1 + clang/include/clang/AST/OperationKinds.h | 5 ++ clang/lib/AST/Expr.cpp | 2 + clang/lib/Checker/GRExprEngine.cpp | 1 + clang/lib/CodeGen/CGExpr.cpp | 4 +- clang/lib/CodeGen/CGExprAgg.cpp | 42 ++++++++++-- clang/lib/CodeGen/CGExprScalar.cpp | 4 ++ clang/lib/Sema/SemaExpr.cpp | 85 ++++++++++++++---------- 8 files changed, 102 insertions(+), 42 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 041446d6895d..4babbc476b20 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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: diff --git a/clang/include/clang/AST/OperationKinds.h b/clang/include/clang/AST/OperationKinds.h index cce351a77076..2ced0c9c719e 100644 --- a/clang/include/clang/AST/OperationKinds.h +++ b/clang/include/clang/AST/OperationKinds.h @@ -43,6 +43,11 @@ enum CastKind { /// reinterpret_casts of l-value expressions to reference types. /// bool b; reinterpret_cast(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. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3a112a7e073f..6e56603c53e6 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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: diff --git a/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp index f541a7ece4aa..fc0913bc2f72 100644 --- a/clang/lib/Checker/GRExprEngine.cpp +++ b/clang/lib/Checker/GRExprEngine.cpp @@ -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) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ce25b7ff2511..c28e405797ba 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 308520aadd4c..bd1c43dff588 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -250,8 +250,6 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { } switch (E->getCastKind()) { - default: assert(0 && "Unhandled cast kind!"); - case CK_Dynamic: { assert(isa(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"); } } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index e5ea26c24b61..a46afe6f658f 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -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(E)); case CK_IntegralToPointer: { Value *Src = Visit(const_cast(E)); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 19b074984332..39a51c1acd6f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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