[cfe-commits] r142915 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaExpr.cpp
John McCall
rjmccall at apple.com
Tue Oct 25 01:42:34 PDT 2011
Author: rjmccall
Date: Tue Oct 25 03:42:34 2011
New Revision: 142915
URL: http://llvm.org/viewvc/llvm-project?rev=142915&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=142915&r1=142914&r2=142915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Oct 25 03:42:34 2011
@@ -31,6 +31,7 @@
SemaLookup.cpp
SemaObjCProperty.cpp
SemaOverload.cpp
+ SemaPseudoObject.cpp
SemaStmt.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=142915&r1=142914&r2=142915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Oct 25 03:42:34 2011
@@ -6960,51 +6960,41 @@
/// 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 @@
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().
More information about the cfe-commits
mailing list