https://gcc.gnu.org/g:5aedc2ee5a58f74825347f0040c35b4a26e72390

commit r16-9088-g5aedc2ee5a58f74825347f0040c35b4a26e72390
Author: Martin Uecker <[email protected]>
Date:   Sat Apr 25 20:14:13 2026 +0200

    c: Fix use of variably-modified structure/union types in nested context 
[PR124985]
    
    If a nested function uses a variably-modified structure or union type
    that depends on the enclosing context, it needs the static chain.
    My recent change missed this, because in this case no decl was used.
    To address this, we now call mark_decl_used also on TYPE_STUB_DECLs.
    
            PR c/124985
    
    gcc/c/ChangeLog:
            * c-decl.cc (pushtag): Update comment.
            (declspecs_add_type): Mark TYPE_STUB_DECL as used.
            * c-typeck.cc (function_to_pointer_conversion): Fix grammar in 
comment.
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/Wreturn-nested-3.c: New test.
            * gcc.dg/pr124985.c: New test.
    
    (cherry picked from commit 67bc28c6c0c68a22280fd0942df598f20e339431)

Diff:
---
 gcc/c/c-decl.cc                         |  8 ++++++-
 gcc/c/c-typeck.cc                       |  2 +-
 gcc/testsuite/gcc.dg/Wreturn-nested-3.c | 42 +++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr124985.c         | 13 ++++++++++
 4 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 8a894de3a1b7..ddcf06bf5d65 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1709,7 +1709,8 @@ pushtag (location_t loc, tree name, tree type)
      NULL-named TYPE_DECL node helps dwarfout.c to know when it needs
      to output a representation of a tagged type, and it also gives
      us a convenient place to record the "scope start" address for the
-     tagged type.  */
+     tagged type, and it is used to track whether the type is used
+     in a non-local context via mark_decl_used.  */
 
   TYPE_STUB_DECL (type) = pushdecl (build_decl (loc,
                                                TYPE_DECL, NULL_TREE, type));
@@ -13134,6 +13135,11 @@ declspecs_add_type (location_t loc, struct c_declspecs 
*specs,
              specs->typedef_p = true;
              specs->locations[cdw_typedef] = loc;
            }
+
+         if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+             || TREE_CODE (type) == ENUMERAL_TYPE)
+           mark_decl_used (TYPE_STUB_DECL (type), false);
+
          if (spec.expr)
            {
              if (specs->expr)
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index aa368a6e95ae..6195d1795432 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -2373,7 +2373,7 @@ function_to_pointer_conversion (location_t loc, tree exp)
 
   tree exp2 = build_unary_op (loc, ADDR_EXPR, exp, false);
 
-  /* If the function is defined and known to not to require a non-local
+  /* If the function is defined and known to not require a non-local
      context, make sure no trampoline is generated.  */
   if (TREE_CODE (exp) == FUNCTION_DECL
       && DECL_INITIAL (exp) && !C_FUNC_NONLOCAL_CONTEXT (exp))
diff --git a/gcc/testsuite/gcc.dg/Wreturn-nested-3.c 
b/gcc/testsuite/gcc.dg/Wreturn-nested-3.c
new file mode 100644
index 000000000000..c31685f28f37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wreturn-nested-3.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target trampolines } */
+/* { dg-options "" } */
+
+
+void *a0() {
+  int b = 1;
+  struct bar { char c[b]; };
+  struct bar e() { struct bar f; return f; }
+  return &e;   /* { dg-warning "referencing local context" } */
+}
+
+void *a1() {
+  int b = 1;
+  struct bar { char c[b]; };
+  struct bar e() { }
+  return &e;
+}
+
+void *a2() {
+  int b = 1;
+  struct bar { char c[b]; };
+  struct bar e() { typeof(struct bar) f; return f; }
+  return &e;   /* { dg-warning "referencing local context" } */
+}
+
+void *a3() {
+  int b = 1;
+  struct bar { char c[b]; };
+  struct bar (*d)();
+  struct bar e() { typeof((*d)()) f; return f; }
+  return &e;   /* { dg-warning "referencing local context" } */
+}
+
+void *a4() {
+  int b = 1;
+  struct bar { char c[b]; };
+  struct bar e() { struct bar f; return f; }
+  return &e;   /* { dg-warning "referencing local context" } */
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/pr124985.c b/gcc/testsuite/gcc.dg/pr124985.c
new file mode 100644
index 000000000000..8ccc282586fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr124985.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target trampolines } */
+/* { dg-options "-O1 -fno-tree-dse" } */
+
+void a() {
+  int b = 0;
+  struct bar { char c[b]; };
+  struct bar (*d)();
+  struct bar e() { struct bar f; return f; }
+  d = e;
+  d();
+}
+

Reply via email to