forked from OSchip/llvm-project
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:
parent
6e9959e327
commit
b2ab73d93c
|
@ -174,7 +174,7 @@ def warn_conflicting_param_types : Warning<
|
|||
"conflicting parameter types in implementation of %0: %1 vs %2">;
|
||||
|
||||
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">;
|
||||
def note_declared_at : Note<"declared at">;
|
||||
def err_setter_type_void : Error<"type of setter must be void">;
|
||||
|
|
|
@ -1315,11 +1315,17 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
|
||||
if (GetterMethod &&
|
||||
GetterMethod->getResultType() != property->getType()) {
|
||||
Diag(property->getLocation(),
|
||||
diag::err_accessor_property_type_mismatch)
|
||||
<< property->getDeclName()
|
||||
<< GetterMethod->getSelector();
|
||||
Diag(GetterMethod->getLocation(), diag::note_declared_at);
|
||||
AssignConvertType result = Incompatible;
|
||||
if (Context.isObjCObjectPointerType(property->getType()))
|
||||
result = CheckAssignmentConstraints(property->getType(),
|
||||
GetterMethod->getResultType());
|
||||
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) {
|
||||
|
@ -1329,7 +1335,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
|
|||
if (SetterMethod->param_size() != 1 ||
|
||||
((*SetterMethod->param_begin())->getType() != property->getType())) {
|
||||
Diag(property->getLocation(),
|
||||
diag::err_accessor_property_type_mismatch)
|
||||
diag::warn_accessor_property_type_mismatch)
|
||||
<< property->getDeclName()
|
||||
<< SetterMethod->getSelector();
|
||||
Diag(SetterMethod->getLocation(), diag::note_declared_at);
|
||||
|
|
|
@ -2096,8 +2096,21 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
// Check whether we can reference this property.
|
||||
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
||||
return ExprError();
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
|
||||
QualType ResTy = 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));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
@interface A
|
||||
-(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
|
||||
|
||||
@interface A (Cat)
|
||||
|
@ -29,3 +29,73 @@ typedef void (F)(void);
|
|||
@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
|
||||
|
||||
|
|
Loading…
Reference in New Issue