More type checking for properties, accessors and

use of dot-syntax expression. This is to match gcc's.

llvm-svn: 71243
This commit is contained in:
Fariborz Jahanian 2009-05-08 19:36:34 +00:00
parent 6e9959e327
commit b2ab73d93c
4 changed files with 99 additions and 10 deletions

View File

@ -174,7 +174,7 @@ def warn_conflicting_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">; "conflicting parameter types in implementation of %0: %1 vs %2">;
def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
def err_accessor_property_type_mismatch : Error< def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">; "type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared at">; def note_declared_at : Note<"declared at">;
def err_setter_type_void : Error<"type of setter must be void">; def err_setter_type_void : Error<"type of setter must be void">;

View File

@ -1315,11 +1315,17 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (GetterMethod && if (GetterMethod &&
GetterMethod->getResultType() != property->getType()) { GetterMethod->getResultType() != property->getType()) {
Diag(property->getLocation(), AssignConvertType result = Incompatible;
diag::err_accessor_property_type_mismatch) if (Context.isObjCObjectPointerType(property->getType()))
<< property->getDeclName() result = CheckAssignmentConstraints(property->getType(),
<< GetterMethod->getSelector(); GetterMethod->getResultType());
Diag(GetterMethod->getLocation(), diag::note_declared_at); if (result != Compatible) {
Diag(property->getLocation(),
diag::warn_accessor_property_type_mismatch)
<< property->getDeclName()
<< GetterMethod->getSelector();
Diag(GetterMethod->getLocation(), diag::note_declared_at);
}
} }
if (SetterMethod) { if (SetterMethod) {
@ -1329,7 +1335,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (SetterMethod->param_size() != 1 || if (SetterMethod->param_size() != 1 ||
((*SetterMethod->param_begin())->getType() != property->getType())) { ((*SetterMethod->param_begin())->getType() != property->getType())) {
Diag(property->getLocation(), Diag(property->getLocation(),
diag::err_accessor_property_type_mismatch) diag::warn_accessor_property_type_mismatch)
<< property->getDeclName() << property->getDeclName()
<< SetterMethod->getSelector(); << SetterMethod->getSelector();
Diag(SetterMethod->getLocation(), diag::note_declared_at); Diag(SetterMethod->getLocation(), diag::note_declared_at);

View File

@ -2096,8 +2096,21 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// Check whether we can reference this property. // Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc)) if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError(); return ExprError();
QualType ResTy = PD->getType();
return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Context, Sel);
if (Getter) {
AssignConvertType result =
CheckAssignmentConstraints(PD->getType(), Getter->getResultType());
if (result != Compatible) {
Diag(MemberLoc, diag::warn_accessor_property_type_mismatch)
<< PD->getDeclName() << Sel;
Diag(Getter->getLocation(), diag::note_declared_at);
ResTy = Getter->getResultType();
}
}
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
MemberLoc, BaseExpr)); MemberLoc, BaseExpr));
} }

View File

@ -2,7 +2,7 @@
@interface A @interface A
-(float) x; // expected-note {{declared at}} -(float) x; // expected-note {{declared at}}
@property int x; // expected-error {{type of property 'x' does not match type of accessor 'x'}} @property int x; // expected-warning {{type of property 'x' does not match type of accessor 'x'}}
@end @end
@interface A (Cat) @interface A (Cat)
@ -29,3 +29,73 @@ typedef void (F)(void);
@end @end
@class SSyncSet;
@interface SPeer
@property(nonatomic,readonly,retain) SSyncSet* syncSet;
@end
@class SSyncSet_iDisk;
@interface SPeer_iDisk_remote1 : SPeer
- (SSyncSet_iDisk*) syncSet; // expected-note {{declared at}}
@end
@interface SPeer_iDisk_local
- (SSyncSet_iDisk*) syncSet;
@end
@interface SSyncSet
@end
@interface SSyncSet_iDisk
@property(nonatomic,readonly,retain) SPeer_iDisk_local* localPeer;
@end
@interface SPeer_iDisk_remote1 (protected)
@end
@implementation SPeer_iDisk_remote1 (protected)
- (id) preferredSource1
{
return self.syncSet.localPeer; // expected-warning {{type of property 'syncSet' does not match type of accessor 'syncSet'}}
}
@end
@interface NSArray @end
@interface NSMutableArray : NSArray
@end
@interface Class1
{
NSMutableArray* pieces;
NSArray* first;
}
@property (readonly) NSArray* pieces;
@property (readonly) NSMutableArray* first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
- (NSMutableArray*) pieces;
- (NSArray*) first; // expected-note {{declared at}} // expected-note {{declared at}}
@end
@interface Class2 {
Class1* container;
}
@end
@implementation Class2
- (id) lastPiece
{
return container.pieces;
}
- (id)firstPeice
{
return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
}
@end