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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |jsm28 at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
int global = 0;

int
foo (void)
{
  ++global;
  return 1;
}

void
baz (void)
{
  void
  bar (s, c)
    char *s;
    char c[static foo ()];
  {
  }
  bar ("1", "1");
  bar ("1", "1");
  bar ("1", "1");
}

int
main ()
{
  baz ();
  if (global != 3)
    __builtin_abort ();
  return 0;
}

shows that for nested functions those side-effects are emitted, but at a wrong
location.
The side-effects in that case are evaluated when passing through the definition
of bar inside of the baz function,
rather than when bar is called.  So above, foo () is called just once, not 3
times.
If standard C declarations are used:
int global = 0;

int
foo (void)
{
  return ++global;
}

void
bar (char *s, char c[static foo ()])
{
}

int
main ()
{
  bar ("1", "1");
  if (global != 1)
    __builtin_abort ();
  return 0;
}
then it works properly, in that case the pending sizes are recorded by
c_parser_parms_list_declarator -> push_parm_decl -> grokdeclarator and queued
by get_parm_info called from c_parser_parms_list_declarator.
But in case of K&R argument declarations, those are done by:
              while (c_parser_next_token_is_not (parser, CPP_EOF)
                     && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
                c_parser_declaration_or_fndef (parser, false, false, false,
                                               true, false);
in c_parser_declaration_or_fndef and in that case that nested
c_parser_declaration_or_fndef calls start_decl which after
calling grokdeclarator which collects the pending expressions just does:
  if (expr)
    add_stmt (fold_convert (void_type_node, expr));
and so it is unclear where exactly it is pushed for the non-nested functions,
for nested ones at the current statement location (the definition of nested
function).
Bet we need to arrange for those side-effects to be instead remembered
somewhere and queued into pending_sizes later.

Reply via email to