Mercurial > hg > CbC > CbC_llvm
diff clang/test/CodeGenObjC/ubsan-nullability.m @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 2e18cbf3894f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/test/CodeGenObjC/ubsan-nullability.m Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,225 @@ +// REQUIRES: asserts +// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s + +// CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6 +// CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 +// CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9 +// CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10 +// CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 506, i32 10 +// CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25 +// CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26 +// CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29 +// CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 800, i32 6 + +#define NULL ((void *)0) +#define INULL ((int *)NULL) +#define INNULL ((int *_Nonnull)NULL) + +// CHECK-LABEL: define i32* @{{.*}}nonnull_retval1 +#line 100 +int *_Nonnull nonnull_retval1(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]] + return p; + // CHECK: ret i32* +} + +#line 190 +void nonnull_arg(int *_Nonnull p) {} + +// CHECK-LABEL: define void @{{.*}}call_func_with_nonnull_arg +#line 200 +void call_func_with_nonnull_arg(int *_Nonnull p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]] + nonnull_arg(p); +} + +// CHECK-LABEL: define void @{{.*}}nonnull_assign1 +#line 300 +void nonnull_assign1(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]] + int *_Nonnull local; + local = p; +} + +// CHECK-LABEL: define void @{{.*}}nonnull_assign2 +#line 400 +void nonnull_assign2(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]] + int *_Nonnull arr[1]; + arr[0] = p; +} + +struct S1 { + int *_Nonnull mptr; +}; + +// CHECK-LABEL: define void @{{.*}}nonnull_assign3 +#line 500 +void nonnull_assign3(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]] + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + struct S1 s; + s.mptr = p; +} + +// CHECK-LABEL: define void @{{.*}}nonnull_init1 +#line 600 +void nonnull_init1(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]] + int *_Nonnull local = p; +} + +// CHECK-LABEL: define void @{{.*}}nonnull_init2 +#line 700 +void nonnull_init2(int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]] + // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]] + int *_Nonnull arr[] = {p, p}; +} + +// CHECK-LABEL: define i32* @{{.*}}nonnull_retval2 +#line 800 +int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. + int *_Nonnull arg2, //< Test this. + int *_Nullable arg3, //< Don't test the rest. + int *arg4, + int arg5, ...) { + // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize + // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize + // CHECK: [[ARG2CMP:%.*]] = icmp ne i32* %arg2, null, !nosanitize + // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]] + // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr + // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null + // CHECK-NEXT: [[DO_RV_CHECK_3:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK_2]] + // CHECK: br i1 [[DO_RV_CHECK_3]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize + // CHECK: [[NULL]]: + // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]] + return arg1; + // CHECK: [[NONULL]]: + // CHECK-NEXT: ret i32* +} + +@interface A ++(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1; +-(int *_Nonnull) objc_method: (int *_Nonnull) arg1; +@end + +@implementation A + +// CHECK-LABEL: define internal i32* @"\01+[A objc_clsmethod:]" ++(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 { + // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize + // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] + // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr + // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null + // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] + // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize + // CHECK: [[NULL]]: + // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_return{{.*}} + return arg1; + // CHECK: [[NONULL]]: + // CHECK-NEXT: ret i32* +} + +// CHECK-LABEL: define internal i32* @"\01-[A objc_method:]" +-(int *_Nonnull) objc_method: (int *_Nonnull) arg1 { + // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize + // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] + // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr + // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null + // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] + // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize + // CHECK: [[NULL]]: + // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_return{{.*}} + return arg1; + // CHECK: [[NONULL]]: + // CHECK-NEXT: ret i32* +} +@end + +// CHECK-LABEL: define void @{{.*}}call_A +void call_A(A *a, int *p) { + // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize + // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]]) + [a objc_method: p]; + + // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize + // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]]) + [A objc_clsmethod: p]; +} + +void dont_crash(int *_Nonnull p, ...) {} + +@protocol NSObject +- (id)init; +@end +@interface NSObject <NSObject> {} +@end + +#pragma clang assume_nonnull begin + +/// Create a "NSObject * _Nonnull" instance. +NSObject *get_nonnull_error() { + // Use nil for convenience. The actual object doesn't matter. + return (NSObject *)NULL; +} + +NSObject *_Nullable no_null_return_value_diagnostic(int flag) { +// CHECK-LABEL: define internal {{.*}}no_null_return_value_diagnostic{{i?}}_block_invoke +// CHECK-NOT: @__ubsan_handle_nullability_return + NSObject *_Nullable (^foo)() = ^() { + if (flag) { + // Clang should not infer a nonnull return value for this block when this + // call is present. + return get_nonnull_error(); + } else { + return (NSObject *)NULL; + } + }; + return foo(); +} + +#pragma clang assume_nonnull end + +int main() { + nonnull_retval1(INULL); + nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0); + call_func_with_nonnull_arg(INNULL); + nonnull_assign1(INULL); + nonnull_assign2(INULL); + nonnull_assign3(INULL); + nonnull_init1(INULL); + nonnull_init2(INULL); + call_A((A *)NULL, INULL); + dont_crash(INNULL, NULL); + no_null_return_value_diagnostic(0); + no_null_return_value_diagnostic(1); + return 0; +}