blob: 3e82ca338a121c628689084fd0b8f93a7276db59 [file] [edit]
// 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 <typename T> 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<int>;
// 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: }