SemaPseudoObject.cpp revision aa9807a85959ffbdc5d9f649d7b24b9b2056d2cd
13c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// 23c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 33c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// The LLVM Compiler Infrastructure 43c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 53c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// This file is distributed under the University of Illinois Open Source 63c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// License. See LICENSE.TXT for details. 73c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 83c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===// 93c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// This file implements semantic analysis for expressions involving 113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// pseudo-object references. Pseudo-objects are conceptual objects 123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// whose storage is entirely abstract and all accesses to which are 133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// translated through some sort of abstraction barrier. 143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// For example, Objective-C objects can have "properties", either 163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// declared or undeclared. A property may be accessed by writing 173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// expr.prop 183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// where 'expr' is an r-value of Objective-C pointer type and 'prop' 193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// is the name of the property. If this expression is used in a context 203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// needing an r-value, it is treated as if it were a message-send 213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// of the associated 'getter' selector, typically: 223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr prop] 233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// If it is used as the LHS of a simple assignment, it is treated 243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// as a message-send of the associated 'setter' selector, typically: 253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr setProp: RHS] 263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// If it is used as the LHS of a compound assignment, or the operand 273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// of a unary increment or decrement, both are required; for example, 283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 'expr.prop *= 100' would be translated to: 293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// [expr setProp: [expr prop] * 100] 303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// 313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===// 323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/SemaInternal.h" 343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/Initialization.h" 353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/AST/ExprObjC.h" 363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h" 373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 383c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang; 393c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema; 403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 413c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall const ObjCPropertyRefExpr *PRE) { 433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (PRE->isObjectReceiver()) { 44aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer const ObjCObjectPointerType *PT = 45aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 46aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 49aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (PRE->isSuperReceiver()) { 50aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer if (const ObjCObjectPointerType *PT = 51aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 52aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 53aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 54aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 55aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer } 56aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer 57aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer assert(PRE->isClassReceiver() && "Invalid expression"); 58aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 59aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer return S.LookupMethodInObjectType(sel, IT, false); 603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 613c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 623c3b7f90a863af43fa63043d396553ecf205351cJohn McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) { 633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(E->getValueKind() == VK_LValue && 643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall E->getObjectKind() == OK_ObjCProperty); 653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); 663c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 673c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType ReceiverType; 683c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (PRE->isObjectReceiver()) 693c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ReceiverType = PRE->getBase()->getType(); 703c3b7f90a863af43fa63043d396553ecf205351cJohn McCall else if (PRE->isSuperReceiver()) 713c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ReceiverType = PRE->getSuperReceiverType(); 723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall else 733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver()); 743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 753c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprValueKind VK = VK_RValue; 763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType T; 773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (PRE->isImplicitProperty()) { 783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (ObjCMethodDecl *GetterMethod = 793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PRE->getImplicitPropertyGetter()) { 803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall T = getMessageSendResultType(ReceiverType, GetterMethod, 813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PRE->isClassReceiver(), 823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PRE->isSuperReceiver()); 833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall VK = Expr::getValueKindForType(GetterMethod->getResultType()); 843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Diag(PRE->getLocation(), diag::err_getter_not_found) 863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << PRE->getBase()->getType(); 873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 883c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 893c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 903c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ObjCPropertyDecl *prop = PRE->getExplicitProperty(); 913c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 923c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ObjCMethodDecl *getter = 933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LookupMethodInReceiverType(*this, prop->getGetterName(), PRE); 943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getter && !getter->hasRelatedResultType()) 953c3b7f90a863af43fa63043d396553ecf205351cJohn McCall DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation()); 963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!getter) getter = prop->getGetterMethodDecl(); 973c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 983c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Figure out the type of the expression. Mostly this is the 993c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // result type of the getter, if possible. 1003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getter) { 1013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall T = getMessageSendResultType(ReceiverType, getter, 1023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PRE->isClassReceiver(), 1033c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PRE->isSuperReceiver()); 1043c3b7f90a863af43fa63043d396553ecf205351cJohn McCall VK = Expr::getValueKindForType(getter->getResultType()); 1053c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1063c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // As a special case, if the method returns 'id', try to get a 1073c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // better type from the property. 1083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (VK == VK_RValue && T->isObjCIdType() && 1093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall prop->getType()->isObjCRetainableType()) 1103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall T = prop->getType(); 1113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 1123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall T = prop->getType(); 1133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall VK = Expr::getValueKindForType(T); 1143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall T = T.getNonLValueExprType(Context); 1153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall E->setType(T); 1193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK); 1203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprResult Result = MaybeBindToTemporary(E); 1223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!Result.isInvalid()) 1233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall E = Result.take(); 1243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return Owned(E); 1263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 1273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1283c3b7f90a863af43fa63043d396553ecf205351cJohn McCallnamespace { 1293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall struct PseudoObjectInfo { 1303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall const ObjCPropertyRefExpr *RefExpr; 1313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall bool HasSetter; 1323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Selector SetterSelector; 1333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ParmVarDecl *SetterParam; 1343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType SetterParamType; 1353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall void setSetter(ObjCMethodDecl *setter) { 1373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall HasSetter = true; 1383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterParam = *setter->param_begin(); 1393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterParamType = SetterParam->getType().getUnqualifiedType(); 1403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1413c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PseudoObjectInfo(Sema &S, Expr *E) 1433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) { 1443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1453c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(E->getValueKind() == VK_LValue && 1463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall E->getObjectKind() == OK_ObjCProperty); 1473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Try to find a setter. 1493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1503c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // For implicit properties, just trust the lookup we already did. 1513c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (RefExpr->isImplicitProperty()) { 1523c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 1533c3b7f90a863af43fa63043d396553ecf205351cJohn McCall setSetter(setter); 1543c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterSelector = setter->getSelector(); 1553c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 1563c3b7f90a863af43fa63043d396553ecf205351cJohn McCall IdentifierInfo *getterName = 1573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall RefExpr->getImplicitPropertyGetter()->getSelector() 1583c3b7f90a863af43fa63043d396553ecf205351cJohn McCall .getIdentifierInfoForSlot(0); 1593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterSelector = 1603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SelectorTable::constructSetterName(S.PP.getIdentifierTable(), 1613c3b7f90a863af43fa63043d396553ecf205351cJohn McCall S.PP.getSelectorTable(), 1623c3b7f90a863af43fa63043d396553ecf205351cJohn McCall getterName); 1633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return; 1653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1663c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1673c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // For explicit properties, this is more involved. 1683c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 1693c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterSelector = prop->getSetterName(); 1703c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1713c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Do a normal method lookup first. 1723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (ObjCMethodDecl *setter = 1733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 1743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall setSetter(setter); 1753c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return; 1763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If that failed, trust the type on the @property declaration. 1793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!prop->isReadOnly()) { 1803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall HasSetter = true; 1813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall SetterParamType = prop->getType().getUnqualifiedType(); 1823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 1843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall }; 1853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 1863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall/// Check an increment or decrement of a pseudo-object expression. 1883c3b7f90a863af43fa63043d396553ecf205351cJohn McCallExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc, 1893c3b7f90a863af43fa63043d396553ecf205351cJohn McCall UnaryOperatorKind opcode, Expr *op) { 1903c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(UnaryOperator::isIncrementDecrementOp(opcode)); 1913c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PseudoObjectInfo info(*this, op); 1923c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 1943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 1953c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!info.HasSetter) { 1963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType resultType = info.RefExpr->getGetterResultType(); 1973c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(!resultType.isNull() && "property has no setter and no getter!"); 1983c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 1993c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Only do this if the getter returns an l-value reference type. 2003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (const LValueReferenceType *refType 2013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall = resultType->getAs<LValueReferenceType>()) { 2023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall op = ImplicitCastExpr::Create(Context, refType->getPointeeType(), 2033c3b7f90a863af43fa63043d396553ecf205351cJohn McCall CK_GetObjCProperty, op, 0, VK_LValue); 2043c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return BuildUnaryOp(S, opcLoc, opcode, op); 2053c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 2063c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2073c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 2083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Diag(opcLoc, diag::err_nosetter_property_incdec) 2093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << unsigned(info.RefExpr->isImplicitProperty()) 2103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 2113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << info.SetterSelector 2123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << op->getSourceRange(); 2133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 2143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 2153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // ++/-- behave like compound assignments, i.e. they need a getter. 2173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType getterResultType = info.RefExpr->getGetterResultType(); 2183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getterResultType.isNull()) { 2193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(info.RefExpr->isImplicitProperty()); 2203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Diag(opcLoc, diag::err_nogetter_property_incdec) 2213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << unsigned(UnaryOperator::isDecrementOp(opcode)) 2223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << info.RefExpr->getImplicitPropertyGetter()->getSelector() 2233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << op->getSourceRange(); 2243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 2253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 2263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // HACK: change the type of the operand to prevent further placeholder 2283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // transformation. 2293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall op->setType(getterResultType.getNonLValueExprType(Context)); 2303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall op->setObjectKind(OK_Ordinary); 2313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op); 2333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (result.isInvalid()) return ExprError(); 2343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Change the object kind back. 2363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall op->setObjectKind(OK_ObjCProperty); 2373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return result; 2383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 2393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2403c3b7f90a863af43fa63043d396553ecf205351cJohn McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 2413c3b7f90a863af43fa63043d396553ecf205351cJohn McCall BinaryOperatorKind opcode, 2423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Expr *LHS, Expr *RHS) { 2433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(BinaryOperator::isAssignmentOp(opcode)); 2443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall PseudoObjectInfo info(*this, LHS); 2453c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there's no setter, we have no choice but to try to assign to 2473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // the result of the getter. 2483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!info.HasSetter) { 2493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType resultType = info.RefExpr->getGetterResultType(); 2503c3b7f90a863af43fa63043d396553ecf205351cJohn McCall assert(!resultType.isNull() && "property has no setter and no getter!"); 2513c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2523c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Only do this if the getter returns an l-value reference type. 2533c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (const LValueReferenceType *refType 2543c3b7f90a863af43fa63043d396553ecf205351cJohn McCall = resultType->getAs<LValueReferenceType>()) { 2553c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(), 2563c3b7f90a863af43fa63043d396553ecf205351cJohn McCall CK_GetObjCProperty, LHS, 0, VK_LValue); 2573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return BuildBinOp(S, opcLoc, opcode, LHS, RHS); 2583c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 2593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Otherwise, it's an error. 2613c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Diag(opcLoc, diag::err_nosetter_property_assignment) 2623c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << unsigned(info.RefExpr->isImplicitProperty()) 2633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << info.SetterSelector 2643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << LHS->getSourceRange() << RHS->getSourceRange(); 2653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 2663c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 2673c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2683c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If there is a setter, we definitely want to use it. 2693c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2703c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If this is a simple assignment, just initialize the parameter 2713c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // with the RHS. 2723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (opcode == BO_Assign) { 2733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setType(info.SetterParamType.getNonLValueExprType(Context)); 2743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2753c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Under certain circumstances, we need to type-check the RHS as a 2763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // straight-up parameter initialization. This gives somewhat 2773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // inferior diagnostics, so we try to avoid it. 2783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (RHS->isTypeDependent()) { 2803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Just build the expression. 2813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else if ((getLangOptions().CPlusPlus && LHS->getType()->isRecordType()) || 2833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall (getLangOptions().ObjCAutoRefCount && 2843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall info.SetterParam && 2853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall info.SetterParam->hasAttr<NSConsumedAttr>())) { 2863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall InitializedEntity param = (info.SetterParam 2873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ? InitializedEntity::InitializeParameter(Context, info.SetterParam) 2883c3b7f90a863af43fa63043d396553ecf205351cJohn McCall : InitializedEntity::InitializeParameter(Context, info.SetterParamType, 2893c3b7f90a863af43fa63043d396553ecf205351cJohn McCall /*consumed*/ false)); 2903c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS); 2913c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (arg.isInvalid()) return ExprError(); 2923c3b7f90a863af43fa63043d396553ecf205351cJohn McCall RHS = arg.take(); 2933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 2943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Warn about assignments of +1 objects to unsafe pointers in ARC. 2953c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // CheckAssignmentOperands does this on the other path. 2963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getLangOptions().ObjCAutoRefCount) 2973c3b7f90a863af43fa63043d396553ecf205351cJohn McCall checkUnsafeExprAssigns(opcLoc, LHS, RHS); 2983c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } else { 2993c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprResult RHSResult = Owned(RHS); 3003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setObjectKind(OK_Ordinary); 3023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc, 3033c3b7f90a863af43fa63043d396553ecf205351cJohn McCall /*compound*/ QualType()); 3043c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setObjectKind(OK_ObjCProperty); 3053c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3063c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (!RHSResult.isInvalid()) RHS = RHSResult.take(); 3073c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (resultType.isNull()) return ExprError(); 3083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 3093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Warn about property sets in ARC that might cause retain cycles. 3113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getLangOptions().ObjCAutoRefCount && !info.RefExpr->isSuperReceiver()) 3123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS); 3133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(), 3153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall RHS->getValueKind(), 3163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall RHS->getObjectKind(), 3173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall opcLoc); 3183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 3193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // If this is a compound assignment, we need to use the getter, too. 3213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType getterResultType = info.RefExpr->getGetterResultType(); 3223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (getterResultType.isNull()) { 3233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 3243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall << LHS->getSourceRange() << RHS->getSourceRange(); 3253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return ExprError(); 3263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall } 3273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // HACK: change the type of the LHS to prevent further placeholder 3293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // transformation. 3303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setType(getterResultType.getNonLValueExprType(Context)); 3313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setObjectKind(OK_Ordinary); 3323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS); 3343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall if (result.isInvalid()) return ExprError(); 3353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall 3363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall // Change the object kind back. 3373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall LHS->setObjectKind(OK_ObjCProperty); 3383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall return result; 3393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall} 340