def warn_property_getter_owning_mismatch : Warning<
"property declared as returning non-retained objects"
"; getter returning retained objects">;
+def warn_property_setter_ambiguous_use : Warning<
+ "synthesized properties '%0' and '%1' both claim setter %2 -"
+ " use of this setter may cause unexpected behavior">,
+ InGroup<DiagGroup<"objc-multiple-property-setter-use">>;
def err_ownin_getter_rule : Error<
"property's synthesized getter follows Cocoa naming"
" convention for returning 'owned' objects">;
return ExprError();
// Search for a declared property first.
- ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member);
- if (PD) {
+ if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
SelectorTable::constructSetterName(PP.getIdentifierTable(),
PP.getSelectorTable(), Member);
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
- // Check for corner case of: @property int p; ... self.P = 0;
- // setter name is synthesized "setP" but there is no property name 'P'.
- if (Setter && Setter->isSynthesized() && !PD)
+ if (Setter && Setter->isSynthesized())
+ // Check for corner case of: @property int p; ... self.P = 0;
+ // setter name is synthesized "setP" but there is no property name 'P'.
Setter = 0;
-
+
// May be founf in property's qualified list.
if (!Setter)
Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);
#include "clang/Sema/Initialization.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
using namespace sema;
Expr *op);
bool tryBuildGetOfReference(Expr *op, ExprResult &result);
- bool findSetter();
+ bool findSetter(bool warn=true);
bool findGetter();
Expr *rebuildAndCaptureObject(Expr *syntacticBase);
/// reference.
///
/// \return true if a setter was found, in which case Setter
-bool ObjCPropertyOpBuilder::findSetter() {
+bool ObjCPropertyOpBuilder::findSetter(bool warn) {
// For implicit properties, just trust the lookup we already did.
if (RefExpr->isImplicitProperty()) {
if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
// Do a normal method lookup first.
if (ObjCMethodDecl *setter =
LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
+ if (setter->isSynthesized() && warn)
+ if (const ObjCInterfaceDecl *IFace =
+ dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
+ const StringRef thisPropertyName(prop->getName());
+ char front = thisPropertyName.front();
+ front = islower(front) ? toupper(front) : tolower(front);
+ SmallString<100> PropertyName = thisPropertyName;
+ PropertyName[0] = front;
+ IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
+ if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
+ if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
+ S.Diag(RefExpr->getExprLoc(), diag::warn_property_setter_ambiguous_use)
+ << prop->getName() << prop1->getName() << setter->getSelector();
+ S.Diag(prop->getLocation(), diag::note_property_declare);
+ S.Diag(prop1->getLocation(), diag::note_property_declare);
+ }
+ }
Setter = setter;
return true;
}
/// value being set as the value of the property operation.
ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
bool captureSetValueAsResult) {
- bool hasSetter = findSetter();
+ bool hasSetter = findSetter(false);
assert(hasSetter); (void) hasSetter;
if (SyntacticRefExpr)
@property (copy) id p;
@property (copy) id r;
@property (copy) id Q;
-@property (copy) id t;
-@property (copy) id T;
+@property (copy) id t; // expected-note 2 {{property declared here}}
+@property (copy) id T; // expected-note 2 {{property declared here}}
+@property (copy) id Pxyz; // expected-note 2 {{property declared here}}
+@property (copy) id pxyz; // expected-note 2 {{property declared here}}
@end
@implementation rdar11363363
@synthesize r;
@synthesize Q;
@synthesize t, T;
+@synthesize Pxyz, pxyz;
- (id) Meth {
self.P = 0; // expected-error {{property 'P' not found on object of type 'rdar11363363 *'}}
self.q = 0; // expected-error {{property 'q' not found on object of type 'rdar11363363 *'}}
- self.t = 0; // OK
- self.T = 0; // OK
+// rdar://11528439
+ self.t = 0; // expected-warning {{synthesized properties 't' and 'T' both claim setter 'setT:'}}
+ self.T = 0; // expected-warning {{synthesized properties 'T' and 't' both claim setter 'setT:'}}
+ self.Pxyz = 0; // expected-warning {{synthesized properties 'Pxyz' and 'pxyz' both claim setter 'setPxyz:'}}
+ self.pxyz = 0; // expected-warning {{synthesized properties 'pxyz' and 'Pxyz' both claim setter 'setPxyz:'}}
self.R = 0; // expected-error {{property 'R' not found on object of type 'rdar11363363 *'; did you mean to access ivar 'R'?}}
return self.R; // expected-error {{property 'R' not found on object of type 'rdar11363363 *'; did you mean to access ivar 'R'?}}
}