vsk created this revision.
vsk added a reviewer: rjmccall.
vsk added a subscriber: cfe-commits.

[CodeGen] Fix assignments of inline layouts into the byref structure

When using blocks, a byref structure is created to represent the
closure. The "byref.layout" field of this structure is an i8*. However,
some 'inline' layouts are represented as i64's, not i8*'s.

Prior to r246985 we cast the i64 'inline' layout to an i8* before
assigning it into the byref structure. This patch brings the cast back
and adds a regression test.

rdar://23713871

http://reviews.llvm.org/D15674

Files:
  lib/CodeGen/CGBlocks.cpp
  lib/CodeGen/CGObjCGNU.cpp
  lib/CodeGen/CGObjCMac.cpp
  lib/CodeGen/CGObjCRuntime.h
  test/CodeGenObjCXX/blocks.mm

Index: test/CodeGenObjCXX/blocks.mm
===================================================================
--- test/CodeGenObjCXX/blocks.mm
+++ test/CodeGenObjCXX/blocks.mm
@@ -68,3 +68,18 @@
     takeBlock(^{ useValues(ptr, this); });
   }
 };
+
+// rdar://problem/23713871
+// Check that we don't crash when using BLOCK_LAYOUT_STRONG.
+#pragma clang assume_nonnull begin
+@interface NSUUID @end
+#pragma clang assume_nonnull end
+
+struct Wrapper1 { NSUUID *Ref; };
+struct Wrapper2 { Wrapper1 W1; };
+
+@implementation B
+- (void) captureStrongRef {
+  __block Wrapper2 W2;
+}
+@end
Index: lib/CodeGen/CGObjCRuntime.h
===================================================================
--- lib/CodeGen/CGObjCRuntime.h
+++ lib/CodeGen/CGObjCRuntime.h
@@ -275,8 +275,9 @@
                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
   virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
-  virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
-                                           QualType T) = 0;
+  virtual llvm::Value *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
+                                        CodeGen::CodeGenFunction &CGF,
+                                        QualType T) = 0;
   virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
                                                bool Weak = false) = 0;
 
Index: lib/CodeGen/CGObjCMac.cpp
===================================================================
--- lib/CodeGen/CGObjCMac.cpp
+++ lib/CodeGen/CGObjCMac.cpp
@@ -1054,8 +1054,9 @@
   llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
                                      const CGBlockInfo &blockInfo) override;
 
-  llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
-                                   QualType T) override;
+  llvm::Value *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
+                                CodeGen::CodeGenFunction &CGF,
+                                QualType T) override;
 };
 
 class CGObjCMac : public CGObjCCommonMac {
@@ -2630,17 +2631,22 @@
 }
 
 
-llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
-                                                  QualType T) {
+llvm::Value *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
+                                               CodeGen::CodeGenFunction &CGF,
+                                               QualType T) {
   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
   assert(!T->isArrayType() && "__block array variable should not be caught");
   CharUnits fieldOffset;
   RunSkipBlockVars.clear();
   bool hasUnion = false;
   if (const RecordType *record = T->getAs<RecordType>()) {
     BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
     llvm::Constant *Result = getBitmapBlockLayout(true);
-    return Result;
+    if (isa<llvm::ConstantInt>(Result))
+      return CGF.Builder.CreateIntToPtr(Result, CGM.Int8PtrTy,
+                                        "byref.layout_cast");
+    else
+      return Result;
   }
   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
   return nullPtr;
Index: lib/CodeGen/CGObjCGNU.cpp
===================================================================
--- lib/CodeGen/CGObjCGNU.cpp
+++ lib/CodeGen/CGObjCGNU.cpp
@@ -565,7 +565,8 @@
     return NULLPtr;
   }
 
-  llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T) override {
+  llvm::Value *BuildByrefLayout(CodeGenModule &CGM, CodeGenFunction &CGF,
+                                QualType T) override {
     return NULLPtr;
   }
 
Index: lib/CodeGen/CGBlocks.cpp
===================================================================
--- lib/CodeGen/CGBlocks.cpp
+++ lib/CodeGen/CGBlocks.cpp
@@ -2242,7 +2242,7 @@
   }
 
   if (ByRefHasLifetime && HasByrefExtendedLayout) {
-    auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
+    auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, *this, type);
     storeHeaderField(layoutInfo, getPointerSize(), "byref.layout");
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to