https://github.com/cooperp updated 
https://github.com/llvm/llvm-project/pull/173311

>From 9939ff8b369adfdc94c6519ebe17ac905116266c Mon Sep 17 00:00:00 2001
From: Peter Cooper <[email protected]>
Date: Sat, 8 Nov 2025 10:14:14 -0800
Subject: [PATCH] Allow the no_stack_protector attribute on local variables.

This attribute is currently only permitted on functions, but sometimes it can
be useful to opt out a specific local variable.  That way the function can still
get a stack protector if other locals require it, but locals which are opted out
won't have the overhead of a stack protector if not needed.
---
 clang/docs/ReleaseNotes.rst                   |  5 +++
 clang/include/clang/Basic/Attr.td             |  7 ++++
 clang/include/clang/Basic/AttrDocs.td         | 11 ++++++
 clang/lib/CodeGen/CGDecl.cpp                  |  8 ++++
 clang/test/CodeGen/stack-protector-vars.cpp   | 38 +++++++++++++++++++
 ...a-attribute-supported-attributes-list.test |  1 +
 6 files changed, 70 insertions(+)
 create mode 100644 clang/test/CodeGen/stack-protector-vars.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8f7a0a2b304d0..41276403a38eb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -387,6 +387,11 @@ Attribute Changes in Clang
   multilibs for printf features. Requires cooperation with the libc
   implementation.
 
+- Added new attribute ``stack_protector_ignore`` to opt specific local 
variables out of
+  the analysis which determines if a function should get a stack protector.  A 
function
+  will still generate a stack protector if other local variables or command 
line flags
+  require it.
+
 - On targets with Itanium C++ ABI, Clang now supports ``[[gnu:gcc_struct]]``
   with the behavior similar to one existing in GCC. In particular, whenever
   ``-mms-bitfields`` command line option is provided (or if 
Microsoft-compatible
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b017906a8d690..525a883f5987c 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2731,6 +2731,13 @@ def NoStackProtector : InheritableAttr {
   let SimpleHandler = 1;
 }
 
+def StackProtectorIgnore : InheritableAttr {
+  let Spellings = [Clang<"stack_protector_ignore">];
+  let Subjects = SubjectList<[LocalVar]>;
+  let Documentation = [StackProtectorIgnoreDocs];
+  let SimpleHandler = 1;
+}
+
 def StrictGuardStackCheck : InheritableAttr {
   let Spellings = [Declspec<"strict_gs_check">];
   let Subjects = SubjectList<[Function]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 812b48058d189..79b872c6bbe78 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -5736,6 +5736,17 @@ option.
     }];
 }
 
+def StackProtectorIgnoreDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``stack_protector_ignore`` attribute skips analysis of the given local
+variable when determining if a function should use a stack protector.
+
+If ``-fstack-protector-all`` is specified then the given function will still
+use a stack protector, even if some/all variables have this attribute.
+  }];
+}
+
 def StrictGuardStackCheckDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8b1cd83af2396..e398a8ce8598b 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1604,6 +1604,14 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
                                  allocaAlignment, D.getName(),
                                  /*ArraySize=*/nullptr, &AllocaAddr);
 
+      if (D.hasAttr<StackProtectorIgnoreAttr>()) {
+        if (auto *AI = dyn_cast<llvm::AllocaInst>(address.getBasePointer())) {
+          llvm::LLVMContext &Ctx = Builder.getContext();
+          auto *Operand = llvm::ConstantAsMetadata::get(Builder.getInt32(0));
+          AI->setMetadata("stack-protector", llvm::MDNode::get(Ctx, 
{Operand}));
+        }
+      }
+
       // Don't emit lifetime markers for MSVC catch parameters. The lifetime of
       // the catch parameter starts in the catchpad instruction, and we can't
       // insert code in those basic blocks.
diff --git a/clang/test/CodeGen/stack-protector-vars.cpp 
b/clang/test/CodeGen/stack-protector-vars.cpp
new file mode 100644
index 0000000000000..b4a551be79406
--- /dev/null
+++ b/clang/test/CodeGen/stack-protector-vars.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck 
%s
+
+typedef __SIZE_TYPE__ size_t;
+
+int printf(const char * _Format, ...);
+char *strcpy(char *s1, const char *s2);
+
+struct S {
+  S();
+  int a[4];
+};
+
+// CHECK: define {{.*}} @_Z5test1PKc
+// CHECK: %a = alloca [1000 x i8], align {{.*}}, !stack-protector ![[A:.*]]
+void test1(const char *msg) {
+  __attribute__((stack_protector_ignore))
+  char a[1000];
+  strcpy(a, msg);
+  printf("%s\n", a);
+}
+
+// CHECK: define {{.*}} @_Z5test2
+// CHECK-NOT: %b = alloca [1000 x i8], align {{.*}}, !stack-protector
+void test2(const char *msg) {
+  char b[1000];
+  strcpy(b, msg);
+  printf("%s\n", b);
+}
+
+// CHECK: define {{.*}} @_Z5test3v
+// CHECK-NOT: %b = alloca [1000 x i8], align {{.*}}, !stack-protector
+S test3() {
+  __attribute__((stack_protector_ignore))
+  S s;
+  return s;
+}
+
+// CHECK: ![[A]] = !{i32 0}
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test 
b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 3114d2fc9e693..d6d900f3caf84 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -198,6 +198,7 @@
 // CHECK-NEXT: Section (SubjectMatchRule_function, 
SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, 
SubjectMatchRule_objc_property)
 // CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
 // CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, 
SubjectMatchRule_objc_method)
+// CHECK-NEXT: StackProtectorIgnore (SubjectMatchRule_variable_is_local)
 // CHECK-NEXT: StandaloneDebug (SubjectMatchRule_record)
 // CHECK-NEXT: SwiftAsync (SubjectMatchRule_function, 
SubjectMatchRule_objc_method)
 // CHECK-NEXT: SwiftAsyncContext (SubjectMatchRule_variable_is_parameter)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to