Files
llvm-project/clang/test/CIR/CodeGen/predefined-expr.c
Erich Keane 7484eb7488 [CIR] Ensure strings are null-terminated, better deal with trailing null (#185513)
Our current implementation of string lowering did some work to remove
extra trailing zeros, plus do a 'zero' constant. That is unchanged by
this patch. However, this patch ALSO ensures that we do the 'remove
extra trailing zeros' to remove ALL trailing zeros, which likely has
canonicalization benefits later on.

However, the real benefit of this patch is to make string emission by
default emit a null-terminator, which fixes the virtual table 'name'
field get lowered correctly. We do this by making the builder::getString
function take an argument (true by default) that will ensure we add a
null terminator if necessary.

This reflects the llvm::ConstantDataArray::getString function, which has
the same functionality. However, doing this during lowering seems
incorrect, since the FE is the one that knows whether these null
terminators are necessary. There is not currently an 'opt out' use of
the behavior, but the functionality is left in place to better reflect
the ConstantDataArray::getString function interface.

Note with the tests that this fixes some inconsistencies between LLVM
and OGCG lowering.
2026-03-10 07:02:36 -07:00

88 lines
5.4 KiB
C

// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -o %t.cir
// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -o %t-cir.ll
// RUN: FileCheck %s --input-file=%t-cir.ll --check-prefix=LLVM
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o %t.ll
// RUN: FileCheck %s --input-file=%t.ll --check-prefix=OGCG
// CIR: cir.global "private" internal dso_local @staticFuncName.name = #cir.global_view<@".str.4"> : !cir.ptr<!s8i> {alignment = 8 : i64} loc(#loc1)
// CIR: cir.global "private" constant cir_private dso_local @".str" = #cir.zero : !cir.array<!s8i x 1>
// CIR: cir.global external @func = #cir.global_view<@".str"> : !cir.ptr<!s8i>
// CIR: cir.global "private" constant cir_private dso_local @__func__.plainFunction = #cir.const_array<"plainFunction" : !cir.array<!s8i x 13>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__PRETTY_FUNCTION__.plainFunction = #cir.const_array<"void plainFunction(void)" : !cir.array<!s8i x 24>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__func__.externFunction = #cir.const_array<"externFunction" : !cir.array<!s8i x 14>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__PRETTY_FUNCTION__.externFunction = #cir.const_array<"void externFunction(void)" : !cir.array<!s8i x 25>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__func__.privateExternFunction = #cir.const_array<"privateExternFunction" : !cir.array<!s8i x 21>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__PRETTY_FUNCTION__.privateExternFunction = #cir.const_array<"void privateExternFunction(void)" : !cir.array<!s8i x 32>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @".str.4" = #cir.const_array<"staticFuncName" : !cir.array<!s8i x 14>, trailing_zeros> : !cir.array<!s8i x 15>
// CIR: cir.global "private" constant cir_private dso_local @__func__.staticFunction = #cir.const_array<"staticFunction" : !cir.array<!s8i x 14>, trailing_zeros>
// CIR: cir.global "private" constant cir_private dso_local @__PRETTY_FUNCTION__.staticFunction = #cir.const_array<"void staticFunction(void)" : !cir.array<!s8i x 25>, trailing_zeros>
// TODO(cir): These should be unnamed_addr
// LLVM: @staticFuncName.name = internal global ptr @.str.4, align 8
// LLVM: @.str = private constant [1 x i8] zeroinitializer, align 1
// LLVM: @func = global ptr @.str, align 8
// LLVM: @__func__.plainFunction = private constant [14 x i8] c"plainFunction\00"
// LLVM: @__PRETTY_FUNCTION__.plainFunction = private constant [25 x i8] c"void plainFunction(void)\00"
// LLVM: @__func__.externFunction = private constant [15 x i8] c"externFunction\00"
// LLVM: @__PRETTY_FUNCTION__.externFunction = private constant [26 x i8] c"void externFunction(void)\00"
// LLVM: @__func__.privateExternFunction = private constant [22 x i8] c"privateExternFunction\00"
// LLVM: @__PRETTY_FUNCTION__.privateExternFunction = private constant [33 x i8] c"void privateExternFunction(void)\00"
// LLVM: @__func__.staticFunction = private constant [15 x i8] c"staticFunction\00"
// LLVM: @__PRETTY_FUNCTION__.staticFunction = private constant [26 x i8] c"void staticFunction(void)\00"
// OGCG: @.str = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
// OGCG: @func = global ptr @.str, align 8
// OGCG: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00"
// OGCG: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [25 x i8] c"void plainFunction(void)\00"
// OGCG: @__func__.externFunction = private unnamed_addr constant [15 x i8] c"externFunction\00"
// OGCG: @__PRETTY_FUNCTION__.externFunction = private unnamed_addr constant [26 x i8] c"void externFunction(void)\00"
// OGCG: @__func__.privateExternFunction = private unnamed_addr constant [22 x i8] c"privateExternFunction\00"
// OGCG: @__PRETTY_FUNCTION__.privateExternFunction = private unnamed_addr constant [33 x i8] c"void privateExternFunction(void)\00"
// OGCG: @staticFuncName.name = internal global ptr @.str.4, align 8
// OGCG: @__func__.staticFunction = private unnamed_addr constant [15 x i8] c"staticFunction\00"
// OGCG: @__PRETTY_FUNCTION__.staticFunction = private unnamed_addr constant [26 x i8] c"void staticFunction(void)\00"
const char* func = __func__;
int printf(const char *, ...);
void plainFunction(void) {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
}
extern void externFunction(void) {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
}
__private_extern__ void privateExternFunction(void) {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
}
// TODO(cir): Add support for __captured_stmt
static void staticFunction(void) {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
}
void staticFuncName(void) {
static const char *name = __func__;
}
int main(void) {
plainFunction();
externFunction();
privateExternFunction();
staticFunction();
staticFuncName();
return 0;
}