[cfe-commits] r116237 - in /cfe/trunk: lib/Rewrite/RewriteObjC.cpp lib/Sema/SemaExpr.cpp test/SemaObjC/access-property-getter.m test/SemaObjC/setter-dotsyntax.m
Fariborz Jahanian
fjahanian at apple.com
Mon Oct 11 14:29:12 PDT 2010
Author: fjahanian
Date: Mon Oct 11 16:29:12 2010
New Revision: 116237
URL: http://llvm.org/viewvc/llvm-project?rev=116237&view=rev
Log:
This patch does a few things in the area of objective-c
properties.
1. Generates the AST for lexical info. of accessing
getter/setter methods using dot-syntax notation.
This fixes //rdar: //8528170.
2. Modifes rewriter to handle the AST putout in 1.
3. Supportes in rewriter ObjCImplicitSetterGetter ASTs.
Added:
cfe/trunk/test/SemaObjC/setter-dotsyntax.m
Modified:
cfe/trunk/lib/Rewrite/RewriteObjC.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/SemaObjC/access-property-getter.m
Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=116237&r1=116236&r2=116237&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Mon Oct 11 16:29:12 2010
@@ -139,10 +139,10 @@
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps a property to it's assignment statement.
- llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
+ llvm::DenseMap<Expr *, BinaryOperator *> PropSetters;
// This maps a property to it's synthesied message expression.
// This allows us to rewrite chained getters (e.g. o.a.b.c).
- llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
+ llvm::DenseMap<Expr *, Stmt *> PropGetters;
// This maps an original source AST to it's rewritten form. This allows
// us to avoid rewriting the same node twice (which is very uncommon).
@@ -281,8 +281,8 @@
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
bool &replaced);
Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
- Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
- Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+ Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr);
+ Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
SourceRange SrcRange);
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
@@ -1203,40 +1203,55 @@
"/* @end */");
}
-Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
SourceRange SrcRange) {
- // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
+ ObjCMethodDecl *OMD = 0;
+ QualType Ty;
+ Selector Sel;
+ Stmt *Receiver;
+ // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ObjCImplicitSetterGetterRefExpr.
// This allows us to reuse all the fun and games in SynthMessageExpr().
- ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
- ObjCMessageExpr *MsgExpr;
- ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
+ if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) {
+ ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
+ OMD = PDecl->getSetterMethodDecl();
+ Ty = PDecl->getType();
+ Sel = PDecl->getSetterName();
+ Receiver = PropRefExpr->getBase();
+ }
+ else if (ObjCImplicitSetterGetterRefExpr *ImplicitRefExpr =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(BinOp->getLHS())) {
+ OMD = ImplicitRefExpr->getSetterMethod();
+ Sel = OMD->getSelector();
+ Ty = ImplicitRefExpr->getType();
+ Receiver = ImplicitRefExpr->getBase();
+ }
+
+ assert(OMD && "RewritePropertyOrImplicitSetter - null OMD");
llvm::SmallVector<Expr *, 1> ExprVec;
ExprVec.push_back(newStmt);
- Stmt *Receiver = PropRefExpr->getBase();
- ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
- if (PRE && PropGetters[PRE]) {
- // This allows us to handle chain/nested property getters.
- Receiver = PropGetters[PRE];
- }
+ if (Expr *Exp = dyn_cast<Expr>(Receiver))
+ if (PropGetters[Exp])
+ // This allows us to handle chain/nested property/implicit getters.
+ Receiver = PropGetters[Exp];
+
+ ObjCMessageExpr *MsgExpr;
if (isa<ObjCSuperExpr>(Receiver))
MsgExpr = ObjCMessageExpr::Create(*Context,
- PDecl->getType().getNonReferenceType(),
+ Ty.getNonReferenceType(),
/*FIXME?*/SourceLocation(),
Receiver->getLocStart(),
/*IsInstanceSuper=*/true,
cast<Expr>(Receiver)->getType(),
- PDecl->getSetterName(),
- PDecl->getSetterMethodDecl(),
+ Sel, OMD,
&ExprVec[0], 1,
/*FIXME:*/SourceLocation());
else
MsgExpr = ObjCMessageExpr::Create(*Context,
- PDecl->getType().getNonReferenceType(),
+ Ty.getNonReferenceType(),
/*FIXME: */SourceLocation(),
cast<Expr>(Receiver),
- PDecl->getSetterName(),
- PDecl->getSetterMethodDecl(),
+ Sel, OMD,
&ExprVec[0], 1,
/*FIXME:*/SourceLocation());
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
@@ -1250,38 +1265,53 @@
return ReplacingStmt;
}
-Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
- // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
+Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
+ // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter.
// This allows us to reuse all the fun and games in SynthMessageExpr().
- ObjCMessageExpr *MsgExpr;
- ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
-
- Stmt *Receiver = PropRefExpr->getBase();
-
- ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
- if (PRE && PropGetters[PRE]) {
- // This allows us to handle chain/nested property getters.
- Receiver = PropGetters[PRE];
+ Stmt *Receiver;
+ ObjCMethodDecl *OMD = 0;
+ QualType Ty;
+ Selector Sel;
+ if (ObjCPropertyRefExpr *PropRefExpr =
+ dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) {
+ ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
+ OMD = PDecl->getGetterMethodDecl();
+ Receiver = PropRefExpr->getBase();
+ Ty = PDecl->getType();
+ Sel = PDecl->getGetterName();
+ }
+ else if (ObjCImplicitSetterGetterRefExpr *ImplicitRefExpr =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(PropOrGetterRefExpr)) {
+ OMD = ImplicitRefExpr->getGetterMethod();
+ Receiver = ImplicitRefExpr->getBase();
+ Sel = OMD->getSelector();
+ Ty = ImplicitRefExpr->getType();
}
-
+
+ assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null");
+
+ if (Expr *Exp = dyn_cast<Expr>(Receiver))
+ if (PropGetters[Exp])
+ // This allows us to handle chain/nested property/implicit getters.
+ Receiver = PropGetters[Exp];
+
+ ObjCMessageExpr *MsgExpr;
if (isa<ObjCSuperExpr>(Receiver))
MsgExpr = ObjCMessageExpr::Create(*Context,
- PDecl->getType().getNonReferenceType(),
+ Ty.getNonReferenceType(),
/*FIXME:*/SourceLocation(),
Receiver->getLocStart(),
/*IsInstanceSuper=*/true,
cast<Expr>(Receiver)->getType(),
- PDecl->getGetterName(),
- PDecl->getGetterMethodDecl(),
+ Sel, OMD,
0, 0,
/*FIXME:*/SourceLocation());
else
MsgExpr = ObjCMessageExpr::Create(*Context,
- PDecl->getType().getNonReferenceType(),
+ Ty.getNonReferenceType(),
/*FIXME:*/SourceLocation(),
cast<Expr>(Receiver),
- PDecl->getGetterName(),
- PDecl->getGetterMethodDecl(),
+ Sel, OMD,
0, 0,
/*FIXME:*/SourceLocation());
@@ -1290,17 +1320,18 @@
if (!PropParentMap)
PropParentMap = new ParentMap(CurrentBody);
- Stmt *Parent = PropParentMap->getParent(PropRefExpr);
- if (Parent && isa<ObjCPropertyRefExpr>(Parent)) {
+ Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr);
+ if (Parent && (isa<ObjCPropertyRefExpr>(Parent) ||
+ isa<ObjCImplicitSetterGetterRefExpr>(Parent))) {
// We stash away the ReplacingStmt since actually doing the
// replacement/rewrite won't work for nested getters (e.g. obj.p.i)
- PropGetters[PropRefExpr] = ReplacingStmt;
+ PropGetters[PropOrGetterRefExpr] = ReplacingStmt;
// NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
// to things that stay around.
Context->Deallocate(MsgExpr);
- return PropRefExpr; // return the original...
+ return PropOrGetterRefExpr; // return the original...
} else {
- ReplaceStmt(PropRefExpr, ReplacingStmt);
+ ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt);
// delete PropRefExpr; elsewhere...
// NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
// to things that stay around.
@@ -1346,7 +1377,7 @@
MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
IV->getLocation(),
D->getType());
- // delete IV; leak for now, see RewritePropertySetter() usage for more info.
+ // delete IV; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return ME;
}
// Get the new text
@@ -2024,7 +2055,7 @@
ReplaceStmt(Exp, Replacement);
// Replace this subexpr in the parent.
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return Replacement;
}
@@ -2042,7 +2073,7 @@
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
&SelExprs[0], SelExprs.size());
ReplaceStmt(Exp, SelExp);
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return SelExp;
}
@@ -2588,7 +2619,7 @@
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_Unknown, Unop);
ReplaceStmt(Exp, cast);
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return cast;
}
@@ -2930,7 +2961,7 @@
MsgExprs.push_back(userExpr);
// We've transferred the ownership to MsgExprs. For now, we *don't* null
// out the argument in the original expression (since we aren't deleting
- // the ObjCMessageExpr). See RewritePropertySetter() usage for more info.
+ // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
//Exp->setArg(i, 0);
}
// Generate the funky cast.
@@ -3054,7 +3085,7 @@
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr);
}
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return ReplacingStmt;
}
@@ -3065,7 +3096,7 @@
// Now do the actual rewrite.
ReplaceStmt(Exp, ReplacingStmt);
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return ReplacingStmt;
}
@@ -3101,7 +3132,7 @@
DerefExpr);
ReplaceStmt(Exp, castExpr);
ProtocolExprDecls.insert(Exp->getProtocol());
- // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return castExpr;
}
@@ -5325,8 +5356,12 @@
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
if (BinOp->isAssignmentOp()) {
- if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()))
+ if (ObjCPropertyRefExpr *PRE =
+ dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()))
PropSetters[PRE] = BinOp;
+ else if (ObjCImplicitSetterGetterRefExpr *ISE =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(BinOp->getLHS()))
+ PropSetters[ISE] = BinOp;
}
}
}
@@ -5372,6 +5407,12 @@
++CI;
continue;
}
+ if (ObjCImplicitSetterGetterRefExpr *ISE =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(S))
+ if (PropSetters[ISE]) {
+ ++CI;
+ continue;
+ }
}
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
@@ -5398,8 +5439,11 @@
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
return RewriteAtEncode(AtEncode);
- if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) {
- BinaryOperator *BinOp = PropSetters[PropRefExpr];
+ if (isa<ObjCPropertyRefExpr>(S) || isa<ObjCImplicitSetterGetterRefExpr>(S)) {
+ Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S);
+ assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null");
+
+ BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr];
if (BinOp) {
// Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to rewrite the right hand side prior to rewriting the setter.
@@ -5437,18 +5481,19 @@
// (CStyleCastExpr 0x231d220 'void *'
// (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0))))
//
- // Note that 'newStmt' is passed to RewritePropertySetter so that it
+ // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter so that it
// can be used as the setter argument. ReplaceStmt() will still 'see'
// the original RHS (since we haven't altered BinOp).
//
// This implies the Rewrite* routines can no longer delete the original
// node. As a result, we now leak the original AST nodes.
//
- return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
+ return RewritePropertyOrImplicitSetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
} else {
- return RewritePropertyGetter(PropRefExpr);
+ return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr);
}
}
+
if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
return RewriteAtSelector(AtSelector);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=116237&r1=116236&r2=116237&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct 11 16:29:12 2010
@@ -2531,38 +2531,39 @@
return VT; // should never get here (a typedef type should always be found).
}
-static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
+static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
IdentifierInfo *Member,
const Selector &Sel,
ASTContext &Context) {
-
- if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
- return PD;
+ if (Member)
+ if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
+ return PD;
if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
return OMD;
for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
E = PDecl->protocol_end(); I != E; ++I) {
- if (Decl *D = FindGetterNameDeclFromProtocolList(*I, Member, Sel,
- Context))
+ if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ Context))
return D;
}
return 0;
}
-static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
- IdentifierInfo *Member,
- const Selector &Sel,
- ASTContext &Context) {
+static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
+ IdentifierInfo *Member,
+ const Selector &Sel,
+ ASTContext &Context) {
// Check protocols on qualified interfaces.
Decl *GDecl = 0;
for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
- GDecl = PD;
- break;
- }
- // Also must look for a getter name which uses property syntax.
+ if (Member)
+ if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ GDecl = PD;
+ break;
+ }
+ // Also must look for a getter or setter name which uses property syntax.
if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
GDecl = OMD;
break;
@@ -2572,7 +2573,8 @@
for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
// Search in the protocol-qualifier list of current protocol.
- GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context);
+ GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ Context);
if (GDecl)
return GDecl;
}
@@ -3273,7 +3275,8 @@
// Check protocols on qualified interfaces.
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
- if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
+ if (Decl *PMDecl = FindGetterSetterNameDecl(QIdTy, Member, Sel,
+ Context)) {
if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
// Check the use of this declaration
if (DiagnoseUseOfDecl(PD, MemberLoc))
@@ -3286,14 +3289,18 @@
// Check the use of this method.
if (DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError();
- // It is important that start and end position is the first character
- // and last character position of the property-dot syntax expression.
- SourceLocation MemberEndLoc = PP.getLocForEndOfToken(MemberLoc, 1);
- return Owned(ObjCMessageExpr::Create(Context,
- OMD->getSendResultType(),
- BaseExpr->getExprLoc(),
- BaseExpr, Sel,
- OMD, NULL, 0, MemberEndLoc));
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), Member);
+ ObjCMethodDecl *SMD = 0;
+ if (Decl *SDecl = FindGetterSetterNameDecl(QIdTy, /*Property id*/0,
+ SetterSel, Context))
+ SMD = dyn_cast<ObjCMethodDecl>(SDecl);
+ QualType PType = OMD->getSendResultType();
+ return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(OMD, PType,
+ SMD,
+ MemberLoc,
+ BaseExpr));
}
}
Modified: cfe/trunk/test/SemaObjC/access-property-getter.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/access-property-getter.m?rev=116237&r1=116236&r2=116237&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/access-property-getter.m (original)
+++ cfe/trunk/test/SemaObjC/access-property-getter.m Mon Oct 11 16:29:12 2010
@@ -30,7 +30,7 @@
@implementation XCWorkQueueCommandCacheFetchInvocation
- (id)harvestPredictivelyProcessedOutputFiles
{
- _outputStream.release;
+ _outputStream.release; // expected-warning {{property access result unused - getters should not be used for side effects}}
return 0;
}
@end
Added: cfe/trunk/test/SemaObjC/setter-dotsyntax.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/setter-dotsyntax.m?rev=116237&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/setter-dotsyntax.m (added)
+++ cfe/trunk/test/SemaObjC/setter-dotsyntax.m Mon Oct 11 16:29:12 2010
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar: //8528170
+
+ at interface NSObject @end
+
+ at protocol MyProtocol
+- (int) level;
+- (void) setLevel:(int)inLevel;
+ at end
+
+ at interface MyClass : NSObject <MyProtocol>
+ at end
+
+int main ()
+{
+ id<MyProtocol> c;
+ c.level = 10;
+ return 0;
+}
More information about the cfe-commits
mailing list