Joseph Myers <josmy...@redhat.com> writes: > Bug 117164 is an ICE on an existing test with -std=gnu23 involving a > nested function returning a variable-size structure (and I think the > last bug needing to be resolved before switching to -std=gnu23 as the > default, as without fixing this would be a clear regression from a > change in default). > > The problem is a GIMPLE verification failure where (after type > remapping from inlining / cloning) the return type of the function no > longer exactly matches the type to which it is assigned (these types > use structural equality, which means GIMPLE verification can't use > TYPE_CANONICAL and expects an exact match). Specifically, the nested > function itself is *not* inlined (the -fno-inline-small-functions in > the original test nested-func-12.c, I think, or the noinline attribute > in some of my variant tests), but the function containing it is either > cloned (the --param ipa-cp-eval-threshold=0 in the original test) or > inlined. (I'm not sure what role -fno-guess-branch-probability plays > in getting the right situation for the ICE; maybe affecting when > inlining or cloning is considered profitable?) > > There is in fact existing code in tree-nested.cc to prevent inlining > of a function containing a nested function with variably modified > *argument* types. I think the same issue of ensuring consistency of > types means such prevention should also apply for a variably modified > return type. Furthermore, exactly the same problem applies for > cloning for other reasons as it does for inlining. Thus, change the > logic to include variably modified return types for nested functions > alongside those for arguments of those functions as a reason not to > inline, and also add the noclone attribute in these cases. > > Bootstrapped with no regressions for x86-64-pc-linux-gnu. > > PR c/117164 > > gcc/ > * tree-nested.cc: Include "attribs.h". > (check_for_nested_with_variably_modified): Also return true for > variably modified return type. > (create_nesting_tree): If check_for_nested_with_variably_modified > returns true, also add noclone attribute. > > gcc/testsuite/ > * gcc.dg/nested-func-13.c, gcc.dg/nested-func-14.c: > gcc.dg/nested-func-15.c, gcc.dg/nested-func-16.c, > gcc.dg/nested-func-17.c: New tests. > > diff --git a/gcc/testsuite/gcc.dg/nested-func-13.c > b/gcc/testsuite/gcc.dg/nested-func-13.c > new file mode 100644 > index 000000000000..697a62354109 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/nested-func-13.c > @@ -0,0 +1,6 @@ > +/* Test nested-func-12.c with -std=gnu17. */ > +/* { dg-do run } */ > +/* { dg-options "-Ofast --param ipa-cp-eval-threshold=0 > -fno-guess-branch-probability -fno-inline-small-functions -std=gnu17" } */ > +/* { dg-require-effective-target alloca } */ > + > +#include "nested-func-12.c" > diff --git a/gcc/testsuite/gcc.dg/nested-func-14.c > b/gcc/testsuite/gcc.dg/nested-func-14.c > new file mode 100644 > index 000000000000..05a77bdb1a5a > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/nested-func-14.c > @@ -0,0 +1,6 @@ > +/* Test nested-func-12.c with -std=gnu23. */ > +/* { dg-do run } */ > +/* { dg-options "-Ofast --param ipa-cp-eval-threshold=0 > -fno-guess-branch-probability -fno-inline-small-functions -std=gnu23" } */ > +/* { dg-require-effective-target alloca } */ > + > +#include "nested-func-12.c" > diff --git a/gcc/testsuite/gcc.dg/nested-func-15.c > b/gcc/testsuite/gcc.dg/nested-func-15.c > new file mode 100644 > index 000000000000..490d69599868 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/nested-func-15.c > @@ -0,0 +1,29 @@ > +/* Bug 117164: ICE with -std=gnu23 inlining function containing call > + to non-inlined nested function returning variable-size struct. */ > +/* { dg-do run } */
nested-func-12 which exposed the problem, as reported in PR117164, has assertions on the value of a. This test doesn't, so its value as a runtime test is questionable as-is. > +/* { dg-options "-O3 --param ipa-cp-eval-threshold=0 > -fno-guess-branch-probability -fno-inline-small-functions -std=gnu23" } */ > +/* { dg-require-effective-target alloca } */ > + > +void > +foo (int n) > +{ > + struct S { int a[n]; }; > + > + struct S > + fn (void) > + { > + struct S s; > + s.a[0] = 42; > + return s; > + } > + > + fn (); > + fn (); > + fn (); > +} > + > +int > +main (void) > +{ > + foo (1); > +} > > [...] thanks, sam