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