diff options
author | John McCall <rjmccall@apple.com> | 2011-10-25 08:42:34 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-10-25 08:42:34 +0000 |
commit | 8628862a5f3fc739dbaa759599851d0aec3822ca (patch) | |
tree | 2a264c40ececd4013d2efcd7318e4df258c30b9a /lib/Sema/SemaExpr.cpp | |
parent | a1b852f8e1bee5ed3604ee483803cef39ce57a20 (diff) |
Pull the pseudo-object stuff into its own file.
Tidy up some marginally related code just to annoy
single-purpose-commit lovers. No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142915 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 357 |
1 files changed, 23 insertions, 334 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 17df1be2fe..885b9664d6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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(). |