From: John McCall Date: Mon, 6 Dec 2010 20:48:59 +0000 (+0000) Subject: Split out a function to do lvalue conversion on objects; this is basically X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=409fa9ab9579de04c5d68fb6a6a8d094545b1e77;p=clang Split out a function to do lvalue conversion on objects; this is basically FunctionArrayLvalueConversion but without the function/array decay. Generally this is only appropriate for use sites that know the type of the expression and thus that it can't be subject to the decays. Also make sure we do lvalue-to-rvalue on the bases of ivar references. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121035 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cf770c66eb..838e4bc2ff 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4003,6 +4003,12 @@ public: // lvalue-to-rvalue conversion. void DefaultFunctionArrayLvalueConversion(Expr *&expr); + // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on + // the operand. This is DefaultFunctionArrayLvalueConversion, + // except that it assumes the operand isn't of function or array + // type. + void DefaultLvalueConversion(Expr *&expr); + // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that // do not have a prototype. Integer promotions are performed on each // argument, and arguments that have type float are promoted to double. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bc8a7527c8..a1ea57ebcf 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -244,53 +244,57 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { } } -void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { - DefaultFunctionArrayConversion(E); - +void Sema::DefaultLvalueConversion(Expr *&E) { // C++ [conv.lval]p1: // A glvalue of a non-function, non-array type T can be // converted to a prvalue. - if (E->isGLValue()) { - QualType T = E->getType(); - assert(!T.isNull() && "r-value conversion on typeless expression?"); + if (!E->isGLValue()) return; - // Create a load out of an ObjCProperty l-value, if necessary. - if (E->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(E); - if (!E->isGLValue()) - return; - } + QualType T = E->getType(); + assert(!T.isNull() && "r-value conversion on typeless expression?"); - // We don't want to throw lvalue-to-rvalue casts on top of - // expressions of certain types in C++. - if (getLangOptions().CPlusPlus && - (E->getType() == Context.OverloadTy || - T->isDependentType() || - T->isRecordType())) + // Create a load out of an ObjCProperty l-value, if necessary. + if (E->getObjectKind() == OK_ObjCProperty) { + ConvertPropertyForRValue(E); + if (!E->isGLValue()) return; + } - // The C standard is actually really unclear on this point, and - // DR106 tells us what the result should be but not why. It's - // generally best to say that void just doesn't undergo - // lvalue-to-rvalue at all. - if (T->isVoidType()) - return; + // We don't want to throw lvalue-to-rvalue casts on top of + // expressions of certain types in C++. + if (getLangOptions().CPlusPlus && + (E->getType() == Context.OverloadTy || + T->isDependentType() || + T->isRecordType())) + return; - // C++ [conv.lval]p1: - // [...] 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. - // - // 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. - if (T.hasQualifiers()) - T = T.getUnqualifiedType(); + // The C standard is actually really unclear on this point, and + // DR106 tells us what the result should be but not why. It's + // generally best to say that void types just doesn't undergo + // lvalue-to-rvalue at all. Note that expressions of unqualified + // 'void' type are never l-values, but qualified void can be. + if (T->isVoidType()) + return; - E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, - E, 0, VK_RValue); - } + // C++ [conv.lval]p1: + // [...] 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. + // + // 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. + if (T.hasQualifiers()) + T = T.getUnqualifiedType(); + + E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue); +} + +void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { + DefaultFunctionArrayConversion(E); + DefaultLvalueConversion(E); } @@ -1722,10 +1726,13 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); + Expr *SelfE = SelfExpr.take(); + DefaultLvalueConversion(SelfE); + MarkDeclarationReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.takeAs(), true, true)); + SelfE, true, true)); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. @@ -2672,7 +2679,7 @@ static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc, // _Real and _Imag are only l-values for normal l-values. if (V->getObjectKind() != OK_Ordinary) - S.DefaultFunctionArrayLvalueConversion(V); + S.DefaultLvalueConversion(V); // These operators return the element type of a complex type. if (const ComplexType *CT = V->getType()->getAs()) @@ -3712,6 +3719,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, << IV->getDeclName(); } + if (IsArrow) DefaultLvalueConversion(BaseExpr); + return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, IsArrow)); @@ -3725,7 +3734,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (!IsArrow && (BaseType->isObjCIdType() || BaseType->isObjCQualifiedIdType())) { // This actually uses the base as an r-value. - DefaultFunctionArrayLvalueConversion(BaseExpr); + DefaultLvalueConversion(BaseExpr); assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType())); const ObjCObjectPointerType *QIdTy = BaseType->getAs(); @@ -3779,7 +3788,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (const ObjCObjectPointerType *OPT = BaseType->getAsObjCInterfacePointerType()) { // This actually uses the base as an r-value. - DefaultFunctionArrayLvalueConversion(BaseExpr); + DefaultLvalueConversion(BaseExpr); return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc, SourceLocation(), QualType(), false); }