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.

llvm-svn: 116237
This commit is contained in:
Fariborz Jahanian 2010-10-11 21:29:12 +00:00
parent 8827889d89
commit f3f903a9f0
4 changed files with 155 additions and 84 deletions

View File

@ -139,10 +139,10 @@ namespace {
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps a property to it's assignment statement. // 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 maps a property to it's synthesied message expression.
// This allows us to rewrite chained getters (e.g. o.a.b.c). // 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 // 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). // us to avoid rewriting the same node twice (which is very uncommon).
@ -281,8 +281,8 @@ namespace {
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
bool &replaced); bool &replaced);
Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr); Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr);
Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
SourceRange SrcRange); SourceRange SrcRange);
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
@ -1203,40 +1203,55 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
"/* @end */"); "/* @end */");
} }
Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
SourceRange SrcRange) { 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(). // This allows us to reuse all the fun and games in SynthMessageExpr().
ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()); if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) {
ObjCMessageExpr *MsgExpr; ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
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; llvm::SmallVector<Expr *, 1> ExprVec;
ExprVec.push_back(newStmt); ExprVec.push_back(newStmt);
Stmt *Receiver = PropRefExpr->getBase(); if (Expr *Exp = dyn_cast<Expr>(Receiver))
ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); if (PropGetters[Exp])
if (PRE && PropGetters[PRE]) { // This allows us to handle chain/nested property/implicit getters.
// This allows us to handle chain/nested property getters. Receiver = PropGetters[Exp];
Receiver = PropGetters[PRE];
} ObjCMessageExpr *MsgExpr;
if (isa<ObjCSuperExpr>(Receiver)) if (isa<ObjCSuperExpr>(Receiver))
MsgExpr = ObjCMessageExpr::Create(*Context, MsgExpr = ObjCMessageExpr::Create(*Context,
PDecl->getType().getNonReferenceType(), Ty.getNonReferenceType(),
/*FIXME?*/SourceLocation(), /*FIXME?*/SourceLocation(),
Receiver->getLocStart(), Receiver->getLocStart(),
/*IsInstanceSuper=*/true, /*IsInstanceSuper=*/true,
cast<Expr>(Receiver)->getType(), cast<Expr>(Receiver)->getType(),
PDecl->getSetterName(), Sel, OMD,
PDecl->getSetterMethodDecl(),
&ExprVec[0], 1, &ExprVec[0], 1,
/*FIXME:*/SourceLocation()); /*FIXME:*/SourceLocation());
else else
MsgExpr = ObjCMessageExpr::Create(*Context, MsgExpr = ObjCMessageExpr::Create(*Context,
PDecl->getType().getNonReferenceType(), Ty.getNonReferenceType(),
/*FIXME: */SourceLocation(), /*FIXME: */SourceLocation(),
cast<Expr>(Receiver), cast<Expr>(Receiver),
PDecl->getSetterName(), Sel, OMD,
PDecl->getSetterMethodDecl(),
&ExprVec[0], 1, &ExprVec[0], 1,
/*FIXME:*/SourceLocation()); /*FIXME:*/SourceLocation());
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
@ -1250,38 +1265,53 @@ Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
return ReplacingStmt; return ReplacingStmt;
} }
Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
// Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr. // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter.
// This allows us to reuse all the fun and games in SynthMessageExpr(). // This allows us to reuse all the fun and games in SynthMessageExpr().
ObjCMessageExpr *MsgExpr; Stmt *Receiver;
ObjCPropertyDecl *PDecl = PropRefExpr->getProperty(); ObjCMethodDecl *OMD = 0;
QualType Ty;
Stmt *Receiver = PropRefExpr->getBase(); Selector Sel;
if (ObjCPropertyRefExpr *PropRefExpr =
ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) {
if (PRE && PropGetters[PRE]) { ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
// This allows us to handle chain/nested property getters. OMD = PDecl->getGetterMethodDecl();
Receiver = PropGetters[PRE]; 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)) if (isa<ObjCSuperExpr>(Receiver))
MsgExpr = ObjCMessageExpr::Create(*Context, MsgExpr = ObjCMessageExpr::Create(*Context,
PDecl->getType().getNonReferenceType(), Ty.getNonReferenceType(),
/*FIXME:*/SourceLocation(), /*FIXME:*/SourceLocation(),
Receiver->getLocStart(), Receiver->getLocStart(),
/*IsInstanceSuper=*/true, /*IsInstanceSuper=*/true,
cast<Expr>(Receiver)->getType(), cast<Expr>(Receiver)->getType(),
PDecl->getGetterName(), Sel, OMD,
PDecl->getGetterMethodDecl(),
0, 0, 0, 0,
/*FIXME:*/SourceLocation()); /*FIXME:*/SourceLocation());
else else
MsgExpr = ObjCMessageExpr::Create(*Context, MsgExpr = ObjCMessageExpr::Create(*Context,
PDecl->getType().getNonReferenceType(), Ty.getNonReferenceType(),
/*FIXME:*/SourceLocation(), /*FIXME:*/SourceLocation(),
cast<Expr>(Receiver), cast<Expr>(Receiver),
PDecl->getGetterName(), Sel, OMD,
PDecl->getGetterMethodDecl(),
0, 0, 0, 0,
/*FIXME:*/SourceLocation()); /*FIXME:*/SourceLocation());
@ -1290,17 +1320,18 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
if (!PropParentMap) if (!PropParentMap)
PropParentMap = new ParentMap(CurrentBody); PropParentMap = new ParentMap(CurrentBody);
Stmt *Parent = PropParentMap->getParent(PropRefExpr); Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr);
if (Parent && isa<ObjCPropertyRefExpr>(Parent)) { if (Parent && (isa<ObjCPropertyRefExpr>(Parent) ||
isa<ObjCImplicitSetterGetterRefExpr>(Parent))) {
// We stash away the ReplacingStmt since actually doing the // We stash away the ReplacingStmt since actually doing the
// replacement/rewrite won't work for nested getters (e.g. obj.p.i) // 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 // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
// to things that stay around. // to things that stay around.
Context->Deallocate(MsgExpr); Context->Deallocate(MsgExpr);
return PropRefExpr; // return the original... return PropOrGetterRefExpr; // return the original...
} else { } else {
ReplaceStmt(PropRefExpr, ReplacingStmt); ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt);
// delete PropRefExpr; elsewhere... // delete PropRefExpr; elsewhere...
// NOTE: We don't want to call MsgExpr->Destroy(), as it holds references // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
// to things that stay around. // to things that stay around.
@ -1346,7 +1377,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
MemberExpr *ME = new (Context) MemberExpr(PE, true, D, MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
IV->getLocation(), IV->getLocation(),
D->getType()); 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; return ME;
} }
// Get the new text // Get the new text
@ -2024,7 +2055,7 @@ Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
ReplaceStmt(Exp, Replacement); ReplaceStmt(Exp, Replacement);
// Replace this subexpr in the parent. // 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; return Replacement;
} }
@ -2042,7 +2073,7 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
&SelExprs[0], SelExprs.size()); &SelExprs[0], SelExprs.size());
ReplaceStmt(Exp, SelExp); 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; return SelExp;
} }
@ -2588,7 +2619,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
CK_Unknown, Unop); CK_Unknown, Unop);
ReplaceStmt(Exp, cast); 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; return cast;
} }
@ -2930,7 +2961,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
MsgExprs.push_back(userExpr); MsgExprs.push_back(userExpr);
// We've transferred the ownership to MsgExprs. For now, we *don't* null // 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 // 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); //Exp->setArg(i, 0);
} }
// Generate the funky cast. // Generate the funky cast.
@ -3054,7 +3085,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr); 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; return ReplacingStmt;
} }
@ -3065,7 +3096,7 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
// Now do the actual rewrite. // Now do the actual rewrite.
ReplaceStmt(Exp, ReplacingStmt); 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; return ReplacingStmt;
} }
@ -3101,7 +3132,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
DerefExpr); DerefExpr);
ReplaceStmt(Exp, castExpr); ReplaceStmt(Exp, castExpr);
ProtocolExprDecls.insert(Exp->getProtocol()); 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; return castExpr;
} }
@ -5325,8 +5356,12 @@ void RewriteObjC::CollectPropertySetters(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
if (BinOp->isAssignmentOp()) { if (BinOp->isAssignmentOp()) {
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) if (ObjCPropertyRefExpr *PRE =
dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()))
PropSetters[PRE] = BinOp; PropSetters[PRE] = BinOp;
else if (ObjCImplicitSetterGetterRefExpr *ISE =
dyn_cast<ObjCImplicitSetterGetterRefExpr>(BinOp->getLHS()))
PropSetters[ISE] = BinOp;
} }
} }
} }
@ -5372,6 +5407,12 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
++CI; ++CI;
continue; continue;
} }
if (ObjCImplicitSetterGetterRefExpr *ISE =
dyn_cast<ObjCImplicitSetterGetterRefExpr>(S))
if (PropSetters[ISE]) {
++CI;
continue;
}
} }
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
@ -5398,8 +5439,11 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
return RewriteAtEncode(AtEncode); return RewriteAtEncode(AtEncode);
if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) { if (isa<ObjCPropertyRefExpr>(S) || isa<ObjCImplicitSetterGetterRefExpr>(S)) {
BinaryOperator *BinOp = PropSetters[PropRefExpr]; Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S);
assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null");
BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr];
if (BinOp) { if (BinOp) {
// Because the rewriter doesn't allow us to rewrite rewritten code, // Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to rewrite the right hand side prior to rewriting the setter. // we need to rewrite the right hand side prior to rewriting the setter.
@ -5437,18 +5481,19 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// (CStyleCastExpr 0x231d220 'void *' // (CStyleCastExpr 0x231d220 'void *'
// (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0)))) // (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' // can be used as the setter argument. ReplaceStmt() will still 'see'
// the original RHS (since we haven't altered BinOp). // the original RHS (since we haven't altered BinOp).
// //
// This implies the Rewrite* routines can no longer delete the original // This implies the Rewrite* routines can no longer delete the original
// node. As a result, we now leak the original AST nodes. // 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 { } else {
return RewritePropertyGetter(PropRefExpr); return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr);
} }
} }
if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
return RewriteAtSelector(AtSelector); return RewriteAtSelector(AtSelector);

