title: The signature of BOOL in a swift closure is wrong in a 32-bit iOS device
body: <p>The BOOL's signature is &quot;<strong>B</strong>&quot; normally in objective-c, <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html" rel="nofollow noreferrer">Reference</a>.</p>
  <p>But on a <strong>32-bit device</strong>. BOOL's signature is &quot;<strong>c</strong>&quot;. <a href="https://stackoverflow.com/a/26621855/9315497">Reference</a></p>
  <h3>Interesting finding</h3>
  <p>The interesting thing is that the BOOL in a swift closure is &quot;<strong>B</strong>&quot; on a <strong>32-bit device</strong> (Should be &quot;<strong>c</strong>&quot;).</p>
  <p>For example, this is a swift closure.</p>
  <pre class="lang-swift prettyprint-override"><code>let closure = {_ in        
  } as @convention(block) (Bool) -&gt; Void
  </code></pre>
  <p>The closure's signature is <strong>v8@?0B4</strong> on <strong>32-bit device</strong>. By right it should be <strong>v8@?0c4</strong>.</p>
  <h3>How to verify it?</h3>
  <p><code>sh_blockSignature</code>(c code) is the function to get the signature from a block</p>
  <p>test.m</p>
  <pre class="lang-objectivec prettyprint-override"><code>enum {
      // Set to true on blocks that have captures (and thus are not true
      // global blocks) but are known not to escape for various other
      // reasons. For backward compatibility with old runtimes, whenever
      // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
      // non-escaping block returns the original block and releasing such a
      // block is a no-op, which is exactly how global blocks are handled.
      BLOCK_IS_NOESCAPE      =  (1 &lt;&lt; 23),
      
      BLOCK_HAS_COPY_DISPOSE =  (1 &lt;&lt; 25),
      BLOCK_HAS_CTOR =          (1 &lt;&lt; 26), // helpers have C++ code
      BLOCK_IS_GLOBAL =         (1 &lt;&lt; 28),
      BLOCK_HAS_STRET =         (1 &lt;&lt; 29), // IFF BLOCK_HAS_SIGNATURE
      BLOCK_HAS_SIGNATURE =     (1 &lt;&lt; 30),
  };
  
  struct Block_literal_1 {
      void *isa; // initialized to &amp;_NSConcreteStackBlock or &amp;_NSConcreteGlobalBlock
      int flags;
      int reserved;
      void (*invoke)(void *, ...);
      struct Block_descriptor_1 {
          unsigned long int reserved;         // NULL
          unsigned long int size;         // sizeof(struct Block_literal_1)
          // optional helper functions
          void (*copy_helper)(void *dst, void *src);     // IFF (1&lt;&lt;25)
          void (*dispose_helper)(void *src);             // IFF (1&lt;&lt;25)
          // required ABI.2010.3.16
          const char *signature;                         // IFF (1&lt;&lt;30)
      } *descriptor;
      // imported variables
  };
  
  const char * _Nullable sh_blockSignature(id block)
  {
      struct Block_literal_1 *layout = (__bridge void *)block;
      if (!(layout-&gt;flags &amp; BLOCK_HAS_SIGNATURE))
          return nil;
      
      void *descRef = layout-&gt;descriptor;
      descRef += 2 * sizeof(unsigned long int);
      
      if (layout-&gt;flags &amp; BLOCK_HAS_COPY_DISPOSE)
          descRef += 2 * sizeof(void *);
      
      if (!descRef) return nil;
      
      const char *signature = (*(const char **)descRef);
      return signature;
  }
  </code></pre>
  <p>test2.swift</p>
  <pre class="lang-swift prettyprint-override"><code>let closure = {_ in 
  } as @convention(block) (Bool) -&gt; Void
  let p = sh_blockSignature(closure)!
  let signature = String.init(cString: p)  
  print(signature)  // &quot;v8@?0B4&quot;
  </code></pre>
  <p>Is this a swift bug on 32-bit device?</p>