From 4c2743f0afe601b0e8ea7bd9b3cd0fb09083a181 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 8 May 2009 19:36:34 +0000 Subject: [PATCH] More type checking for properties, accessors and use of dot-syntax expression. This is to match gcc's. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71243 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 +- lib/Sema/SemaDeclObjC.cpp | 18 ++++-- lib/Sema/SemaExpr.cpp | 17 ++++- test/SemaObjC/property-typecheck-1.m | 72 +++++++++++++++++++++- 4 files changed, 99 insertions(+), 10 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f4da725314..a8d079d720 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index e35b7a919b..34afdedba7 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 79c471a2d4..f698620543 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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)); } diff --git a/test/SemaObjC/property-typecheck-1.m b/test/SemaObjC/property-typecheck-1.m index 1795da8599..c4d7cd2448 100644 --- a/test/SemaObjC/property-typecheck-1.m +++ b/test/SemaObjC/property-typecheck-1.m @@ -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 + -- 2.40.0