Hi, i noticed a bigger change in the latest clang and wanted to check if this is intentional or a beta bug. clang in XCode 14.3 is 'carrying over' nullability of objects (objc/c++) with _auto_type/auto [despite assert or inline if]
In 14.2 autotype/auto made an null_unspecified ptr allowing us to downcast / unwrap an object. In 14.3 this isnt possible anymore. => Is there still a way to do 'nullability unwrapping' of any reference in C(objC/C++)
tried but failed workarounds:
- There is an easy workaround by looking at the dereferenced type but that doesnt work with dispatch bloks as they arent dereferencable
- There is also a workaround with objc generics but I cant use that as there might be objects not usable as generics
example
The following is a sample that worked with 14.2 but throws warnings in 14.3
clang:
xcrun clang -fobjc-arc -Wnullable-to-nonnull-conversion -Werror test.m
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#define typename(x) _Generic((x), /* Get the name of a type */ \
id: "id", \
default: "other")
#define fmt "%20s is '%s'\n"
_Pragma("clang diagnostic ignored \"-Wauto-var-id\"")
int main(int argc, char *argv[]) {
@autoreleasepool {
int temp = 666;
NSString *_Nullable s = @"";
id _Nullable s2 = @"";
dispatch_block_t _Nullable s3 = dispatch_block_create(0, ^{});
CFStringRef _Nullable s4 = CFSTR("");
int *_Nullable s5 = &temp;
printf( fmt, "NSString (_Nullable", typename(s));
printf( fmt, "id _Nullable", typename(s2));
printf( fmt, "block _Nullable", typename(s3));
printf( fmt, "CFStringRef _Nullable", typename(s4));
printf( fmt, "int _Nullable", typename(s5));
assert(s != nil);
assert(s2 != nil);
assert(s3 != nil);
assert(s4 != nil);
assert(s5 != nil);
//no modifier works if type is given
// NSString *u = s;
// id u2 = s2;
// dispatch_block_t u3 = s3;
// CFStringRef u4 = s4;
// int *u5 = s5;
// __auto_typeauto carries _nullable in 14.3 but not 14.2
__auto_type u = s;
__auto_type u_with_default = s != nil ? s : @"DEFAULT";
__auto_type u2 = s2;
__auto_type u3 = s3;
__auto_type u4 = s4;
__auto_type u5 = s5;
//auto and decltype have the same behaviour for C++ and even if we use an inline if
//Q: how can I unwrap an optional [not just objc!]
NSString *_Nonnull d = u;
NSString *_Nonnull d_with_default = u_with_default;
id _Nonnull d2 = u2;
dispatch_block_t _Nonnull d3 = u3;
CFStringRef _Nonnull d4 = u4;
int *_Nonnull d5 = u5;
printf( "-------\n");
printf( fmt, "NSString", typename(d));
printf( fmt, "NSString", typename(d_with_default));
printf( fmt, "id", typename(d2));
printf( fmt, "block", typename(d3));
printf( fmt, "CFStringRef", typename(d4));
printf( fmt, "int", typename(d5));
}
}