https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123536

--- Comment #5 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Marek Polacek <[email protected]>:

https://gcc.gnu.org/g:efb9667e2fb81dc0dd4dab25a84756c040bc3506

commit r17-607-gefb9667e2fb81dc0dd4dab25a84756c040bc3506
Author: Marek Polacek <[email protected]>
Date:   Thu May 14 09:27:17 2026 -0400

    c++: capture of reference to global in template [PR123536]

    Thanks to DR 696 (r253266), this works:

      int g;
      void fn ()
      {
        int &c = g;
        auto l = [] { c++; };
        l();
      }

    because `c` in the lambda body is not an odr-use because we can
    evaluate it to a constant and so there's no capture.  But when
    fn is a template, we reject the code and crash.  This patch fixes
    both.

    Outside a template, the call to maybe_constant_value in mark_use
    evaluates `c` to `(int&) &g` but in a template, it remains `c`.
    Then we emit an error, and crash on the error_mark_node from
    process_outer_var_ref.  One of the reasons is
          else if (TYPE_REF_P (TREE_TYPE (expression)))
            /* FIXME cp_finish_decl doesn't fold reference initializers.  */
            return true;
    in value_dependent_expression_p but even if that changed, we still
    wouldn't get the referent because decl_really_constant_value wouldn't
    give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.

    So I stopped trying to make this work in a template, and instead
    I'm deferring the error in process_outer_var_ref to instantiation
    when it's instantiation-dependent.  The VAR_P check there is not
    to regress the diagnostic in pr57416.C.

    The mark_use hunk is to fix a crash on invalid (lambda-const14.C).

            PR c++/123536

    gcc/cp/ChangeLog:

            * cp-tree.h (process_outer_var_ref): Remove a parameter's name.
            * expr.cc (mark_use): Return if mark_rvalue_use returns
            error_mark_node.
            * semantics.cc (process_outer_var_ref): Return decl when it is
            instantiation-dependent.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp0x/lambda/lambda-const12.C: New test.
            * g++.dg/cpp0x/lambda/lambda-const13.C: New test.
            * g++.dg/cpp0x/lambda/lambda-const14.C: New test.
            * g++.dg/template/local11.C: New test.

    Reviewed-by: Jason Merrill <[email protected]>
    Reviewed-by: Patrick Palka <[email protected]>

Reply via email to