// RUN: %clang_cc1 -emit-llvm -x c %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks -DTEST_ATTR | FileCheck %s --check-prefix=C,C-ATTR // RUN: %clang_cc1 -emit-llvm -x c %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks -mno-outline | FileCheck %s --check-prefix=C,C-ARG // RUN: %clang_cc1 -emit-llvm -x c %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks | FileCheck %s --check-prefix=C,C-NONE // RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks -std=c++23 -DTEST_ATTR | FileCheck %s --check-prefixes=CXX,CXX-ATTR // RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks -std=c++23 -mno-outline | FileCheck %s --check-prefixes=CXX,CXX-ARG // RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks -std=c++23 | FileCheck %s --check-prefixes=CXX,CXX-NONE // This test checks that: // - [[clang::no_outline]] adds the nooutline IR attribute to specific definitions // - `-mno-outline` adds the nooutline IR attribute to all definitions // - Lack of either does not add nooutline IR attribute #ifdef TEST_ATTR #define ATTR [[clang::no_outline]] #define ATTR_DUNDER __attribute__((no_outline)) #else #define ATTR #define ATTR_DUNDER #endif // C-LABEL: define dso_local i32 @toplevel_func( // C-SAME: ) #[[ATTR1:[0-9]+]] { // CXX-LABEL: define dso_local noundef i32 @_Z13toplevel_funci( // CXX-SAME: ) #[[ATTR1:[0-9]+]] { ATTR int toplevel_func(int x) { return x; } // C-LABEL: define dso_local i32 @toplevel_func_noattr( // C-ATTR-SAME: ) #[[ATTR2:[0-9]+]] { // C-ARG-SAME: ) #[[ATTR1]] { // C-NONE-SAME: ) #[[ATTR1]] { // CXX-LABEL: define dso_local noundef i32 @_Z20toplevel_func_noattri( // CXX-ATTR-SAME: ) #[[ATTR2:[0-9]+]] { // CXX-ARG-SAME: ) #[[ATTR1]] { // CXX-NONE-SAME: ) #[[ATTR1]] { int toplevel_func_noattr(int x) { return x; } // C-only: Function without prototype #ifndef __cplusplus #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-non-prototype" #pragma clang diagnostic ignored "-Wimplicit-int" // C-LABEL: define dso_local i32 @no_proto_func( // C-SAME: ) #[[ATTR1]] { ATTR no_proto_func(x) int x; { return x; } #pragma clang diagnostic pop #endif // With Blocks #if __has_feature(blocks) // C-LABEL: define dso_local i32 @func_with_block( // C-ATTR-SAME: ) #[[ATTR2]] { // C-ARG-SAME: ) #[[ATTR1]] { // C-NONE-SAME: ) #[[ATTR1]] { // CXX-LABEL: define dso_local noundef i32 @_Z15func_with_blocki( // CXX-ATTR-SAME: ) #[[ATTR2]] { // CXX-ARG-SAME: ) #[[ATTR1]] { // CXX-NONE-SAME: ) #[[ATTR1]] { int func_with_block(int x) { // C-LABEL: define internal i32 @__func_with_block_block_invoke( // C-SAME: ) #[[ATTR1]] { // CXX-LABEL: define internal noundef i32 @___Z15func_with_blocki_block_invoke( // CXX-ATTR-SAME: ) #[[ATTR3:[0-9]+]] { // CXX-ARG-SAME: ) #[[ATTR2:[0-9]+]] { // CXX-NONE-SAME: ) #[[ATTR2:[0-9]+]] { int (^block)(int) = ^ ATTR_DUNDER int (int y) { return y; }; return block(x); } #endif // C++-only: Member Functions, Lambdas, Templates #ifdef __cplusplus struct my_struct { // CXX-LABEL: define linkonce_odr noundef i32 @_ZN9my_struct11member_funcEi( // CXX-SAME: ) #[[ATTR1]] comdat ATTR int member_func(int x) { return x; } // CXX-LABEL: define linkonce_odr noundef i32 @_ZN9my_struct11static_funcEi( // CXX-SAME: ) #[[ATTR1]] comdat ATTR static int static_func(int x) { return x; } }; template struct templated_struct { ATTR T member_func(T x) { return x; } ATTR static T static_func(T x) { return x; } }; // CXX-LABEL: define weak_odr noundef i32 @_ZN16templated_structIiE11member_funcEi( // CXX-SAME: ) #[[ATTR1]] comdat // CXX-LABEL: define weak_odr noundef i32 @_ZN16templated_structIiE11static_funcEi( // CXX-SAME: ) #[[ATTR1]] comdat template struct templated_struct; // CXX-LABEL: define dso_local noundef i32 @_Z16func_with_lambdai( // CXX-ATTR-SAME: ) #[[ATTR2]] // CXX-ARG-SAME: ) #[[ATTR1]] // CXX-NONE-SAME: ) #[[ATTR1]] int func_with_lambda(int x) { // CXX-LABEL: define internal noundef i32 @"_ZZ16func_with_lambdaiENK3$_0clEv"( // CXX-SAME: ) #[[ATTR1]] auto lambda = [x] ATTR () -> int { return x; }; return lambda(); } #endif // C: attributes #[[ATTR1]] = { // C-ATTR-SAME: nooutline // C-ARG-SAME: nooutline // C-NONE-NOT: nooutline // C-SAME: } // C-ATTR: attributes #[[ATTR2]] = { // C-ATTR-NOT: nooutline // C-ATTR-SAME: } // CXX: attributes #[[ATTR1]] = { // CXX-ATTR-SAME: nooutline // CXX-ARG-SAME: nooutline // CXX-NONE-NOT: nooutline // CXX-SAME: } // CXX: attributes #[[ATTR2]] = { // CXX-ATTR-NOT: nooutline // CXX-ARG-SAME: nooutline // CXX-NONE-NOT: nooutline // CXX-SAME: } // CXX-ATTR: attributes #[[ATTR3]] = { // CXX-ATTR-SAME: nooutline // CXX-ATTR-SAME: }