From 0ae287a498b8cec2086fe6b7e753cbb3df63e74a Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 1 Dec 2010 04:43:34 +0000 Subject: [PATCH] Restore the lvalue-to-rvalue conversion patch with a minimal fix. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120555 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 1 + include/clang/AST/OperationKinds.h | 5 ++ lib/AST/Expr.cpp | 2 + lib/Checker/GRExprEngine.cpp | 1 + lib/CodeGen/CGExpr.cpp | 4 +- lib/CodeGen/CGExprAgg.cpp | 42 ++++++++++++-- lib/CodeGen/CGExprScalar.cpp | 4 ++ lib/Sema/SemaExpr.cpp | 85 +++++++++++++++++------------ test/CodeGenCXX/derived-to-base.cpp | 11 ++++ 9 files changed, 113 insertions(+), 42 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 041446d689..4babbc476b 100644 --- a/include/clang/AST/Expr.h +++ b/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/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index cce351a770..2ced0c9c71 100644 --- a/include/clang/AST/OperationKinds.h +++ b/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/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 3a112a7e07..6e56603c53 100644 --- a/lib/AST/Expr.cpp +++ b/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/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index f541a7ece4..fc0913bc2f 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/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/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index ce25b7ff25..466f55f341 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/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() || E->getType()->isRecordType()) { 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/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 308520aadd..bd1c43dff5 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/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/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index e5ea26c24b..a46afe6f65 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 08941505d5..c115061164 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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 diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp index e44fdc5ed2..76b79fc3a8 100644 --- a/test/CodeGenCXX/derived-to-base.cpp +++ b/test/CodeGenCXX/derived-to-base.cpp @@ -34,3 +34,14 @@ A *f(B* b) { } +// Don't crash on a derived-to-base conversion of an r-value +// aggregate. +namespace test3 { + struct A {}; + struct B : A {}; + + void foo(A a); + void test() { + foo(B()); + } +}