diff options
| -rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 357 | 
2 files changed, 24 insertions, 334 deletions
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index dbbb980de85..06d02252d68 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangSema    SemaLookup.cpp    SemaObjCProperty.cpp    SemaOverload.cpp +  SemaPseudoObject.cpp    SemaStmt.cpp    SemaTemplate.cpp    SemaTemplateDeduction.cpp diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 17df1be2feb..885b9664d62 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6960,51 +6960,41 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]  /// depends on various declarations and thus must be treated specially.  ///  static bool IsReadonlyProperty(Expr *E, Sema &S) { -  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { -    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); -    if (PropExpr->isImplicitProperty()) return false; +  const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E); +  if (!PropExpr) return false; +  if (PropExpr->isImplicitProperty()) return false; -    ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); -    QualType BaseType = PropExpr->isSuperReceiver() ?  +  ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); +  QualType BaseType = PropExpr->isSuperReceiver() ?                               PropExpr->getSuperReceiverType() :                                PropExpr->getBase()->getType(); -    if (const ObjCObjectPointerType *OPT = -          BaseType->getAsObjCInterfacePointerType()) -      if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) -        if (S.isPropertyReadonly(PDecl, IFace)) -          return true; -  } +  if (const ObjCObjectPointerType *OPT = +      BaseType->getAsObjCInterfacePointerType()) +    if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) +      if (S.isPropertyReadonly(PDecl, IFace)) +        return true;    return false;  }  static bool IsConstProperty(Expr *E, Sema &S) { -  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { -    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); -    if (PropExpr->isImplicitProperty()) return false; +  const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E); +  if (!PropExpr) return false; +  if (PropExpr->isImplicitProperty()) return false; -    ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); -    QualType T = PDecl->getType(); -    if (T->isReferenceType()) -      T = T->getAs<ReferenceType>()->getPointeeType(); -    CanQualType CT = S.Context.getCanonicalType(T); -    return CT.isConstQualified(); -  } -  return false; +  ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); +  QualType T = PDecl->getType().getNonReferenceType(); +  return T.isConstQualified();  }  static bool IsReadonlyMessage(Expr *E, Sema &S) { -  if (E->getStmtClass() != Expr::MemberExprClass)  -    return false; -  const MemberExpr *ME = cast<MemberExpr>(E); -  NamedDecl *Member = ME->getMemberDecl(); -  if (isa<FieldDecl>(Member)) { -    Expr *Base = ME->getBase()->IgnoreParenImpCasts(); -    if (Base->getStmtClass() != Expr::ObjCMessageExprClass) -      return false; -    return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0; -  } -  return false; +  const MemberExpr *ME = dyn_cast<MemberExpr>(E); +  if (!ME) return false; +  if (!isa<FieldDecl>(ME->getMemberDecl())) return false; +  ObjCMessageExpr *Base = +    dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts()); +  if (!Base) return false; +  return Base->getMethodDecl() != 0;  }  /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not, @@ -7291,307 +7281,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,      return ResType.getUnqualifiedType();    }  } - -static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, -                                            const ObjCPropertyRefExpr *PRE) { -  bool instanceProperty; -  QualType searchType; -  if (PRE->isObjectReceiver()) { -    searchType = PRE->getBase()->getType() -      ->castAs<ObjCObjectPointerType>()->getPointeeType(); -    instanceProperty = true; -  } else if (PRE->isSuperReceiver()) { -    searchType = PRE->getSuperReceiverType(); -    instanceProperty = false; -    if (const ObjCObjectPointerType *PT -        = searchType->getAs<ObjCObjectPointerType>()) { -      searchType = PT->getPointeeType(); -      instanceProperty = true; -    } -  } else if (PRE->isClassReceiver()) { -    searchType = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); -    instanceProperty = false; -  } - -  return S.LookupMethodInObjectType(sel, searchType, instanceProperty); -} - -ExprResult Sema::checkPseudoObjectRValue(Expr *E) { -  assert(E->getValueKind() == VK_LValue && -         E->getObjectKind() == OK_ObjCProperty); -  const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); - -  QualType ReceiverType; -  if (PRE->isObjectReceiver()) -    ReceiverType = PRE->getBase()->getType(); -  else if (PRE->isSuperReceiver()) -    ReceiverType = PRE->getSuperReceiverType(); -  else -    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver()); -     -  ExprValueKind VK = VK_RValue; -  QualType T; -  if (PRE->isImplicitProperty()) { -    if (ObjCMethodDecl *GetterMethod =  -          PRE->getImplicitPropertyGetter()) { -      T = getMessageSendResultType(ReceiverType, GetterMethod, -                                   PRE->isClassReceiver(),  -                                   PRE->isSuperReceiver()); -      VK = Expr::getValueKindForType(GetterMethod->getResultType()); -    } else { -      Diag(PRE->getLocation(), diag::err_getter_not_found) -            << PRE->getBase()->getType(); -      return ExprError(); -    } -  } else { -    ObjCPropertyDecl *prop = PRE->getExplicitProperty(); - -    ObjCMethodDecl *getter = -      LookupMethodInReceiverType(*this, prop->getGetterName(), PRE); -    if (getter && !getter->hasRelatedResultType()) -      DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation()); -    if (!getter) getter = prop->getGetterMethodDecl(); - -    // Figure out the type of the expression.  Mostly this is the -    // result type of the getter, if possible. -    if (getter) { -      T = getMessageSendResultType(ReceiverType, getter,  -                                   PRE->isClassReceiver(),  -                                   PRE->isSuperReceiver()); -      VK = Expr::getValueKindForType(getter->getResultType()); - -      // As a special case, if the method returns 'id', try to get a -      // better type from the property. -      if (VK == VK_RValue && T->isObjCIdType() && -          prop->getType()->isObjCRetainableType()) -        T = prop->getType(); -    } else { -      T = prop->getType(); -      VK = Expr::getValueKindForType(T); -      T = T.getNonLValueExprType(Context); -    } -  } - -  E->setType(T); -  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK); -   -  ExprResult Result = MaybeBindToTemporary(E); -  if (!Result.isInvalid()) -    E = Result.take(); - -  return Owned(E); -} - -namespace { -  struct PseudoObjectInfo { -    const ObjCPropertyRefExpr *RefExpr; -    bool HasSetter; -    Selector SetterSelector; -    ParmVarDecl *SetterParam; -    QualType SetterParamType; - -    void setSetter(ObjCMethodDecl *setter) { -      HasSetter = true; -      SetterParam = *setter->param_begin(); -      SetterParamType = SetterParam->getType().getUnqualifiedType(); -    } - -    PseudoObjectInfo(Sema &S, Expr *E) -      : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) { - -      assert(E->getValueKind() == VK_LValue && -             E->getObjectKind() == OK_ObjCProperty); - -      // Try to find a setter. - -      // For implicit properties, just trust the lookup we already did. -      if (RefExpr->isImplicitProperty()) { -        if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { -          setSetter(setter); -          SetterSelector = setter->getSelector(); -        } else { -          IdentifierInfo *getterName = -            RefExpr->getImplicitPropertyGetter()->getSelector() -              .getIdentifierInfoForSlot(0); -          SetterSelector =  -            SelectorTable::constructSetterName(S.PP.getIdentifierTable(), -                                               S.PP.getSelectorTable(), -                                               getterName); -        } -        return; -      } - -      // For explicit properties, this is more involved. -      ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); -      SetterSelector = prop->getSetterName(); - -      // Do a normal method lookup first. -      if (ObjCMethodDecl *setter = -            LookupMethodInReceiverType(S, SetterSelector, RefExpr)) -        return setSetter(setter); - -      // If that failed, trust the type on the @property declaration. -      if (!prop->isReadOnly()) { -        HasSetter = true; -        SetterParamType = prop->getType().getUnqualifiedType(); -      } -    } -  }; -} - -/// Check an increment or decrement of a pseudo-object expression. -ExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc, -                                         UnaryOperatorKind opcode, Expr *op) { -  assert(UnaryOperator::isIncrementDecrementOp(opcode)); -  PseudoObjectInfo info(*this, op); - -  // If there's no setter, we have no choice but to try to assign to -  // the result of the getter. -  if (!info.HasSetter) { -    QualType resultType = info.RefExpr->getGetterResultType(); -    assert(!resultType.isNull() && "property has no setter and no getter!"); - -    // Only do this if the getter returns an l-value reference type. -    if (const LValueReferenceType *refType -          = resultType->getAs<LValueReferenceType>()) { -      op = ImplicitCastExpr::Create(Context, refType->getPointeeType(), -                                    CK_GetObjCProperty, op, 0, VK_LValue); -      return BuildUnaryOp(S, opcLoc, opcode, op); -    } - -    // Otherwise, it's an error. -    Diag(opcLoc, diag::err_nosetter_property_incdec) -      << unsigned(info.RefExpr->isImplicitProperty()) -      << unsigned(UnaryOperator::isDecrementOp(opcode)) -      << info.SetterSelector -      << op->getSourceRange(); -    return ExprError(); -  } - -  // ++/-- behave like compound assignments, i.e. they need a getter. -  QualType getterResultType = info.RefExpr->getGetterResultType(); -  if (getterResultType.isNull()) { -    assert(info.RefExpr->isImplicitProperty()); -    Diag(opcLoc, diag::err_nogetter_property_incdec) -      << unsigned(UnaryOperator::isDecrementOp(opcode)) -      << info.RefExpr->getImplicitPropertyGetter()->getSelector() -      << op->getSourceRange(); -    return ExprError(); -  } - -  // HACK: change the type of the operand to prevent further placeholder -  // transformation. -  op->setType(getterResultType.getNonLValueExprType(Context)); -  op->setObjectKind(OK_Ordinary); -   -  ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op); -  if (result.isInvalid()) return ExprError(); - -  // Change the object kind back. -  op->setObjectKind(OK_ObjCProperty); -  return result; -} - -ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, -                                             BinaryOperatorKind opcode, -                                             Expr *LHS, Expr *RHS) { -  assert(BinaryOperator::isAssignmentOp(opcode)); -  PseudoObjectInfo info(*this, LHS); - -  // If there's no setter, we have no choice but to try to assign to -  // the result of the getter. -  if (!info.HasSetter) { -    QualType resultType = info.RefExpr->getGetterResultType(); -    assert(!resultType.isNull() && "property has no setter and no getter!"); - -    // Only do this if the getter returns an l-value reference type. -    if (const LValueReferenceType *refType -          = resultType->getAs<LValueReferenceType>()) { -      LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(), -                                     CK_GetObjCProperty, LHS, 0, VK_LValue); -      return BuildBinOp(S, opcLoc, opcode, LHS, RHS); -    } - -    // Otherwise, it's an error. -    Diag(opcLoc, diag::err_nosetter_property_assignment) -      << unsigned(info.RefExpr->isImplicitProperty()) -      << info.SetterSelector -      << LHS->getSourceRange() << RHS->getSourceRange(); -    return ExprError(); -  } - -  // If there is a setter, we definitely want to use it. - -  // If this is a simple assignment, just initialize the parameter -  // with the RHS. -  if (opcode == BO_Assign) { -    LHS->setType(info.SetterParamType.getNonLValueExprType(Context)); - -    // Under certain circumstances, we need to type-check the RHS as a -    // straight-up parameter initialization.  This gives somewhat -    // inferior diagnostics, so we try to avoid it. - -    if (RHS->isTypeDependent()) { -      // Just build the expression. - -    } else if ((getLangOptions().CPlusPlus && LHS->getType()->isRecordType()) || -               (getLangOptions().ObjCAutoRefCount && -                info.SetterParam && -                info.SetterParam->hasAttr<NSConsumedAttr>())) { -      InitializedEntity param = (info.SetterParam -        ? InitializedEntity::InitializeParameter(Context, info.SetterParam) -        : InitializedEntity::InitializeParameter(Context, info.SetterParamType, -                                                 /*consumed*/ false)); -      ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS); -      if (arg.isInvalid()) return ExprError(); -      RHS = arg.take(); - -      // Warn about assignments of +1 objects to unsafe pointers in ARC. -      // CheckAssignmentOperands does this on the other path. -      if (getLangOptions().ObjCAutoRefCount) -        checkUnsafeExprAssigns(opcLoc, LHS, RHS); -    } else { -      ExprResult RHSResult = Owned(RHS); - -      LHS->setObjectKind(OK_Ordinary); -      QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc, -                                                    /*compound*/ QualType()); -      LHS->setObjectKind(OK_ObjCProperty); - -      if (!RHSResult.isInvalid()) RHS = RHSResult.take(); -      if (resultType.isNull()) return ExprError(); -    } - -    // Warn about property sets in ARC that might cause retain cycles. -    if (getLangOptions().ObjCAutoRefCount && !info.RefExpr->isSuperReceiver()) -      checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS); - -    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(), -                                        RHS->getValueKind(), -                                        RHS->getObjectKind(), -                                        opcLoc); -  } - -  // If this is a compound assignment, we need to use the getter, too. -  QualType getterResultType = info.RefExpr->getGetterResultType(); -  if (getterResultType.isNull()) { -    Diag(opcLoc, diag::err_nogetter_property_compound_assignment) -      << LHS->getSourceRange() << RHS->getSourceRange(); -    return ExprError(); -  } - -  // HACK: change the type of the LHS to prevent further placeholder -  // transformation. -  LHS->setType(getterResultType.getNonLValueExprType(Context)); -  LHS->setObjectKind(OK_Ordinary); -   -  ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS); -  if (result.isInvalid()) return ExprError(); - -  // Change the object kind back. -  LHS->setObjectKind(OK_ObjCProperty); -  return result; -}  /// getPrimaryDecl - Helper function for CheckAddressOfOperand().  | 

