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)); } }