[clang] [clang] Add clang::no_outline Attribute (PR #163666)

Sam Elliott via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 10 21:46:38 PST 2026


https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/163666

>From 5e156d45ce83beebab79b96fe33f9d18d60bdd49 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Wed, 15 Oct 2025 17:26:19 -0700
Subject: [PATCH 1/5] [clang] Add clang::nooutline Attribute

This change:
- Adds a `[[clang::nooutline]]` function attribute for C and C++. There
  is no equivalent GNU syntax for this attribute, so no `__attribute__`
  syntax.
- Uses the presence of `[[clang::nooutline]]` to add the `nooutline`
  attribute to IR function definitions.
- Adds test for the above.

The `nooutline` attribute disables both the Machine Outliner (enabled at
Oz for some targets), and the IR Outliner (disabled by default).
---
 clang/include/clang/Basic/Attr.td                |  7 +++++++
 clang/lib/CodeGen/CodeGenModule.cpp              |  3 +++
 clang/test/CodeGen/attr-nooutline.c              | 16 ++++++++++++++++
 ...agma-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-nooutline.c                 |  7 +++++++
 clang/test/Sema/attr-nooutline.cpp               |  7 +++++++
 6 files changed, 41 insertions(+)
 create mode 100644 clang/test/CodeGen/attr-nooutline.c
 create mode 100644 clang/test/Sema/attr-nooutline.c
 create mode 100644 clang/test/Sema/attr-nooutline.cpp

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index ea3f9df6d8342..361ae41da97dc 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2371,6 +2371,13 @@ def NoInline : DeclOrStmtAttr {
   let SimpleHandler = 1;
 }
 
+def NoOutline : DeclOrStmtAttr {
+  let Spellings = [CXX11<"clang", "nooutline">, C23<"clang", "nooutline">];
+  let Subjects = SubjectList<[Function], ErrorDiag>;
+  let Documentation = [Undocumented];
+  let SimpleHandler = 1;
+}
+
 def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
   let Spellings = [GCC<"nomips16">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 65f5468c4b998..6a087be3751f0 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2928,6 +2928,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
       B.addAttribute(llvm::Attribute::MinSize);
   }
 
+  if (D->hasAttr<NoOutlineAttr>())
+    B.addAttribute(llvm::Attribute::NoOutline);
+
   F->addFnAttrs(B);
 
   unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
diff --git a/clang/test/CodeGen/attr-nooutline.c b/clang/test/CodeGen/attr-nooutline.c
new file mode 100644
index 0000000000000..b9f175da24cb5
--- /dev/null
+++ b/clang/test/CodeGen/attr-nooutline.c
@@ -0,0 +1,16 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 6
+// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -disable-O0-optnone -o - | FileCheck %s
+
+
+// CHECK: Function Attrs: noinline nooutline nounwind
+// CHECK-LABEL: define dso_local i32 @t1(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    ret i32 [[TMP0]]
+//
+[[clang::nooutline]] int t1(int x) {
+  return x;
+}
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index d6d900f3caf84..a7c667fa6018d 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -130,6 +130,7 @@
 // CHECK-NEXT: NoMerge (SubjectMatchRule_function, SubjectMatchRule_variable)
 // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
 // CHECK-NEXT: NoMips16 (SubjectMatchRule_function)
+// CHECK-NEXT: NoOutline (SubjectMatchRule_function)
 // CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function)
 // CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record)
 // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
diff --git a/clang/test/Sema/attr-nooutline.c b/clang/test/Sema/attr-nooutline.c
new file mode 100644
index 0000000000000..83848c22d1003
--- /dev/null
+++ b/clang/test/Sema/attr-nooutline.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
+
+[[clang::nooutline]] void t1(void);
+
+[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}
diff --git a/clang/test/Sema/attr-nooutline.cpp b/clang/test/Sema/attr-nooutline.cpp
new file mode 100644
index 0000000000000..b6c9b3995081a
--- /dev/null
+++ b/clang/test/Sema/attr-nooutline.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
+
+[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
+
+[[clang::nooutline]] void t1(void);
+
+[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}

>From c20d4c5d4a489e711f407dafb2e24c44524cf624 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 13:25:32 -0700
Subject: [PATCH 2/5] Address reviewer feedback: Tests, Docs, TableGen

---
 clang/include/clang/Basic/Attr.td     |  4 ++--
 clang/include/clang/Basic/AttrDocs.td | 30 +++++++++++++++++++++++++++
 clang/test/CodeGen/attr-nooutline.c   | 29 +++++++++++++++++---------
 3 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 361ae41da97dc..f2a372503c041 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2372,9 +2372,9 @@ def NoInline : DeclOrStmtAttr {
 }
 
 def NoOutline : DeclOrStmtAttr {
-  let Spellings = [CXX11<"clang", "nooutline">, C23<"clang", "nooutline">];
+  let Spellings = [Clang<"nooutline">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
-  let Documentation = [Undocumented];
+  let Documentation = [NoOutlineDocs];
   let SimpleHandler = 1;
 }
 
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index cad45501df6d2..67fadaff6e4a9 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -862,6 +862,36 @@ with ``__noinline__`` defined as a macro as ``__attribute__((noinline))``.
   }];
 }
 
