| // RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx11.0.0 -fobjc-runtime=macosx-11.0.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fobjc-constant-literals -fconstant-nsnumber-literals -fconstant-nsarray-literals -fconstant-nsdictionary-literals -O2 -disable-llvm-passes -o - %s | FileCheck %s |
| |
| #include "literal-support.h" |
| |
| #if __has_feature(objc_constant_literals) |
| |
| #if __has_feature(objc_bool) |
| #define YES __objc_yes |
| #define NO __objc_no |
| #else |
| #define YES ((BOOL)1) |
| #define NO ((BOOL)0) |
| #endif |
| |
| // Check that the constant classes were picked and emitted |
| // CHECK: %struct.__builtin_NSDictionary = type { ptr, i64, i64, ptr, ptr } |
| // CHECK: %struct.__builtin_NSConstantIntegerNumber = type { ptr, ptr, i64 } |
| // CHECK: %struct.__builtin_NSArray = type { ptr, i64, ptr } |
| // CHECK: %struct.__builtin_NSConstantDoubleNumber = type { ptr, double } |
| // CHECK: %struct.__builtin_NSConstantFloatNumber = type { ptr, float } |
| |
| // Ensure we're able to use literals at global scope |
| |
| // CHECK: @"OBJC_CLASS_$_NSConstantDictionary" = external global %struct._class_t |
| // CHECK: @_unnamed_array_storage = internal unnamed_addr constant [1 x ptr] [ptr @_unnamed_cfstring_], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_array_storage.3 = internal unnamed_addr constant [1 x ptr] [ptr @_unnamed_cfstring_.2], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsdictionary_ = private constant %struct.__builtin_NSDictionary { ptr @"OBJC_CLASS_$_NSConstantDictionary", i64 1, i64 1, ptr @_unnamed_array_storage, ptr @_unnamed_array_storage.3 }, section "__DATA,__objc_dictobj,regular,no_dead_strip", align 8 |
| // CHECK: @dict = global ptr @_unnamed_nsdictionary_, align 8 |
| NSDictionary *dict = @{@"fast food" : @"burger"}; |
| |
| // CHECK: @"OBJC_CLASS_$_NSConstantIntegerNumber" = external global %struct._class_t |
| // CHECK: @.str.4 = private unnamed_addr constant [2 x i8] c"i\00", align 1 |
| // CHECK: @_unnamed_nsconstantintegernumber_ = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.4, i64 42 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| // CHECK: @__kCFBooleanTrue = external global ptr |
| // CHECK: @"OBJC_CLASS_$_NSConstantArray" = external global %struct._class_t |
| // CHECK: @_unnamed_array_storage.5 = internal unnamed_addr constant [2 x ptr] [ptr @_unnamed_nsconstantintegernumber_, ptr @__kCFBooleanTrue], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsarray_ = private constant %struct.__builtin_NSArray { ptr @"OBJC_CLASS_$_NSConstantArray", i64 2, ptr @_unnamed_array_storage.5 }, section "__DATA,__objc_arrayobj,regular,no_dead_strip", align 8 |
| // CHECK: @arr = global ptr @_unnamed_nsarray_, align 8 |
| NSArray *arr = @[ @42, @YES ]; |
| |
| // CHECK: @"OBJC_CLASS_$_NSConstantDoubleNumber" = external global %struct._class_t |
| // CHECK: @_unnamed_nsconstantdoublenumber_ = private constant %struct.__builtin_NSConstantDoubleNumber { ptr @"OBJC_CLASS_$_NSConstantDoubleNumber", double 6.000000e+00 }, section "__DATA,__objc_doubleobj,regular,no_dead_strip", align 8 |
| // CHECK: @num = global ptr @_unnamed_nsconstantdoublenumber_, align 8 |
| NSNumber *num = @(2 + 4.0); |
| |
| // CHECK: @_unnamed_nsconstantintegernumber_.6 = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.4, i64 17 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsconstantintegernumber_.8 = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.7, i64 25 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsconstantintegernumber_.10 = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.9, i64 42 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsconstantintegernumber_.12 = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.11, i64 97 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| |
| // Check globals are emitted for test_array |
| // CHECK: @_unnamed_array_storage.15 = internal unnamed_addr constant [2 x ptr] [ptr @_unnamed_cfstring_.14, ptr @_unnamed_nsconstantintegernumber_], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsarray_.16 = private constant %struct.__builtin_NSArray { ptr @"OBJC_CLASS_$_NSConstantArray", i64 2, ptr @_unnamed_array_storage.15 }, section "__DATA,__objc_arrayobj,regular,no_dead_strip", align 8 |
| |
| // Check globals are emitted for test_dictionary |
| // CHECK: @"OBJC_CLASS_$_NSConstantFloatNumber" = external global %struct._class_t |
| // CHECK: @_unnamed_nsconstantfloatnumber_ = private constant %struct.__builtin_NSConstantFloatNumber { ptr @"OBJC_CLASS_$_NSConstantFloatNumber", float 2.200000e+01 }, section "__DATA,__objc_floatobj,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_array_storage.27 = internal unnamed_addr constant [3 x ptr] [ptr @_unnamed_cfstring_.18, ptr @_unnamed_cfstring_.26, ptr @_unnamed_cfstring_.22], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_array_storage.28 = internal unnamed_addr constant [3 x ptr] [ptr @_unnamed_cfstring_.20, ptr @_unnamed_nsconstantfloatnumber_, ptr @_unnamed_cfstring_.24], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsdictionary_.29 = private constant %struct.__builtin_NSDictionary { ptr @"OBJC_CLASS_$_NSConstantDictionary", i64 1, i64 3, ptr @_unnamed_array_storage.27, ptr @_unnamed_array_storage.28 }, section "__DATA,__objc_dictobj,regular,no_dead_strip", align 8 |
| |
| // CHECK: @_unnamed_nsconstantintegernumber_.30 = private constant %struct.__builtin_NSConstantIntegerNumber { ptr @"OBJC_CLASS_$_NSConstantIntegerNumber", ptr @.str.9, i64 -1 }, section "__DATA,__objc_intobj,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_array_storage.31 = internal unnamed_addr constant [1 x ptr] [ptr @_unnamed_nsconstantintegernumber_.30], section "__DATA,__objc_arraydata,regular,no_dead_strip", align 8 |
| // CHECK: @_unnamed_nsarray_.32 = private constant %struct.__builtin_NSArray { ptr @"OBJC_CLASS_$_NSConstantArray", i64 1, ptr @_unnamed_array_storage.31 }, section "__DATA,__objc_arrayobj,regular,no_dead_strip", align 8 |
| |
| // CHECK-LABEL: define void @test_numeric() |
| void test_numeric() { |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsconstantintegernumber_.6) |
| id ilit = @17; |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsconstantintegernumber_.8) |
| id ulit = @25u; |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsconstantintegernumber_.10) |
| id ulllit = @42ull; |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsconstantintegernumber_.12) |
| id charlit = @'a'; |
| } |
| |
| // CHECK-LABEL: define void @test_array |
| void test_array(id a, id b) { |
| |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsarray_.16) |
| id arr = @[ @"meaningOfLife", @42 ]; |
| } |
| |
| // CHECK-LABEL: define void @test_dictionary |
| void test_dictionary(id k1, id o1, id k2, id o2) { |
| |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsdictionary_.29) |
| id dict = @{@"fruit" : @"apple", |
| @"vegetable" : @"carrot", |
| @"number" : @22.0f}; |
| } |
| |
| // CHECK-LABEL: define void @test_int64array( |
| void test_int64array() { |
| // CHECK: call ptr @llvm.objc.retain(ptr @_unnamed_nsarray_.32) |
| id arr = @[@(0xFFFFFFFFFFFFFFFF)]; |
| } |
| |
| #endif |