
Msan needs noundef consistency between interface and implementation. If we call C++ from C we can have noundef on C++ side, and no noundef on caller C side, noundef implementation will not set TLS for return value, no noundef caller will expect it. Then we have false reports in msan. The workaround could be set TLS to zero even for noundef return values. However if we do that always it will increase binary size by about 10%. If we do that selectively we need to handle "address is taken" functions, any non local functions, and probably all function which have musttail callers. Which is still a lot. The existing implementation of HasStrictReturn refers to C standard as the reason not enforcing noundef. I believe it applies only to the case when return statement is omitted. Testing on Google codebase I never see such cases, however I've see tens of cases where C code returns actual uninitialized variables, but we ignore that it because of "omitted return" case. So this patch will: 1. fix false-positives with TLS missmatch. 2. detect bugs returning uninitialized variables for C as well. 3. report "omitted return" cases stricter than C, which is already a warning and very likely a bug in a code anyway. Reviewed By: kda Differential Revision: https://reviews.llvm.org/D139296
123 lines
9.7 KiB
C
123 lines
9.7 KiB
C
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
|
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s --check-prefix=CHECK-LIFETIME
|
|
|
|
// We shouldn't have markers at -O0 or with msan.
|
|
// RUN: %clang_cc1 -O0 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s --check-prefix=CHECK-OPTNONE
|
|
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=memory | FileCheck %s --check-prefix=CHECK-MSAN
|
|
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=kernel-memory | FileCheck %s --check-prefix=CHECK-KMSAN
|
|
|
|
// There is no exception to handle here, lifetime.end is not a destructor,
|
|
// so there is no need have cleanup dest slot related code
|
|
|
|
// CHECK-LIFETIME-LABEL: @test(
|
|
// CHECK-LIFETIME-NEXT: entry:
|
|
// CHECK-LIFETIME-NEXT: [[X:%.*]] = alloca i32, align 4
|
|
// CHECK-LIFETIME-NEXT: [[P:%.*]] = alloca ptr, align 8
|
|
// CHECK-LIFETIME-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2:[0-9]+]], !dbg [[DBG9:![0-9]+]]
|
|
// CHECK-LIFETIME-NEXT: store i32 3, ptr [[X]], align 4, !dbg [[DBG10:![0-9]+]], !tbaa [[TBAA11:![0-9]+]]
|
|
// CHECK-LIFETIME-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG15:![0-9]+]]
|
|
// CHECK-LIFETIME-NEXT: store volatile ptr [[X]], ptr [[P]], align 8, !dbg [[DBG16:![0-9]+]], !tbaa [[TBAA17:![0-9]+]]
|
|
// CHECK-LIFETIME-NEXT: [[P_0_P_0_P_0_P_0_:%.*]] = load volatile ptr, ptr [[P]], align 8, !dbg [[DBG19:![0-9]+]], !tbaa [[TBAA17]]
|
|
// CHECK-LIFETIME-NEXT: [[TMP0:%.*]] = load i32, ptr [[P_0_P_0_P_0_P_0_]], align 4, !dbg [[DBG20:![0-9]+]], !tbaa [[TBAA11]]
|
|
// CHECK-LIFETIME-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG21:![0-9]+]]
|
|
// CHECK-LIFETIME-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2]], !dbg [[DBG21]]
|
|
// CHECK-LIFETIME-NEXT: ret i32 [[TMP0]], !dbg [[DBG22:![0-9]+]]
|
|
//
|
|
// CHECK-OPTNONE-LABEL: @test(
|
|
// CHECK-OPTNONE-NEXT: entry:
|
|
// CHECK-OPTNONE-NEXT: [[X:%.*]] = alloca i32, align 4
|
|
// CHECK-OPTNONE-NEXT: [[P:%.*]] = alloca ptr, align 8
|
|
// CHECK-OPTNONE-NEXT: store i32 3, ptr [[X]], align 4, !dbg [[DBG9:![0-9]+]]
|
|
// CHECK-OPTNONE-NEXT: store volatile ptr [[X]], ptr [[P]], align 8, !dbg [[DBG10:![0-9]+]]
|
|
// CHECK-OPTNONE-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !dbg [[DBG11:![0-9]+]]
|
|
// CHECK-OPTNONE-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !dbg [[DBG12:![0-9]+]]
|
|
// CHECK-OPTNONE-NEXT: ret i32 [[TMP1]], !dbg [[DBG13:![0-9]+]]
|
|
//
|
|
// CHECK-MSAN-LABEL: @test(
|
|
// CHECK-MSAN-NEXT: entry:
|
|
// CHECK-MSAN-NEXT: [[X:%.*]] = alloca i32, align 4
|
|
// CHECK-MSAN-NEXT: [[P:%.*]] = alloca ptr, align 8
|
|
// CHECK-MSAN-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2:[0-9]+]], !dbg [[DBG9:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[X]] to i64, !dbg [[DBG9]]
|
|
// CHECK-MSAN-NEXT: [[TMP1:%.*]] = xor i64 [[TMP0]], 87960930222080, !dbg [[DBG9]]
|
|
// CHECK-MSAN-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr, !dbg [[DBG9]]
|
|
// CHECK-MSAN-NEXT: store i32 0, ptr [[TMP2]], align 4, !dbg [[DBG10:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: store i32 3, ptr [[X]], align 4, !dbg [[DBG10]], !tbaa [[TBAA11:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG15:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[P]] to i64, !dbg [[DBG15]]
|
|
// CHECK-MSAN-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 87960930222080, !dbg [[DBG15]]
|
|
// CHECK-MSAN-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr, !dbg [[DBG15]]
|
|
// CHECK-MSAN-NEXT: store i64 0, ptr [[TMP5]], align 8, !dbg [[DBG16:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: store volatile ptr [[X]], ptr [[P]], align 8, !dbg [[DBG16]], !tbaa [[TBAA17:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: [[P_0_P_0_P_0_P_0_:%.*]] = load volatile ptr, ptr [[P]], align 8, !dbg [[DBG19:![0-9]+]], !tbaa [[TBAA17]]
|
|
// CHECK-MSAN-NEXT: [[_MSLD:%.*]] = load i64, ptr [[TMP5]], align 8, !dbg [[DBG19]]
|
|
// CHECK-MSAN-NEXT: [[_MSCMP_NOT:%.*]] = icmp eq i64 [[_MSLD]], 0, !dbg [[DBG20:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: br i1 [[_MSCMP_NOT]], label [[TMP7:%.*]], label [[TMP6:%.*]], !dbg [[DBG20]], !prof [[PROF21:![0-9]+]]
|
|
// CHECK-MSAN: 6:
|
|
// CHECK-MSAN-NEXT: call void @__msan_warning_noreturn() #[[ATTR3:[0-9]+]], !dbg [[DBG20]]
|
|
// CHECK-MSAN-NEXT: unreachable, !dbg [[DBG20]]
|
|
// CHECK-MSAN: 7:
|
|
// CHECK-MSAN-NEXT: [[TMP8:%.*]] = load i32, ptr [[P_0_P_0_P_0_P_0_]], align 4, !dbg [[DBG20]], !tbaa [[TBAA11]]
|
|
// CHECK-MSAN-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[P_0_P_0_P_0_P_0_]] to i64, !dbg [[DBG20]]
|
|
// CHECK-MSAN-NEXT: [[TMP10:%.*]] = xor i64 [[TMP9]], 87960930222080, !dbg [[DBG20]]
|
|
// CHECK-MSAN-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr, !dbg [[DBG20]]
|
|
// CHECK-MSAN-NEXT: [[_MSLD1:%.*]] = load i32, ptr [[TMP11]], align 4, !dbg [[DBG20]]
|
|
// CHECK-MSAN-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG22:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2]], !dbg [[DBG22]]
|
|
// CHECK-MSAN-NEXT: [[_MSCMP2_NOT:%.*]] = icmp eq i32 [[_MSLD1]], 0, !dbg [[DBG23:![0-9]+]]
|
|
// CHECK-MSAN-NEXT: br i1 [[_MSCMP2_NOT]], label [[TMP13:%.*]], label [[TMP12:%.*]], !dbg [[DBG23]], !prof [[PROF21]]
|
|
// CHECK-MSAN: 12:
|
|
// CHECK-MSAN-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]], !dbg [[DBG23]]
|
|
// CHECK-MSAN-NEXT: unreachable, !dbg [[DBG23]]
|
|
// CHECK-MSAN: 13:
|
|
// CHECK-MSAN-NEXT: ret i32 [[TMP8]], !dbg [[DBG23]]
|
|
//
|
|
// CHECK-KMSAN-LABEL: @test(
|
|
// CHECK-KMSAN-NEXT: entry:
|
|
// CHECK-KMSAN-NEXT: [[TMP0:%.*]] = call ptr @__msan_get_context_state() #[[ATTR2:[0-9]+]]
|
|
// CHECK-KMSAN-NEXT: [[X:%.*]] = alloca i32, align 4
|
|
// CHECK-KMSAN-NEXT: [[P:%.*]] = alloca ptr, align 8
|
|
// CHECK-KMSAN-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2]], !dbg [[DBG9:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: call void @__msan_poison_alloca(ptr nonnull [[X]], i64 4, ptr nonnull @[[GLOB0:[0-9]+]]) #[[ATTR2]], !dbg [[DBG9]]
|
|
// CHECK-KMSAN-NEXT: [[TMP1:%.*]] = call { ptr, ptr } @__msan_metadata_ptr_for_store_4(ptr nonnull [[X]]) #[[ATTR2]], !dbg [[DBG10:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: [[TMP2:%.*]] = extractvalue { ptr, ptr } [[TMP1]], 0, !dbg [[DBG10]]
|
|
// CHECK-KMSAN-NEXT: store i32 0, ptr [[TMP2]], align 4, !dbg [[DBG10]]
|
|
// CHECK-KMSAN-NEXT: store i32 3, ptr [[X]], align 4, !dbg [[DBG10]], !tbaa [[TBAA11:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG15:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: call void @__msan_poison_alloca(ptr nonnull [[P]], i64 8, ptr nonnull @[[GLOB1:[0-9]+]]) #[[ATTR2]], !dbg [[DBG15]]
|
|
// CHECK-KMSAN-NEXT: [[TMP3:%.*]] = call { ptr, ptr } @__msan_metadata_ptr_for_store_8(ptr nonnull [[P]]) #[[ATTR2]], !dbg [[DBG16:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: [[TMP4:%.*]] = extractvalue { ptr, ptr } [[TMP3]], 0, !dbg [[DBG16]]
|
|
// CHECK-KMSAN-NEXT: store i64 0, ptr [[TMP4]], align 8, !dbg [[DBG16]]
|
|
// CHECK-KMSAN-NEXT: store volatile ptr [[X]], ptr [[P]], align 8, !dbg [[DBG16]], !tbaa [[TBAA17:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: [[P_0_P_0_P_0_P_0_:%.*]] = load volatile ptr, ptr [[P]], align 8, !dbg [[DBG19:![0-9]+]], !tbaa [[TBAA17]]
|
|
// CHECK-KMSAN-NEXT: [[TMP5:%.*]] = call { ptr, ptr } @__msan_metadata_ptr_for_load_8(ptr nonnull [[P]]) #[[ATTR2]], !dbg [[DBG19]]
|
|
// CHECK-KMSAN-NEXT: [[TMP6:%.*]] = extractvalue { ptr, ptr } [[TMP5]], 0, !dbg [[DBG19]]
|
|
// CHECK-KMSAN-NEXT: [[_MSLD:%.*]] = load i64, ptr [[TMP6]], align 8, !dbg [[DBG19]]
|
|
// CHECK-KMSAN-NEXT: [[_MSCMP_NOT:%.*]] = icmp eq i64 [[_MSLD]], 0, !dbg [[DBG20:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: br i1 [[_MSCMP_NOT]], label [[TMP10:%.*]], label [[TMP7:%.*]], !dbg [[DBG20]], !prof [[PROF21:![0-9]+]]
|
|
// CHECK-KMSAN: 7:
|
|
// CHECK-KMSAN-NEXT: [[TMP8:%.*]] = extractvalue { ptr, ptr } [[TMP5]], 1, !dbg [[DBG19]]
|
|
// CHECK-KMSAN-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 8, !dbg [[DBG19]]
|
|
// CHECK-KMSAN-NEXT: call void @__msan_warning(i32 [[TMP9]]) #[[ATTR3:[0-9]+]], !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: br label [[TMP10]], !dbg [[DBG20]]
|
|
// CHECK-KMSAN: 10:
|
|
// CHECK-KMSAN-NEXT: [[RETVAL_ORIGIN:%.*]] = getelementptr { [100 x i64], [100 x i64], [100 x i64], [100 x i64], i64, [200 x i32], i32, i32 }, ptr [[TMP0]], i64 0, i32 6
|
|
// CHECK-KMSAN-NEXT: [[RETVAL_SHADOW:%.*]] = getelementptr { [100 x i64], [100 x i64], [100 x i64], [100 x i64], i64, [200 x i32], i32, i32 }, ptr [[TMP0]], i64 0, i32 1
|
|
// CHECK-KMSAN-NEXT: [[TMP11:%.*]] = load i32, ptr [[P_0_P_0_P_0_P_0_]], align 4, !dbg [[DBG20]], !tbaa [[TBAA11]]
|
|
// CHECK-KMSAN-NEXT: [[TMP12:%.*]] = call { ptr, ptr } @__msan_metadata_ptr_for_load_4(ptr nonnull [[P_0_P_0_P_0_P_0_]]) #[[ATTR2]], !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: [[TMP13:%.*]] = extractvalue { ptr, ptr } [[TMP12]], 0, !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: [[TMP14:%.*]] = extractvalue { ptr, ptr } [[TMP12]], 1, !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: [[_MSLD1:%.*]] = load i32, ptr [[TMP13]], align 4, !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4, !dbg [[DBG20]]
|
|
// CHECK-KMSAN-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[P]]), !dbg [[DBG22:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]]) #[[ATTR2]], !dbg [[DBG22]]
|
|
// CHECK-KMSAN-NEXT: store i32 [[_MSLD1]], ptr [[RETVAL_SHADOW]], align 8, !dbg [[DBG23:![0-9]+]]
|
|
// CHECK-KMSAN-NEXT: store i32 [[TMP15]], ptr [[RETVAL_ORIGIN]], align 4, !dbg [[DBG23]]
|
|
// CHECK-KMSAN-NEXT: ret i32 [[TMP11]], !dbg [[DBG23]]
|
|
//
|
|
int test(void) {
|
|
int x = 3;
|
|
int *volatile p = &x;
|
|
return *p;
|
|
}
|