+def NoOutlineDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+This function attribute suppresses outlining from the annotated function.
+
+Outlining is the process where common parts of separate functions are extracted
+into a separate function (or assembly snippet), and calls to that function or
+snippet are inserted in the original functions. In this way, it can be seen as
+the opposite of inlining. It can help to reduce code size.
+
+.. code-block:: c
+
+  [[clang::nooutline]] int x1(int y) {
+    int z = COMPLEX_MACRO(y); // Not outlined
+    return z + const1;
+  }
+
+  int x2(int y) {
+    int z = COMPLEX_MACRO(y); // May be outlined
+    return z * const2;
+  }
+
+  int x3(int y) {
+    int z = COMPLEX_MACRO(y); // May be outlined
+    reutrn z / const3;
+  }
+
+  }];
+}
+
 def MustTailDocs : Documentation {
   let Category = DocCatStmt;
   let Content = [{
diff --git a/clang/test/CodeGen/attr-nooutline.c b/clang/test/CodeGen/attr-nooutline.c
index b9f175da24cb5..8519414397a8b 100644
--- a/clang/test/CodeGen/attr-nooutline.c
+++ b/clang/test/CodeGen/attr-nooutline.c
@@ -1,15 +1,24 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 6
-// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -disable-O0-optnone -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=CXX
 
-
-// CHECK: Function Attrs: noinline nooutline nounwind
-// CHECK-LABEL: define dso_local i32 @t1(
-// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT:    ret i32 [[TMP0]]
+// C: Function Attrs: noinline nooutline nounwind optnone
+// C-LABEL: define dso_local i32 @t1(
+// C-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// C-NEXT:  [[ENTRY:.*:]]
+// C-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// C-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// C-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// C-NEXT:    ret i32 [[TMP0]]
+//
+// CXX: Function Attrs: mustprogress noinline nooutline nounwind optnone
+// CXX-LABEL: define dso_local noundef i32 @_Z2t1i(
+// CXX-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// CXX-NEXT:  [[ENTRY:.*:]]
+// CXX-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CXX-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CXX-NEXT:    ret i32 [[TMP0]]
 //
 [[clang::nooutline]] int t1(int x) {
   return x;

>From 99d640d64e1f6fcc3f4e45300b440f98562e7ce6 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 13:46:36 -0700
Subject: [PATCH 3/5] Release Notes

---
 clang/docs/ReleaseNotes.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59fdbc80e8bed..91571aee7ad6c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,6 +138,9 @@ Non-comprehensive list of changes in this release
   Usable in constant expressions. Implicit conversion is supported for
   class/struct types with conversion operators.
 
+- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
+  annotated functions. This uses the LLVM `nooutline` attribute.
+
 New Compiler Flags
 ------------------
 - New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added

>From 2aa680e5a1c55a72a26bab979ed0c5f2dd101cbc Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 14:07:51 -0700
Subject: [PATCH 4/5] Address Review Feedback: Flags, Release Notes

---
 clang/docs/ReleaseNotes.rst        | 6 +++---
 clang/test/Sema/attr-nooutline.c   | 2 +-
 clang/test/Sema/attr-nooutline.cpp | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 91571aee7ad6c..3c40407faf9d1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,9 +138,6 @@ Non-comprehensive list of changes in this release
   Usable in constant expressions. Implicit conversion is supported for
   class/struct types with conversion operators.
 
-- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
-  annotated functions. This uses the LLVM `nooutline` attribute.
-
 New Compiler Flags
 ------------------
 - New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
@@ -165,6 +162,9 @@ Attribute Changes in Clang
   will still generate a stack protector if other local variables or command line flags
   require it.
 
+- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
+  annotated functions. This uses the LLVM `nooutline` attribute.
+
 Improvements to Clang's diagnostics
 -----------------------------------
 - Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
diff --git a/clang/test/Sema/attr-nooutline.c b/clang/test/Sema/attr-nooutline.c
index 83848c22d1003..ceb77c5d59bd8 100644
--- a/clang/test/Sema/attr-nooutline.c
+++ b/clang/test/Sema/attr-nooutline.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 -verify -fsyntax-only %s
 
 [[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
 
diff --git a/clang/test/Sema/attr-nooutline.cpp b/clang/test/Sema/attr-nooutline.cpp
index b6c9b3995081a..ceb77c5d59bd8 100644
--- a/clang/test/Sema/attr-nooutline.cpp
+++ b/clang/test/Sema/attr-nooutline.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
+// RUN: %clang_cc1 -verify -fsyntax-only %s
 
 [[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
 

>From 387662961b013feba392b464996b091299458fb1 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Tue, 10 Feb 2026 17:57:41 -0800
Subject: [PATCH 5/5] Change spelling to clang::no_outline, more tests

---
 clang/docs/ReleaseNotes.rst                   |   2 +-
 clang/include/clang/Basic/Attr.td             |   6 +-
 clang/include/clang/Basic/AttrDocs.td         |  18 ---
 clang/test/CodeGen/attr-no-outline.c          | 107 ++++++++++++++++++
 clang/test/CodeGen/attr-nooutline.c           |  25 ----
 clang/test/CodeGenObjC/attr-no-outline.m      |  40 +++++++
 ...a-attribute-supported-attributes-list.test |   2 +-
 clang/test/Sema/attr-no-outline.c             |   7 ++
 clang/test/Sema/attr-no-outline.cpp           |   7 ++
 clang/test/Sema/attr-nooutline.c              |   7 --
 clang/test/Sema/attr-nooutline.cpp            |   7 --
 11 files changed, 166 insertions(+), 62 deletions(-)
 create mode 100644 clang/test/CodeGen/attr-no-outline.c
 delete mode 100644 clang/test/CodeGen/attr-nooutline.c
 create mode 100644 clang/test/CodeGenObjC/attr-no-outline.m
 create mode 100644 clang/test/Sema/attr-no-outline.c
 create mode 100644 clang/test/Sema/attr-no-outline.cpp
 delete mode 100644 clang/test/Sema/attr-nooutline.c
 delete mode 100644 clang/test/Sema/attr-nooutline.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c40407faf9d1..5bc96736e108e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -162,7 +162,7 @@ Attribute Changes in Clang
   will still generate a stack protector if other local variables or command line flags
   require it.
 
-- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
+- Added a new attribute, ``[[clang::no_outline]]`` to suppress outlining from
   annotated functions. This uses the LLVM `nooutline` attribute.
 
 Improvements to Clang's diagnostics
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index f2a372503c041..2621d178d99e8 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2372,10 +2372,10 @@ def NoInline : DeclOrStmtAttr {
 }
 
 def NoOutline : DeclOrStmtAttr {
-  let Spellings = [Clang<"nooutline">];
-  let Subjects = SubjectList<[Function], ErrorDiag>;
+  let Spellings = [Clang<"no_outline">];
+  let Subjects = SubjectList<[Function, ObjCMethod, Block], ErrorDiag>;
   let Documentation = [NoOutlineDocs];
-  let SimpleHandler = 1;
+  let SimpleHandler = true;
 }
 
 def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 67fadaff6e4a9..f91fe2c7b0259 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -871,24 +871,6 @@ Outlining is the process where common parts of separate functions are extracted
 into a separate function (or assembly snippet), and calls to that function or
 snippet are inserted in the original functions. In this way, it can be seen as
 the opposite of inlining. It can help to reduce code size.
-
-.. code-block:: c
-
-  [[clang::nooutline]] int x1(int y) {
-    int z = COMPLEX_MACRO(y); // Not outlined
-    return z + const1;
-  }
-
-  int x2(int y) {
-    int z = COMPLEX_MACRO(y); // May be outlined
-    return z * const2;
-  }
-
-  int x3(int y) {
-    int z = COMPLEX_MACRO(y); // May be outlined
-    reutrn z / const3;
-  }
-
   }];
 }
 
diff --git a/clang/test/CodeGen/attr-no-outline.c b/clang/test/CodeGen/attr-no-outline.c
new file mode 100644
index 0000000000000..60d2ab5563f34
--- /dev/null
+++ b/clang/test/CodeGen/attr-no-outline.c
@@ -0,0 +1,107 @@
+// RUN: %clang_cc1 -emit-llvm -x c %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - -femit-all-decls -fblocks | FileCheck %s --check-prefix=CXX
+// 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,CXX23
+
+// C-LABEL: define dso_local i32 @toplevel_func(
+// C-SAME: ) #[[ATTR0:[0-9]+]] {
+
+// CXX-LABEL: define dso_local noundef i32 @_Z13toplevel_funci(
+// CXX-SAME: ) #[[ATTR0:[0-9]+]] {
+[[clang::no_outline]] int toplevel_func(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: ) #[[ATTR0]] {
+
+[[clang::no_outline]] no_proto_func(x)
+int x; {
+  return x;
+}
+
+#pragma clang diagnostic pop
+#endif
+
+// With Blocks
+#if __has_feature(blocks)
+
+int func_with_block(int x) {
+// C-LABEL: define internal i32 @__func_with_block_block_invoke(
+// C-SAME: ) #[[ATTR0]] {
+
+// CXX-LABEL: define internal noundef i32 @___Z15func_with_blocki_block_invoke(
+// CXX-SAME: ) #[[ATTR1:[0-9]+]] {
+
+  int (^block)(int) = ^ __attribute__((no_outline)) 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: ) #[[ATTR0]] comdat
+  [[clang::no_outline]] int member_func(int x) {
+    return x;
+  }
+
+// CXX-LABEL: define linkonce_odr noundef i32 @_ZN9my_struct11static_funcEi(
+// CXX-SAME: ) #[[ATTR0]] comdat
+  [[clang::no_outline]] static int static_func(int x) {
+    return x;
+  }
+};
+
+template <typename T> struct templated_struct {
+  [[clang::no_outline]] T member_func(T x) {
+    return x;
+  }
+
+  [[clang::no_outline]] static T static_func(T x) {
+    return x;
+  }
+};
+
+// CXX-LABEL: define weak_odr noundef i32 @_ZN16templated_structIiE11member_funcEi(
+// CXX-SAME: ) #[[ATTR0]] comdat
+// CXX-LABEL: define weak_odr noundef i32 @_ZN16templated_structIiE11static_funcEi(
+// CXX-SAME: ) #[[ATTR0]] comdat
+template struct templated_struct<int>;
+
+
+#if __cplusplus >= 202302L
+int func_with_lambda(int x) {
+  // CXX23-LABEL: define internal noundef i32 @"_ZZ16func_with_lambdaiENK3$_0clEv"(
+  // CXX23-SAME: ) #[[ATTR0]]
+  auto lambda = [x][[clang::no_outline]]() -> int {
+    return x;
+  };
+
+  return lambda();
+}
+#endif
+#endif
+
+
+// C: attributes #[[ATTR0]] = {
+// C-SAME: nooutline
+// C-SAME: }
+
+// CXX: attributes #[[ATTR0]] = {
+// CXX-SAME: nooutline
+// CXX-SAME: }
+
+// CXX: attributes #[[ATTR1]] = {
+// CXX-SAME: nooutline
+// CXX-SAME: }
diff --git a/clang/test/CodeGen/attr-nooutline.c b/clang/test/CodeGen/attr-nooutline.c
deleted file mode 100644
index 8519414397a8b..0000000000000
--- a/clang/test/CodeGen/attr-nooutline.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 6
-// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=C
-// RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=CXX
-
-// C: Function Attrs: noinline nooutline nounwind optnone
-// C-LABEL: define dso_local i32 @t1(
-// C-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-// C-NEXT:  [[ENTRY:.*:]]
-// C-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
-// C-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
-// C-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// C-NEXT:    ret i32 [[TMP0]]
-//
-// CXX: Function Attrs: mustprogress noinline nooutline nounwind optnone
-// CXX-LABEL: define dso_local noundef i32 @_Z2t1i(
-// CXX-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-// CXX-NEXT:  [[ENTRY:.*:]]
-// CXX-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
-// CXX-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
-// CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CXX-NEXT:    ret i32 [[TMP0]]
-//
-[[clang::nooutline]] int t1(int x) {
-  return x;
-}
diff --git a/clang/test/CodeGenObjC/attr-no-outline.m b/clang/test/CodeGenObjC/attr-no-outline.m
new file mode 100644
index 0000000000000..f2f5e790386f1
--- /dev/null
+++ b/clang/test/CodeGenObjC/attr-no-outline.m
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s --check-prefix=OBJC
+// RUN: %clang_cc1 -emit-llvm -x objective-c++ %s -o - | FileCheck %s --check-prefix=OBJCXX
+
+ at interface Test
+- (int)method:(int)x;
++ (int)static_method:(int)x;
+ at end
+
+ at implementation Test
+
+// OBJC-LABEL: define internal i32 @"\01-[Test method:]"(
+// OBJC: ) #[[ATTR0:[0-9]+]] {
+
+// OBJCXX-LABEL: define internal noundef i32 @"\01-[Test method:]"(
+// OBJCXX: ) #[[ATTR0:[0-9]+]] {
+- (int)method:(int)x [[clang::no_outline]] {
+  return x;
+}
+
+// OBJC-LABEL: define internal i32 @"\01+[Test static_method:]"(
+// OBJC: ) #[[ATTR0]] {
+
+// OBJCXX-LABEL: define internal noundef i32 @"\01+[Test static_method:]"(
+// OBJCXX: ) #[[ATTR0]] {
++ (int)static_method:(int)x [[clang::no_outline]] {
+  return x;
+}
+
+ at end
+
+// OBJC: attributes #[[ATTR0]] = {
+// OBJC-SAME: nooutline
+// OBJC-SAME: }
+
+// OBJCXX: attributes #[[ATTR0]] = {
+// OBJCXX-SAME: nooutline
+// OBJCXX-SAME: }
+
+
+
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index a7c667fa6018d..626a0743238d5 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -130,7 +130,7 @@
 // CHECK-NEXT: NoMerge (SubjectMatchRule_function, SubjectMatchRule_variable)
 // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
 // CHECK-NEXT: NoMips16 (SubjectMatchRule_function)
-// CHECK-NEXT: NoOutline (SubjectMatchRule_function)
+// CHECK-NEXT: NoOutline (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
 // CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function)
 // CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record)
 // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
diff --git a/clang/test/Sema/attr-no-outline.c b/clang/test/Sema/attr-no-outline.c
new file mode 100644
index 0000000000000..d6ddc2a1349d0
--- /dev/null
+++ b/clang/test/Sema/attr-no-outline.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+[[clang::no_outline]] int a; // expected-error {{'clang::no_outline' attribute only applies to functions}}
+
+[[clang::no_outline]] void t1(void);
+
+[[clang::no_outline(2)]] void t2(void); // expected-error {{'clang::no_outline' attribute takes no arguments}}
diff --git a/clang/test/Sema/attr-no-outline.cpp b/clang/test/Sema/attr-no-outline.cpp
new file mode 100644
index 0000000000000..d6ddc2a1349d0
--- /dev/null
+++ b/clang/test/Sema/attr-no-outline.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+[[clang::no_outline]] int a; // expected-error {{'clang::no_outline' attribute only applies to functions}}
+
+[[clang::no_outline]] void t1(void);
+
+[[clang::no_outline(2)]] void t2(void); // expected-error {{'clang::no_outline' attribute takes no arguments}}
diff --git a/clang/test/Sema/attr-nooutline.c b/clang/test/Sema/attr-nooutline.c
deleted file mode 100644
index ceb77c5d59bd8..0000000000000
--- a/clang/test/Sema/attr-nooutline.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -verify -fsyntax-only %s
-
-[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
-
-[[clang::nooutline]] void t1(void);
-
-[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}
diff --git a/clang/test/Sema/attr-nooutline.cpp b/clang/test/Sema/attr-nooutline.cpp
deleted file mode 100644
index ceb77c5d59bd8..0000000000000
--- a/clang/test/Sema/attr-nooutline.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -verify -fsyntax-only %s
-
-[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
-
-[[clang::nooutline]] void t1(void);
-
-[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}



More information about the cfe-commits mailing list