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

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

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

commit r17-3993-ga310db3ba39dbf8bd4db94ee5de7acce5e1cca69
Author: Vladislav Semykin <[email protected]>
Date:   Sat Sep 5 00:19:35 2026 +0300

    c++: fix typeid capture in generic lambdas [PR c++/127132]

    [expr.prim.lambda.capture]/7 (P0588R1 / CWG1468) requires a lambda to
    capture a local entity if the expression would be potentially evaluated
    were the effect of any enclosing typeid expressions ignored.  Capture
    must not depend on whether the typeid operand is itself evaluated.

    The PR125886 two-pass parse gated the capture-triggering evaluated
    re-parse on processing_template_decl == 0.  A generic lambda's own auto
    parameter makes that nonzero regardless of the operand, so capture of
    an outer polymorphic glvalue was skipped and the resulting uncaptured
    decl ICEd at RTL expand (PR127132).

    Do not teach typeid_evaluated_p to treat a template context as
    evaluated: mark_used must still suppress instantiation while the
    operand is genuinely unevaluated (declval<T>()), and
    resolves_to_fixed_type_p already returns "fixed" whenever
    in_template_context.

    Instead, add cp_unevaluated_typeid_cutoff: process_outer_var_ref and
    lambda_expr_this_capture suppress capture only when
    cp_unevaluated_operand exceeds that cutoff.  A typeid probe passes
    typeid_operand=true to cp_unevaluated, which raises the cutoff only
    when operand == cutoff at probe start, so sizeof (typeid (b)) stays
    suppressed while typeid (typeid (x)) looks through every enclosing
    typeid.  Inside the cutoff, capture is attempted as usual, but a
    missing capture-default is not diagnosed there - the real
    evaluated-ness isn't known yet, and a later, non-probe pass will
    diagnose it if the operand turns out evaluated.  Outside a lambda (a
    local class, a default argument) the capture attempt has nothing to
    attach to and falls through unchanged, so params() in pr125886.C still
    sees an unevaluated operand with no extra special-casing.  Every
    force-reset site that clears cp_unevaluated_operand also
    save/reset/restores the cutoff, including cp_evaluated.

    processing_template_decl == 0 turned out to still be the right gate for
    the evaluated re-parse itself: mark_used and build_typeid both already
    no-op unconditionally in any template context, independent of which
    pass hits them, so the two-pass parse needs no extra gate there either.

    gcc/cp/ChangeLog:

            PR c++/127132
            * cp-tree.h (saved_scope): Save unevaluated_typeid_cutoff.
            (cp_unevaluated_typeid_cutoff): Declare.
            (cp_unevaluated): Add a defaulted TYPEID_OPERAND parameter; save
            and restore the cutoff.
            (cp_evaluated): Save, reset, and restore the cutoff.
            * parser.cc (cp_unevaluated_typeid_cutoff): Define.
            (cp_unevaluated::cp_unevaluated, cp_unevaluated::~cp_unevaluated):
            Implement TYPEID_OPERAND cutoff handling.
            (cp_parser_postfix_expression): Pass typeid_operand=true for the
            typeid probe.
            * pt.cc (instantiate_class_template): Save/reset/restore the
            cutoff around NSDMI / lambda capture substitution.
            (tsubst_expr): Pass typeid_operand=true for TYPEID_EXPR's probe.
            * semantics.cc (process_outer_var_ref): Allow lambda capture
            through a typeid probe per [expr.prim.lambda.capture]/7; defer
            the "not captured" diagnostic to a later, non-probe pass.
            * lambda.cc (lambda_expr_this_capture): Same cutoff and deferral
            for 'this'.
            * constraint.cc (tsubst_constraint_variables): Save/reset/restore
            the cutoff with cp_unevaluated_operand.
            * name-lookup.cc (push_to_top_level, pop_from_top_level): Same.
            (local_state_t): Same.

    gcc/testsuite/ChangeLog:

            PR c++/127132
            * g++.dg/rtti/typeid-lambda-capture-pr127132.C: New test,
            consolidating the original PR127132 reproducer with the /7 cases
            previously added to pr125886.C, plus this-capture coverage and
            closure-size checks.

    Signed-off-by: Vladislav Semykin <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Reply via email to