xref: /llvm-project/clang/test/CodeGen/attr-function-return.c (revision 64473f1221fbc16af140407d5ea64d808f5853a7)
12240d72fSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
2d2792e7dSNick Desaulniers // RUN:   -Werror=ignored-attributes \
32240d72fSNick Desaulniers // RUN:   | FileCheck %s --check-prefixes=CHECK,CHECK-NOM
42240d72fSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
5d2792e7dSNick Desaulniers // RUN:   -Werror=ignored-attributes -mfunction-return=keep \
6d2792e7dSNick Desaulniers // RUN:   | FileCheck %s --check-prefixes=CHECK,CHECK-KEEP
72240d72fSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
8d2792e7dSNick Desaulniers // RUN:   -Werror=ignored-attributes -mfunction-return=thunk-extern \
9d2792e7dSNick Desaulniers // RUN:   | FileCheck %s --check-prefixes=CHECK,CHECK-EXTERN
10140bfdcaSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
11*64473f12SFangrui Song // RUN:  -mfunction-return=thunk-extern -coverage-data-file=/dev/null \
12140bfdcaSNick Desaulniers // RUN:   | FileCheck %s --check-prefix=CHECK-GCOV
13140bfdcaSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
14140bfdcaSNick Desaulniers // RUN:  -mfunction-return=thunk-extern -fsanitize=address \
15140bfdcaSNick Desaulniers // RUN:   | FileCheck %s --check-prefix=CHECK-ASAN
16140bfdcaSNick Desaulniers // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \
17140bfdcaSNick Desaulniers // RUN:  -mfunction-return=thunk-extern -fsanitize=thread \
18140bfdcaSNick Desaulniers // RUN:   | FileCheck %s --check-prefix=CHECK-TSAN
192240d72fSNick Desaulniers 
202240d72fSNick Desaulniers #if !__has_attribute(function_return)
212240d72fSNick Desaulniers #error "missing attribute support for function_return"
222240d72fSNick Desaulniers #endif
232240d72fSNick Desaulniers 
242240d72fSNick Desaulniers // CHECK: @keep() [[KEEP:#[0-9]+]]
keep(void)252240d72fSNick Desaulniers __attribute__((function_return("keep"))) void keep(void) {}
262240d72fSNick Desaulniers 
27d2792e7dSNick Desaulniers // CHECK: @keep2() [[KEEP]]
keep2(void)282240d72fSNick Desaulniers [[gnu::function_return("keep")]] void keep2(void) {}
292240d72fSNick Desaulniers 
302240d72fSNick Desaulniers // CHECK: @thunk_extern() [[EXTERN:#[0-9]+]]
thunk_extern(void)312240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void thunk_extern(void) {}
322240d72fSNick Desaulniers 
33d2792e7dSNick Desaulniers // CHECK: @thunk_extern2() [[EXTERN]]
thunk_extern2(void)342240d72fSNick Desaulniers [[gnu::function_return("thunk-extern")]] void thunk_extern2(void) {}
352240d72fSNick Desaulniers 
362240d72fSNick Desaulniers // CHECK: @double_thunk_keep() [[KEEP]]
372240d72fSNick Desaulniers // clang-format off
382240d72fSNick Desaulniers __attribute__((function_return("thunk-extern")))
392240d72fSNick Desaulniers __attribute__((function_return("keep")))
double_thunk_keep(void)402240d72fSNick Desaulniers void double_thunk_keep(void) {}
412240d72fSNick Desaulniers 
422240d72fSNick Desaulniers // CHECK: @double_thunk_keep2() [[KEEP]]
432240d72fSNick Desaulniers [[gnu::function_return("thunk-extern")]][[gnu::function_return("keep")]]
double_thunk_keep2(void)442240d72fSNick Desaulniers void double_thunk_keep2(void) {}
452240d72fSNick Desaulniers 
462240d72fSNick Desaulniers // CHECK: @double_keep_thunk() [[EXTERN]]
472240d72fSNick Desaulniers __attribute__((function_return("keep")))
482240d72fSNick Desaulniers __attribute__((function_return("thunk-extern")))
double_keep_thunk(void)492240d72fSNick Desaulniers void double_keep_thunk(void) {}
502240d72fSNick Desaulniers 
512240d72fSNick Desaulniers // CHECK: @double_keep_thunk2() [[EXTERN]]
52d2792e7dSNick Desaulniers [[gnu::function_return("keep")]][[gnu::function_return("thunk-extern")]]
double_keep_thunk2(void)532240d72fSNick Desaulniers void double_keep_thunk2(void) {}
542240d72fSNick Desaulniers 
552240d72fSNick Desaulniers // CHECK: @thunk_keep() [[KEEP]]
562240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"), function_return("keep")))
thunk_keep(void)572240d72fSNick Desaulniers void thunk_keep(void) {}
582240d72fSNick Desaulniers 
592240d72fSNick Desaulniers // CHECK: @thunk_keep2() [[KEEP]]
602240d72fSNick Desaulniers [[gnu::function_return("thunk-extern"), gnu::function_return("keep")]]
thunk_keep2(void)612240d72fSNick Desaulniers void thunk_keep2(void) {}
622240d72fSNick Desaulniers 
632240d72fSNick Desaulniers // CHECK: @keep_thunk() [[EXTERN]]
642240d72fSNick Desaulniers __attribute__((function_return("keep"), function_return("thunk-extern")))
keep_thunk(void)652240d72fSNick Desaulniers void keep_thunk(void) {}
662240d72fSNick Desaulniers 
672240d72fSNick Desaulniers // CHECK: @keep_thunk2() [[EXTERN]]
682240d72fSNick Desaulniers [[gnu::function_return("keep"), gnu::function_return("thunk-extern")]]
keep_thunk2(void)692240d72fSNick Desaulniers void keep_thunk2(void) {}
702240d72fSNick Desaulniers // clang-format on
712240d72fSNick Desaulniers 
722240d72fSNick Desaulniers void undef(void);
732240d72fSNick Desaulniers // CHECK: @undef() [[KEEP]]
undef(void)742240d72fSNick Desaulniers __attribute__((function_return("keep"))) void undef(void) {}
752240d72fSNick Desaulniers 
762240d72fSNick Desaulniers void undef2(void);
772240d72fSNick Desaulniers // CHECK: @undef2() [[EXTERN]]
undef2(void)782240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void undef2(void) {}
792240d72fSNick Desaulniers 
802240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void change_def(void);
812240d72fSNick Desaulniers // CHECK: @change_def() [[KEEP]]
change_def(void)822240d72fSNick Desaulniers __attribute__((function_return("keep"))) void change_def(void) {}
832240d72fSNick Desaulniers 
842240d72fSNick Desaulniers __attribute__((function_return("keep"))) void change_def2(void);
852240d72fSNick Desaulniers // CHECK: @change_def2() [[EXTERN]]
change_def2(void)862240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void change_def2(void) {}
872240d72fSNick Desaulniers 
882240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void change_def3(void);
892240d72fSNick Desaulniers // CHECK: @change_def3() [[KEEP]]
change_def3(void)902240d72fSNick Desaulniers [[gnu::function_return("keep")]] void change_def3(void) {}
912240d72fSNick Desaulniers 
922240d72fSNick Desaulniers [[gnu::function_return("keep")]] void change_def4(void);
932240d72fSNick Desaulniers // CHECK: @change_def4() [[EXTERN]]
change_def4(void)942240d72fSNick Desaulniers __attribute__((function_return("thunk-extern"))) void change_def4(void) {}
952240d72fSNick Desaulniers 
962240d72fSNick Desaulniers // When there is no -mfunction-return= flag set (NOM) or it's set to keep,
972240d72fSNick Desaulniers // we don't emit anything into the IR for unattributed functions.
982240d72fSNick Desaulniers 
992240d72fSNick Desaulniers // CHECK-NOM:    @no_attrs() [[NOATTR:#[0-9]+]]
1002240d72fSNick Desaulniers // CHECK-KEEP:   @no_attrs() [[NOATTR:#[0-9]+]]
1012240d72fSNick Desaulniers // CHECK-EXTERN: @no_attrs() [[EXTERN]]
no_attrs(void)1022240d72fSNick Desaulniers void no_attrs(void) {}
1032240d72fSNick Desaulniers 
104140bfdcaSNick Desaulniers // Test synthetic functions.
105140bfdcaSNick Desaulniers // CHECK-GCOV: @__llvm_gcov_writeout() unnamed_addr [[EXTERNGCOV:#[0-9]+]]
106140bfdcaSNick Desaulniers // CHECK-GCOV: @__llvm_gcov_reset() unnamed_addr [[EXTERNGCOV]]
107140bfdcaSNick Desaulniers // CHECK-GCOV: @__llvm_gcov_init() unnamed_addr [[EXTERNGCOV]]
108140bfdcaSNick Desaulniers // CHECK-ASAN: @asan.module_ctor() [[EXTERNASAN:#[0-9]+]]
109140bfdcaSNick Desaulniers // CHECK-TSAN: @tsan.module_ctor() [[EXTERNTSAN:#[0-9]+]]
110140bfdcaSNick Desaulniers 
1112240d72fSNick Desaulniers // CHECK-NOM-NOT:  [[NOATTR]] = {{.*}}fn_ret_thunk_extern
1122240d72fSNick Desaulniers // CHECK-KEEP-NOT: [[NOATTR]] = {{.*}}fn_ret_thunk_extern
1132240d72fSNick Desaulniers // CHECK: [[EXTERN]] = {{.*}}fn_ret_thunk_extern
114140bfdcaSNick Desaulniers // CHECK-GCOV: [[EXTERNGCOV]] = {{.*}}fn_ret_thunk_extern
115140bfdcaSNick Desaulniers // CHECK-ASAN: [[EXTERNASAN]] = {{.*}}fn_ret_thunk_extern
116140bfdcaSNick Desaulniers // CHECK-TSAN: [[EXTERNTSAN]] = {{.*}}fn_ret_thunk_extern
117