View File

@ -2531,38 +2531,39 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
return VT; // should never get here (a typedef type should always be found). 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, IdentifierInfo *Member,
const Selector &Sel, const Selector &Sel,
ASTContext &Context) { ASTContext &Context) {
if (Member)
if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member)) if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
return PD; return PD;
if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
return OMD; return OMD;
for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
E = PDecl->protocol_end(); I != E; ++I) { E = PDecl->protocol_end(); I != E; ++I) {
if (Decl *D = FindGetterNameDeclFromProtocolList(*I, Member, Sel, if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
Context)) Context))
return D; return D;
} }
return 0; return 0;
} }
static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
IdentifierInfo *Member, IdentifierInfo *Member,
const Selector &Sel, const Selector &Sel,
ASTContext &Context) { ASTContext &Context) {
// Check protocols on qualified interfaces. // Check protocols on qualified interfaces.
Decl *GDecl = 0; Decl *GDecl = 0;
for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) { E = QIdTy->qual_end(); I != E; ++I) {
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { if (Member)
GDecl = PD; if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
break; GDecl = PD;
} break;
// Also must look for a getter name which uses property syntax. }
// Also must look for a getter or setter name which uses property syntax.
if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
GDecl = OMD; GDecl = OMD;
break; break;
@ -2572,7 +2573,8 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) { E = QIdTy->qual_end(); I != E; ++I) {
// Search in the protocol-qualifier list of current protocol. // Search in the protocol-qualifier list of current protocol.
GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context); GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
Context);
if (GDecl) if (GDecl)
return GDecl; return GDecl;
} }
@ -3273,7 +3275,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Check protocols on qualified interfaces. // Check protocols on qualified interfaces.
Selector Sel = PP.getSelectorTable().getNullarySelector(Member); 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)) { if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
// Check the use of this declaration // Check the use of this declaration
if (DiagnoseUseOfDecl(PD, MemberLoc)) if (DiagnoseUseOfDecl(PD, MemberLoc))
@ -3286,14 +3289,18 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Check the use of this method. // Check the use of this method.
if (DiagnoseUseOfDecl(OMD, MemberLoc)) if (DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError(); return ExprError();
// It is important that start and end position is the first character Selector SetterSel =
// and last character position of the property-dot syntax expression. SelectorTable::constructSetterName(PP.getIdentifierTable(),
SourceLocation MemberEndLoc = PP.getLocForEndOfToken(MemberLoc, 1); PP.getSelectorTable(), Member);
return Owned(ObjCMessageExpr::Create(Context, ObjCMethodDecl *SMD = 0;
OMD->getSendResultType(), if (Decl *SDecl = FindGetterSetterNameDecl(QIdTy, /*Property id*/0,
BaseExpr->getExprLoc(), SetterSel, Context))
BaseExpr, Sel, SMD = dyn_cast<ObjCMethodDecl>(SDecl);
OMD, NULL, 0, MemberEndLoc)); QualType PType = OMD->getSendResultType();
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(OMD, PType,
SMD,
MemberLoc,
BaseExpr));
} }
} }

View File

@ -30,7 +30,7 @@
@implementation XCWorkQueueCommandCacheFetchInvocation @implementation XCWorkQueueCommandCacheFetchInvocation
- (id)harvestPredictivelyProcessedOutputFiles - (id)harvestPredictivelyProcessedOutputFiles
{ {
_outputStream.release; _outputStream.release; // expected-warning {{property access result unused - getters should not be used for side effects}}
return 0; return 0;
} }
@end @end

View File

@ -0,0 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar: //8528170
@interface NSObject @end
@protocol MyProtocol
- (int) level;
- (void) setLevel:(int)inLevel;
@end
@interface MyClass : NSObject <MyProtocol>
@end
int main ()
{
id<MyProtocol> c;
c.level = 10;
return 0;
}