On 1/15/26 9:35 PM, Lucas Chollet wrote:
The patch fixes a bug in the detection of the usage of static variables inside
generic lambdas. It does so by forcing the instantiation of generic lambdas
within their enclosing scope. This ensures that the scope's static variables
usage is computed correctly.

Hmm, we shouldn't need to instantiate in order to know we've named a variable. I notice in finish_id_expression_1 that we have

/* A use in unevaluated operand might not be instantiated appropriately if tsubst_copy builds a dummy parm, or if we never instantiate a generic lambda, so mark it now. */
      if (processing_template_decl && cp_unevaluated_operand)
        mark_type_use (decl);

...where the comment mentions generic lambdas, but the code doesn't handle this case. Maybe add a check for generic_lambda_fn_p (current_function_decl)?

2026-01-15  Lucas Chollet  <[email protected]>

        PR c++/114450
cp/
        * decl2.cc (has_generic_lambda_param_p): New.
        (mark_used): Don't allow deferring template instantiations for
        generic lambdas.

testsuite/
        * g++.dg/warn/Wunused-var-42.C: New.
---
  gcc/cp/decl2.cc                            | 37 +++++++++++++++++++++-
  gcc/testsuite/g++.dg/warn/Wunused-var-42.C | 33 +++++++++++++++++++
  2 files changed, 69 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-var-42.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index c6449844965..bea083797cf 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -6546,6 +6546,37 @@ fn_template_being_defined (tree decl)
    return fn_being_defined (pattern);
  }
+/* True if the function declaration DECL takes a generic lambda as one of its
+    template parameters.  */
+
+static bool
+has_generic_lambda_param_p (tree decl)
+{
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    return false;
+
+  tree tinfo = DECL_TEMPLATE_INFO (decl);
+  if (!tinfo)
+      return false;
+
+  tree args = TI_ARGS (tinfo);
+  for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
+  {
+    tree arg = TREE_VEC_ELT (args, i);
+    if (TREE_CODE (arg) == RECORD_TYPE && LAMBDA_TYPE_P (arg))
+      {
+       tree callop = lambda_function (arg);
+       tree call_type = TREE_TYPE (callop);
+       for (tree parms = TYPE_ARG_TYPES (call_type);
+            parms;
+            parms = TREE_CHAIN (parms))
+       if (uses_template_parms (TREE_VALUE (parms)))
+         return true;
+      }
+  }
+  return false;
+}
+
  /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
     If DECL is a specialization or implicitly declared class member,
     generate the actual definition.  Return false if something goes
@@ -6798,7 +6829,11 @@ mark_used (tree decl, tsubst_flags_t complain /* = 
tf_warning_or_error */)
         need.  Therefore, we always try to defer instantiation.  */
      {
        ++function_depth;
-      instantiate_decl (decl, /*defer_ok=*/true,
+      /* Generic lambdas need to be instantiated right away, when we
+   still know the parent scope.  Otherwise, we won't be able to
+        see the usage of local static variable.  See bug 114450.  */
+      bool defer_ok = !(warn_unused && has_generic_lambda_param_p (decl));
+      instantiate_decl (decl, /*defer_ok=*/defer_ok,
                        /*expl_inst_class_mem_p=*/false);
        --function_depth;
      }
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-42.C 
b/gcc/testsuite/g++.dg/warn/Wunused-var-42.C
new file mode 100644
index 00000000000..f84fb94c334
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-var-42.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c14 } }
+// { dg-options "-Wunused" }
+
+template <typename F>
+void f (F &&d)
+{
+  static unsigned context;
+  d(context);
+}
+
+void g ()
+{
+  static int b;
+  f([](auto c) { return c <= b; });
+}
+
+void h ()
+{
+  static int b = 0; // { dg-warning "unused variable" }
+  f([](auto c) { return c <= 0; });
+}
+
+void i ()
+{
+  static int b = 0; // { dg-warning "set but not used" }
+  [](auto c) { return c <= b; };
+}
+
+void j ()
+{
+  static int b = 0; // { dg-warning "unused variable" }
+  [](auto c) { return c <= 0; };
+}

Reply via email to