1) Why does this retain its __block var:
{
    void (^blockWithOutPointer)(NSObject * __autoreleasing *) = ^(NSObject * __autoreleasing * outPointer) {
        *outPointer = [NSObject new];
    };
    NSObject * __block blockVar1;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                 (int64_t)(1 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(),
                   ^{
                       NSLog(@"blockVar1: %@",
                             blockVar1);
                       // prints non-nil. WHY????
                   });
    blockWithOutPointer(&blockVar1);
}
2) But this doesn't?
void (^blockWithOutPointerThatDispatchesLater)(NSObject * __autoreleasing *,
                                               dispatch_block_t) = ^(NSObject * __autoreleasing * outPointer,
                                                                     dispatch_block_t block) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                 (int64_t)(1 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(),
                   block);
    *outPointer = [NSObject new];
};
{
    NSObject * __block blockVar2;
    blockWithOutPointerThatDispatchesLater(&blockVar2,
                                           ^{
                                               NSLog(@"blockVar2: %@",
                                                     blockVar2);
                                           });
    // prints nil, which is expected.
}
3) If I instead use an __autoreleasing variable as my out pointer destination, and then assign that variable to my __block pointer, everything works fine.
{
    NSObject * __autoreleasing autoreleasingVar;
    NSObject * __block blockVar3;
    blockWithOutPointerThatDispatchesLater(&autoreleasingVar,
                                           ^{
                                               NSLog(@"blockVar3: %@",
                                                     blockVar3);
                                           });
    blockVar3 = autoreleasingVar;
    // prints non-nil, which is expected.
}
I've read CRD's answer about ARC pointer-to-pointer issues, it makes sense that #2 would print nil because ARC assumes that blockVar2 is __autoreleasing, and doesn't retain its value. Thus, in #3, when we assign autoreleasingVar to blockVar3, ARC properly retains the value. However, there is no such assignment for #1. Why does #1 retain its value?
Even more amazingly, #1 is unaffected if I wrap the out-pointer assignment in an @autoreleasepool:
{
    void (^blockWithOutPointer)(NSObject * __autoreleasing *) = ^(NSObject * __autoreleasing * outPointer) {
        @autoreleasepool {
            *outPointer = [NSObject new];
        }
    };
    NSObject * __block blockVar1;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                 (int64_t)(1 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(),
                   ^{
                       NSLog(@"blockVar1: %@",
                             blockVar1);
                       // still prints non-nil. WHY???
                   });
    blockWithOutPointer(&blockVar1);
}
Whereas #3 crashes, as expected since the @autoreleasepool released the out-pointer's object, and I guess ARC doesn't set __autoreleasing variables to nil.
void (^blockWithOutPointerThatDispatchesLater)(NSObject * __autoreleasing *,
                                               dispatch_block_t) = ^(NSObject * __autoreleasing * outPointer,
                                                                     dispatch_block_t block) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                 (int64_t)(1 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(),
                   block);
    @autoreleasepool {
        *outPointer = [NSObject new];
    }
};
{
    NSObject * __autoreleasing autoreleasingVar;
    NSObject * __block blockVar3;
    blockWithOutPointerThatDispatchesLater(&autoreleasingVar,
                                           ^{
                                               NSLog(@"blockVar3: %@",
                                                     blockVar3);
                                               // crashes on the NSLog!
                                           });
    blockVar3 = autoreleasingVar;
}
I filed a radar about this.