https://gcc.gnu.org/g:67bc28c6c0c68a22280fd0942df598f20e339431

commit r17-366-g67bc28c6c0c68a22280fd0942df598f20e339431
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.

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 cc07e05e3363..683780ab6543 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)
            {
              tree expr = save_expr (fold_convert (void_type_node, spec.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