]> granicus.if.org Git - clang/commitdiff
objective-c: fix a sema and IRGen crash when property
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 29 May 2012 19:56:01 +0000 (19:56 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 29 May 2012 19:56:01 +0000 (19:56 +0000)
getter result type is safe but does not match with property
type resulting in spurious warning followed by crash in
IRGen. // rdar://11515196

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157641 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenFunction.h
lib/Sema/SemaObjCProperty.cpp
test/CodeGenObjC/getter-property-type-mismatch.m [new file with mode: 0644]
test/SemaObjC/property-typecheck-1.m

index a10822b7576926691f40580b09563a2f45d26d40..254f63c863b3a8cf131a84674304d25737a6b4c6 100644 (file)
@@ -30,7 +30,7 @@ typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
 static TryEmitResult
 tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
 static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
-                                      const Expr *E,
+                                      QualType ET,
                                       const ObjCMethodDecl *Method,
                                       RValue Result);
 
@@ -202,20 +202,20 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
 /// \brief Adjust the type of the result of an Objective-C message send 
 /// expression when the method has a related result type.
 static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
-                                      const Expr *E,
+                                      QualType ExpT,
                                       const ObjCMethodDecl *Method,
                                       RValue Result) {
   if (!Method)
     return Result;
 
   if (!Method->hasRelatedResultType() ||
-      CGF.getContext().hasSameType(E->getType(), Method->getResultType()) ||
+      CGF.getContext().hasSameType(ExpT, Method->getResultType()) ||
       !Result.isScalar())
     return Result;
   
   // We have applied a related result type. Cast the rvalue appropriately.
   return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(),
-                                               CGF.ConvertType(E->getType())));
+                                               CGF.ConvertType(ExpT)));
 }
 
 /// Decide whether to extend the lifetime of the receiver of a
@@ -401,7 +401,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
     Builder.CreateStore(newSelf, selfAddr);
   }
 
-  return AdjustRelatedResultType(*this, E, method, result);
+  return AdjustRelatedResultType(*this, E->getType(), method, result);
 }
 
 namespace {
@@ -710,7 +710,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
   assert(OMD && "Invalid call to generate getter (empty method)");
   StartObjCMethod(OMD, IMP->getClassInterface(), OMD->getLocStart());
 
-  generateObjCGetterBody(IMP, PID, AtomicHelperFn);
+  generateObjCGetterBody(IMP, PID, OMD, AtomicHelperFn);
 
   FinishFunction();
 }
@@ -772,6 +772,7 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
                                         const ObjCPropertyImplDecl *propImpl,
+                                        const ObjCMethodDecl *GetterMethodDecl,
                                         llvm::Constant *AtomicHelperFn) {
   // If there's a non-trivial 'get' expression, we just have to emit that.
   if (!hasTrivialGetExpr(propImpl)) {
@@ -905,6 +906,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
         }
 
         value = Builder.CreateBitCast(value, ConvertType(propType));
+        value = Builder.CreateBitCast(value, 
+                  ConvertType(GetterMethodDecl->getResultType()));
       }
       
       EmitReturnOfRValue(RValue::get(value), propType);
index 91022de59e1ede69947b0d578e5bfca9044911cd..de7e89e3911b0bfb9e759f1773ba1233ad49c5f2 100644 (file)
@@ -1310,6 +1310,7 @@ public:
                           const ObjCPropertyImplDecl *PID);
   void generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
                               const ObjCPropertyImplDecl *propImpl,
+                              const ObjCMethodDecl *GetterMothodDecl,
                               llvm::Constant *AtomicHelperFn);
 
   void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
index 88de7d315e13ec3d4e025c7d873bde4c0d1037fb..fb49e9f50cc784972931b84fd164280d66e094e0 100644 (file)
@@ -1114,9 +1114,9 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
         isa<ObjCObjectPointerType>(GetterType))
       compat =
         Context.canAssignObjCInterfaces(
-                                      PropertyIvarType->getAs<ObjCObjectPointerType>(),
-                                      GetterType->getAs<ObjCObjectPointerType>());
-    else if (CheckAssignmentConstraints(Loc, PropertyIvarType, GetterType) 
+                                      GetterType->getAs<ObjCObjectPointerType>(),
+                                      PropertyIvarType->getAs<ObjCObjectPointerType>());
+    else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) 
               != Compatible) {
           Diag(Loc, diag::error_property_accessor_type)
             << property->getDeclName() << PropertyIvarType
diff --git a/test/CodeGenObjC/getter-property-type-mismatch.m b/test/CodeGenObjC/getter-property-type-mismatch.m
new file mode 100644 (file)
index 0000000..c7e1c1a
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10  -emit-llvm -o - %s | FileCheck %s
+// rdar://11515196
+
+@interface NSArray @end
+
+@interface NSMutableArray : NSArray
+- (void) addObject;
+@end
+
+@interface BPXLAppDelegate
+
+- (NSArray *)arrayOfThings;
+
+@end
+
+
+@interface BPXLAppDelegate ()
+@property (retain, nonatomic) NSMutableArray *arrayOfThings;
+@end
+
+@implementation BPXLAppDelegate
+
+@synthesize arrayOfThings=_arrayOfThings;
+
+- (void)applicationDidFinishLaunching
+{
+   [self.arrayOfThings addObject];
+}
+
+@end
+
+// CHECK: define internal [[RET:%.*]]* @"\01-[BPXLAppDelegate arrayOfThings
+// CHECK: [[THREE:%.*]] = bitcast [[OPQ:%.*]]* [[TWO:%.*]] to [[RET]]*
+// CHECK: ret [[RET]]* [[THREE]]
+
index b28108ac85d1c5a26f01c4fa14363011d1f18454..58d0f215cd92728d9bfde14fa2125a245a0a5305 100644 (file)
@@ -73,11 +73,11 @@ typedef void (F)(void);
  NSArray* first;
 }
 
-@property (readonly) NSArray* pieces;
-@property (readonly) NSMutableArray* first;  // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
+@property (readonly) NSArray* pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
+@property (readonly) NSMutableArray* first;
 
-- (NSMutableArray*) pieces;
-- (NSArray*) first; // expected-note 2 {{declared here}}
+- (NSMutableArray*) pieces; // expected-note 2 {{declared here}}
+- (NSArray*) first;
 @end
 
 @interface Class2  {
@@ -90,12 +90,12 @@ typedef void (F)(void);
 
 - (id) lastPiece
 {
- return container.pieces;
+ return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
 }
 
 - (id)firstPeice
 {
-  return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
+  return container.first;
 }
 @end