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

            Bug ID: 127750
           Summary: [17 Regression] Lambda in polymorphic typeid operand
                    mangled with wrong discriminator (undocumented ABI
                    break vs 16)
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: ABI, wrong-code
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gabravier at gmail dot com
                CC: vladislav.semykin at gmail dot com
  Target Milestone: ---

#include <typeinfo>

struct B { virtual ~B(); };          // polymorphic -> typeid operand is
evaluated -> reparse

inline auto g(B* p) {
  (void)typeid(*[&]{ return p; }()); // lambda inside the probed/reparsed
operand
}

void use(B* p) {
  g(p);
}

Compiling this code with GCC 16.2 (and -O0) emits a function symbol named:

_ZZ1gP1BENKUlvE_clEv (g(B*)::{lambda()#1}::operator()() const)

GCC trunk:

_ZZ1gP1BENKUlvE0_clEv (g(B*)::{lambda()#2}::operator()() const)

The latter seems incorrect, since the Itanium ABI would expect that the first
lambda with the signature "()" (which this is) be UlvE_, AIUI. In particular,
it appears to rather directly be an ABI break (both are currently on ABI
20/__GXX_ABI_VERSION == 1020).

I am not particularly certain but my *guess* is that r17-2200-g621661f7d2e915
is the cause. This in particular looks quite suspect to me:

+           if (expression != error_mark_node
+               && processing_template_decl == 0
+               && !cp_unevaluated_operand
+               && typeid_evaluated_p (expression))
+             {
+               /* Re-parse the operand evaluated so the /4 side-effects occur.
+                  The unevaluated pass above called no mark_used and captured
+                  nothing, so rolling back has nothing to undo.  */
+               cp_lexer_rollback_tokens (parser->lexer);
+               expression = cp_parser_expression (parser, &idk);
+             }

...because I would have to imagine that lambda expression must surely have
rather elaborate parse-time side effects (the closure type, the discriminator,
etc.). This could, perchance, result in every lambda in an evaluated typeid
operand being numbered twice (at least, that is my analysis :))

...although I haven't actually tested that this is the particular commit that
causes the issue, nor am I sufficiently an expert in C++ to be able to say so
definitely.

Reply via email to