From 9abf88c9286d7465ce18285f87bb302f588b59fc Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 15 May 2012 22:37:04 +0000 Subject: [PATCH] objective-c: perform strict type checking on property type and its accessor type and issue error if types are incompatible, instead of crashing in IRgen. // rdar://1105153 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156871 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/Sema/SemaObjCProperty.cpp | 47 ++++++++++++++++------ test/SemaObjC/property-impl-misuse.m | 13 ++++++ test/SemaObjC/property-typecheck-1.m | 12 +++--- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7436f8b396..0865619e6d 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -685,6 +685,8 @@ def err_incomplete_synthesized_property : Error< def error_property_ivar_type : Error< "type of property %0 (%1) does not match type of ivar %2 (%3)">; +def error_property_accessor_type : Error< + "type of property %0 (%1) does not match type of accessor %2 (%3)">; def error_ivar_in_superclass_use : Error< "property %0 attempting to use ivar %1 declared in super class %2">; def error_weak_property : Error< diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e826b47784..f42259c686 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1050,21 +1050,42 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, ObjCMethodDecl *GetterMethod, SourceLocation Loc) { - if (GetterMethod && - !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(), - property->getType().getNonReferenceType())) { - AssignConvertType result = Incompatible; - if (property->getType()->isObjCObjectPointerType()) - result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), - property->getType()); - if (result != Compatible) { - Diag(Loc, diag::warn_accessor_property_type_mismatch) - << property->getDeclName() - << GetterMethod->getSelector(); - Diag(GetterMethod->getLocation(), diag::note_declared_at); - return true; + if (!GetterMethod) + return false; + QualType GetterType = GetterMethod->getResultType().getNonReferenceType(); + QualType PropertyIvarType = property->getType().getNonReferenceType(); + bool compat = Context.hasSameType(PropertyIvarType, GetterType); + if (!compat) { + if (isa(PropertyIvarType) && + isa(GetterType)) + compat = + Context.canAssignObjCInterfaces( + PropertyIvarType->getAs(), + GetterType->getAs()); + else if (CheckAssignmentConstraints(Loc, PropertyIvarType, GetterType) + != Compatible) { + Diag(Loc, diag::error_property_accessor_type) + << property->getDeclName() << PropertyIvarType + << GetterMethod->getSelector() << GetterType; + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } else { + compat = true; + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); + if (lhsType != rhsType && lhsType->isArithmeticType()) + compat = false; } } + + if (!compat) { + Diag(Loc, diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << GetterMethod->getSelector(); + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } + return false; } diff --git a/test/SemaObjC/property-impl-misuse.m b/test/SemaObjC/property-impl-misuse.m index c3cedb05ed..1d3d64ce31 100644 --- a/test/SemaObjC/property-impl-misuse.m +++ b/test/SemaObjC/property-impl-misuse.m @@ -34,3 +34,16 @@ self.gradientStyle; // expected-error {{property 'gradientStyle' not found on object of type 'Class'}} } @end + +// rdar://1105153 +@interface rdar1105153 +@property int P; // expected-error {{type of property 'P' ('int') does not match type of accessor 'P' ('void')}} +- (void)P; // expected-note {{declared here}} + +@property int P1; // expected-warning {{type of property 'P1' does not match type of accessor 'P1'}} +- (double) P1; // expected-note {{declared here}} + +@property int P2; // expected-error {{type of property 'P2' ('int') does not match type of accessor 'P2' ('double *')}} +- (double*)P2; // expected-note {{declared here}} + +@end diff --git a/test/SemaObjC/property-typecheck-1.m b/test/SemaObjC/property-typecheck-1.m index f71e4a0f1c..b28108ac85 100644 --- a/test/SemaObjC/property-typecheck-1.m +++ b/test/SemaObjC/property-typecheck-1.m @@ -73,11 +73,11 @@ typedef void (F)(void); NSArray* first; } -@property (readonly) NSArray* pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} -@property (readonly) NSMutableArray* first; +@property (readonly) NSArray* pieces; +@property (readonly) NSMutableArray* first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}} -- (NSMutableArray*) pieces; // expected-note {{declared here}} // expected-note {{declared here}} -- (NSArray*) first; +- (NSMutableArray*) pieces; +- (NSArray*) first; // expected-note 2 {{declared here}} @end @interface Class2 { @@ -90,12 +90,12 @@ typedef void (F)(void); - (id) lastPiece { - return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} + return container.pieces; } - (id)firstPeice { - return container.first; + return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}} } @end -- 2.40.0