On Wed, 27 Apr 2016, Eric Botcazou wrote:
> > Gimplification is done in-place and thus relies on all processed
> > trees being unshared. This is achieved by unshare_body which
> > in the end uses walk_tree to get at all interesting trees that possibly
> > need unsharing.
> >
> > Unfortunately it doesn't really work because walk_tree only walks
> > types and type-related fields (TYPE_SIZE, TYPE_MIN_VALUE, etc.) in
> > very narrow circumstances.
>
> Right, but well defined and explained:
>
> case DECL_EXPR:
> /* If this is a TYPE_DECL, walk into the fields of the type that it's
> defining. We only want to walk into these fields of a type in this
> case and not in the general case of a mere reference to the type.
>
> The criterion is as follows: if the field can be an expression, it
> must be walked only here. This should be in keeping with the fields
> that are directly gimplified in gimplify_type_sizes in order for the
> mark/copy-if-shared/unmark machinery of the gimplifier to work with
> variable-sized types.
>
> Note that DECLs get walked as part of processing the BIND_EXPR. */
>
> > Thus the following patch which makes the gimplifier unsharing
> > visit all types.
>
> I think this will generate a lot of useless walking in Ada...
>
> > So - any opinion on the "correct" way to fix this?
>
> Add DECL_EXPRs for the types, that's what done in Ada.
Aww, I was hoping for sth that would not require me to fix all
frontends ...
It seems the C frontend does it correctly already - I hit the
ubsan issue for c-c++-common/ubsan/pr59667.c and only for the C++ FE
for example. Notice how only the pointed-to type is variable-size
here.
C produces
{
unsigned int len = 1;
typedef float <anon>[0:(sizetype) ((long int) SAVE_EXPR <len> +
-1)][0:(sizetype) ((long int) SAVE_EXPR <len> + -1)];
float[0:(sizetype) ((long int) SAVE_EXPR <len> + -1)][0:(sizetype)
((long int) SAVE_EXPR <len> + -1)] * P = 0B;
unsigned int len = 1;
typedef float <anon>[0:(sizetype) ((long int) SAVE_EXPR <len> +
-1)][0:(sizetype) ((long int) SAVE_EXPR <len> + -1)];
SAVE_EXPR <len>;, (void) SAVE_EXPR <len>;;
float[0:(sizetype) ((long int) SAVE_EXPR <len> + -1)][0:(sizetype)
((long int) SAVE_EXPR <len> + -1)] * P = 0B;
(*P)[0][0] = 1.0e+0;
return 0;
}
the decl-expr is the 'typedef' line. The C++ FE produces
{
unsigned int len = 1;
float[0:(sizetype) (SAVE_EXPR <(ssizetype) len + -1>)][0:(sizetype)
(SAVE_EXPR <(ssizetype) len + -1>)] * P = 0B;
<<cleanup_point unsigned int len = 1;>>;
<<cleanup_point <<< Unknown tree: expr_stmt
(void) (((bitsizetype) ((sizetype) (SAVE_EXPR <(ssizetype) len + -1>) +
1) * (bitsizetype) ((sizetype) (SAVE_EXPR <(ssizetype) len + -1>) + 1)) *
32) >>>>>;
<<cleanup_point float[0:(sizetype) (SAVE_EXPR <(ssizetype) len +
-1>)][0:(sizetype) (SAVE_EXPR <(ssizetype) len + -1>)] * P = 0B;>>;
<<cleanup_point <<< Unknown tree: expr_stmt
(void) ((*P)[0][0] = 1.0e+0) >>>>>;
return <retval> = 0;
}
notice the lack of a decl-expr here. It has some weird expr_stmt
here covering the sizes though. Possibly because VLA arrays are a GNU
extension.
Didn't look into the fortran FE issue but I expect it's similar
(it only occurs for pointers to VLAs as well).
I'll try to come up with patches.
Thanks for the hint,
Richard.