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">;
|
"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">;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
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, PD->getType(),
|
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
|
||||||
MemberLoc, BaseExpr));
|
MemberLoc, BaseExpr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue