From: Richard Biener <rguenther@suse.de>
To: Jakub Jelinek <jakub@redhat.com>
Cc: Martin Sebor <msebor@gmail.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c-family, v2: Improve MEM_REF printing for diagnostics [PR98597]
Date: Fri, 15 Jan 2021 11:43:23 +0100 (CET) [thread overview]
Message-ID: <nycvar.YFH.7.76.2101151143120.17979@zhemvz.fhfr.qr> (raw)
In-Reply-To: <20210114182636.GZ1034503@tucnak>
On Thu, 14 Jan 2021, Jakub Jelinek wrote:
> On Thu, Jan 14, 2021 at 10:49:42AM -0700, Martin Sebor wrote:
> > > In the light of Martins patch this is probably reasonable but still
> > > the general direction is wrong (which is why I didn't approve Martins
> > > original patch). I'm also somewhat disappointed we're breaking this
> > > so late in the cycle.
> >
> > So am I. I didn't test this change as exhaustively as I could and
> > (in light of the poor test coverage) should have. That's my bad.
> > FWIW, I did do it for the first patch (by instrumenting GCC and
> > formatting every MEM_REF it came across), but it didn't occur to
> > me to do it this time around. I have now completed this testing
> > (it found one more ICE elsewhere that I'll fix soon).
>
> Ok, here is an updated patch which fixes what I found, and implements what
> has been discussed on the mailing list and on IRC, i.e. if the types
> are compatible as well as alias sets are same, then it prints
> what c_fold_indirect_ref_for_warn managed to create, otherwise it uses
> that info for printing offsets using offsetof (except when it starts
> with ARRAY_REFs, because one can't have offsetof (struct T[2][2], [1][0].x.y)
>
> The uninit-38.c test (which was the only one I believe which had tests on the
> exact spelling of MEM_REF printing) contains mainly changes to have space
> before * for pointer types (as that is how the C pretty-printers normally
> print types, int * rather than int*), plus what might be considered a
> regression from what Martin printed, but it is actually a correctness fix.
>
> When the arg is a pointer with type pointer to VLA with char element type
> (let's say the pointer is p), which is what happens in several of the
> uninit-38.c tests, omitting the (char *) cast is incorrect, as p + 1
> is not the 1 byte after p, but pointer to the end of the VLA.
> It only happened to work because of the hacks (which I don't like at all
> and are dangerous, DECL_ARTIFICIAL var names with dot inside can be pretty
> much anything, e.g. a lot of passes construct their helper vars from some
> prefix that designates intended use of the var plus numeric suffix), where
> the a.1 pointer to VLA is printed as a which if one is lucky happens to be
> a variable with VLA type (rather than pointer to it), and for such vars
> a + 1 is indeed &a[0] + 1 rather than &a + 1. But if we want to do this
> reliably, we'd need to make sure it comes from VLA (e.g. verify that the
> SSA_NAME is defined to __builtin_alloca_with_align and that there exists
> a corresponding VAR_DECL with DECL_VALUE_EXPR that has the a.1 variable
> in it).
>
> Is this ok for trunk if it passes bootstrap/regtest?
OK.
Thanks,
Richard.
> 2021-01-14 Jakub Jelinek <jakub@redhat.com>
>
> PR tree-optimization/98597
> * c-pretty-print.c (c_fold_indirect_ref_for_warn): New function.
> (print_mem_ref): Use it. If it returns something that has compatible
> type and is TBAA compatible with zero offset, print it and return,
> otherwise print it using offsetof syntax or array ref syntax. Fix up
> printing if MEM_REFs first operand is ADDR_EXPR, or when the first
> argument has pointer to array type. Print pointers using the standard
> formatting.
>
> * gcc.dg/uninit-38.c: Expect a space in between type name and asterisk.
> Expect for now a (char *) cast for VLAs.
> * gcc.dg/uninit-40.c: New test.
>
> --- gcc/c-family/c-pretty-print.c.jj 2021-01-13 15:27:09.822834600 +0100
> +++ gcc/c-family/c-pretty-print.c 2021-01-14 19:02:21.299138891 +0100
> @@ -1809,6 +1809,113 @@ pp_c_call_argument_list (c_pretty_printe
> pp_c_right_paren (pp);
> }
>
> +/* Try to fold *(type *)&op into op.fld.fld2[1] if possible.
> + Only used for printing expressions. Should punt if ambiguous
> + (e.g. in unions). */
> +
> +static tree
> +c_fold_indirect_ref_for_warn (location_t loc, tree type, tree op,
> + offset_int &off)
> +{
> + tree optype = TREE_TYPE (op);
> + if (off == 0)
> + {
> + if (lang_hooks.types_compatible_p (optype, type))
> + return op;
> + /* *(foo *)&complexfoo => __real__ complexfoo */
> + else if (TREE_CODE (optype) == COMPLEX_TYPE
> + && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
> + return build1_loc (loc, REALPART_EXPR, type, op);
> + }
> + /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
> + else if (TREE_CODE (optype) == COMPLEX_TYPE
> + && lang_hooks.types_compatible_p (type, TREE_TYPE (optype))
> + && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
> + {
> + off = 0;
> + return build1_loc (loc, IMAGPART_EXPR, type, op);
> + }
> + /* ((foo *)&fooarray)[x] => fooarray[x] */
> + if (TREE_CODE (optype) == ARRAY_TYPE
> + && TYPE_SIZE_UNIT (TREE_TYPE (optype))
> + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (optype))) == INTEGER_CST
> + && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
> + {
> + tree type_domain = TYPE_DOMAIN (optype);
> + tree min_val = size_zero_node;
> + if (type_domain && TYPE_MIN_VALUE (type_domain))
> + min_val = TYPE_MIN_VALUE (type_domain);
> + offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (optype)));
> + offset_int idx = off / el_sz;
> + offset_int rem = off % el_sz;
> + if (TREE_CODE (min_val) == INTEGER_CST)
> + {
> + tree index
> + = wide_int_to_tree (sizetype, idx + wi::to_offset (min_val));
> + op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
> + NULL_TREE, NULL_TREE);
> + off = rem;
> + if (tree ret = c_fold_indirect_ref_for_warn (loc, type, op, off))
> + return ret;
> + return op;
> + }
> + }
> + /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
> + else if (TREE_CODE (optype) == RECORD_TYPE)
> + {
> + for (tree field = TYPE_FIELDS (optype);
> + field; field = DECL_CHAIN (field))
> + if (TREE_CODE (field) == FIELD_DECL
> + && TREE_TYPE (field) != error_mark_node
> + && TYPE_SIZE_UNIT (TREE_TYPE (field))
> + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (field))) == INTEGER_CST)
> + {
> + tree pos = byte_position (field);
> + if (TREE_CODE (pos) != INTEGER_CST)
> + continue;
> + offset_int upos = wi::to_offset (pos);
> + offset_int el_sz
> + = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (field)));
> + if (upos <= off && off < upos + el_sz)
> + {
> + tree cop = build3_loc (loc, COMPONENT_REF, TREE_TYPE (field),
> + op, field, NULL_TREE);
> + off = off - upos;
> + if (tree ret = c_fold_indirect_ref_for_warn (loc, type, cop,
> + off))
> + return ret;
> + return cop;
> + }
> + }
> + }
> + /* Similarly for unions, but in this case try to be very conservative,
> + only match if some field has type compatible with type and it is the
> + only such field. */
> + else if (TREE_CODE (optype) == UNION_TYPE)
> + {
> + tree fld = NULL_TREE;
> + for (tree field = TYPE_FIELDS (optype);
> + field; field = DECL_CHAIN (field))
> + if (TREE_CODE (field) == FIELD_DECL
> + && TREE_TYPE (field) != error_mark_node
> + && lang_hooks.types_compatible_p (TREE_TYPE (field), type))
> + {
> + if (fld)
> + return NULL_TREE;
> + else
> + fld = field;
> + }
> + if (fld)
> + {
> + off = 0;
> + return build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), op, fld,
> + NULL_TREE);
> + }
> + }
> +
> + return NULL_TREE;
> +}
> +
> /* Print the MEM_REF expression REF, including its type and offset.
> Apply casts as necessary if the type of the access is different
> from the type of the accessed object. Produce compact output
> @@ -1833,59 +1940,79 @@ print_mem_ref (c_pretty_printer *pp, tre
> offset_int elt_idx = 0;
> /* True to include a cast to char* (for a nonzero final BYTE_OFF). */
> bool char_cast = false;
> - const bool addr = TREE_CODE (arg) == ADDR_EXPR;
> - if (addr)
> + tree op = NULL_TREE;
> + bool array_ref_only = false;
> + if (TREE_CODE (arg) == ADDR_EXPR)
> {
> - arg = TREE_OPERAND (arg, 0);
> - if (byte_off == 0)
> + op = c_fold_indirect_ref_for_warn (EXPR_LOCATION (e), TREE_TYPE (e),
> + TREE_OPERAND (arg, 0), byte_off);
> + /* Try to fold it back to component, array ref or their combination,
> + but print it only if the types and TBAA types are compatible. */
> + if (op
> + && byte_off == 0
> + && lang_hooks.types_compatible_p (TREE_TYPE (e), TREE_TYPE (op))
> + && get_deref_alias_set (TREE_OPERAND (e, 1)) == get_alias_set (op))
> {
> - pp->expression (arg);
> + pp->expression (op);
> return;
> }
> + if (op == NULL_TREE)
> + op = TREE_OPERAND (arg, 0);
> + /* If the types or TBAA types are incompatible, undo the
> + UNION_TYPE handling from c_fold_indirect_ref_for_warn, and similarly
> + undo __real__/__imag__ the code below doesn't try to handle. */
> + if (op != TREE_OPERAND (arg, 0)
> + && ((TREE_CODE (op) == COMPONENT_REF
> + && TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == UNION_TYPE)
> + || TREE_CODE (op) == REALPART_EXPR
> + || TREE_CODE (op) == IMAGPART_EXPR))
> + op = TREE_OPERAND (op, 0);
> + if (op != TREE_OPERAND (arg, 0))
> + {
> + array_ref_only = true;
> + for (tree ref = op; ref != TREE_OPERAND (arg, 0);
> + ref = TREE_OPERAND (ref, 0))
> + if (TREE_CODE (ref) != ARRAY_REF)
> + {
> + array_ref_only = false;
> + break;
> + }
> + }
> }
>
> tree access_type = TREE_TYPE (e);
> - if (TREE_CODE (access_type) == ARRAY_TYPE)
> - access_type = TREE_TYPE (access_type);
> - tree arg_type = TREE_TYPE (arg);
> - if (POINTER_TYPE_P (arg_type))
> - arg_type = TREE_TYPE (arg_type);
> - if (TREE_CODE (arg_type) == ARRAY_TYPE)
> - arg_type = TREE_TYPE (arg_type);
> + tree arg_type = TREE_TYPE (TREE_TYPE (arg));
> if (tree access_size = TYPE_SIZE_UNIT (access_type))
> - if (TREE_CODE (access_size) == INTEGER_CST)
> + if (byte_off != 0
> + && TREE_CODE (access_size) == INTEGER_CST
> + && !integer_zerop (access_size))
> {
> - /* For naturally aligned accesses print the nonzero offset
> - in units of the accessed type, in the form of an index.
> - For unaligned accesses also print the residual byte offset. */
> offset_int asize = wi::to_offset (access_size);
> - offset_int szlg2 = wi::floor_log2 (asize);
> -
> - elt_idx = byte_off >> szlg2;
> - byte_off = byte_off - (elt_idx << szlg2);
> + elt_idx = byte_off / asize;
> + byte_off = byte_off % asize;
> }
>
> /* True to include a cast to the accessed type. */
> - const bool access_cast = VOID_TYPE_P (arg_type)
> - || TYPE_MAIN_VARIANT (access_type) != TYPE_MAIN_VARIANT (arg_type);
> + const bool access_cast
> + = ((op && op != TREE_OPERAND (arg, 0))
> + || VOID_TYPE_P (arg_type)
> + || !lang_hooks.types_compatible_p (access_type, arg_type));
> + const bool has_off = byte_off != 0 || (op && op != TREE_OPERAND (arg, 0));
>
> - if (byte_off != 0)
> + if (has_off && (byte_off != 0 || !array_ref_only))
> {
> /* When printing the byte offset for a pointer to a type of
> a different size than char, include a cast to char* first,
> before printing the cast to a pointer to the accessed type. */
> - offset_int arg_size = 0;
> - if (tree size = TYPE_SIZE (arg_type))
> - arg_size = wi::to_offset (size);
> - if (arg_size != BITS_PER_UNIT)
> + tree size = TYPE_SIZE (arg_type);
> + if (size == NULL_TREE
> + || TREE_CODE (size) != INTEGER_CST
> + || wi::to_wide (size) != BITS_PER_UNIT)
> char_cast = true;
> }
>
> if (elt_idx == 0)
> - {
> - if (!addr)
> - pp_c_star (pp);
> - }
> + pp_c_star (pp);
> else if (access_cast || char_cast)
> pp_c_left_paren (pp);
>
> @@ -1895,25 +2022,63 @@ print_mem_ref (c_pretty_printer *pp, tre
> with the type of the referenced object (or if the object
> is typeless). */
> pp_c_left_paren (pp);
> - pp->type_id (access_type);
> - pp_c_star (pp);
> + pp->type_id (build_pointer_type (access_type));
> pp_c_right_paren (pp);
> }
>
> - if (byte_off != 0)
> + if (has_off)
> pp_c_left_paren (pp);
>
> if (char_cast)
> {
> - /* Include a cast to char*. */
> + /* Include a cast to char *. */
> pp_c_left_paren (pp);
> - pp->type_id (char_type_node);
> - pp_c_star (pp);
> + pp->type_id (string_type_node);
> pp_c_right_paren (pp);
> }
>
> pp->unary_expression (arg);
>
> + if (op && op != TREE_OPERAND (arg, 0))
> + {
> + auto_vec<tree, 16> refs;
> + tree ref;
> + unsigned i;
> + bool array_refs = true;
> + for (ref = op; ref != TREE_OPERAND (arg, 0); ref = TREE_OPERAND (ref, 0))
> + refs.safe_push (ref);
> + FOR_EACH_VEC_ELT_REVERSE (refs, i, ref)
> + if (array_refs && TREE_CODE (ref) == ARRAY_REF)
> + {
> + pp_c_left_bracket (pp);
> + pp->expression (TREE_OPERAND (ref, 1));
> + pp_c_right_bracket (pp);
> + }
> + else
> + {
> + if (array_refs)
> + {
> + array_refs = false;
> + pp_string (pp, " + offsetof");
> + pp_c_left_paren (pp);
> + pp->type_id (TREE_TYPE (TREE_OPERAND (ref, 0)));
> + pp_comma (pp);
> + }
> + else if (TREE_CODE (ref) == COMPONENT_REF)
> + pp_c_dot (pp);
> + if (TREE_CODE (ref) == COMPONENT_REF)
> + pp->expression (TREE_OPERAND (ref, 1));
> + else
> + {
> + pp_c_left_bracket (pp);
> + pp->expression (TREE_OPERAND (ref, 1));
> + pp_c_right_bracket (pp);
> + }
> + }
> + if (!array_refs)
> + pp_c_right_paren (pp);
> + }
> +
> if (byte_off != 0)
> {
> pp_space (pp);
> @@ -1921,25 +2086,20 @@ print_mem_ref (c_pretty_printer *pp, tre
> pp_space (pp);
> tree off = wide_int_to_tree (ssizetype, byte_off);
> pp->constant (off);
> - pp_c_right_paren (pp);
> }
> +
> + if (has_off)
> + pp_c_right_paren (pp);
> +
> if (elt_idx != 0)
> {
> if (access_cast || char_cast)
> pp_c_right_paren (pp);
>
> - if (addr)
> - {
> - pp_space (pp);
> - pp_plus (pp);
> - pp_space (pp);
> - }
> - else
> - pp_c_left_bracket (pp);
> + pp_c_left_bracket (pp);
> tree idx = wide_int_to_tree (ssizetype, elt_idx);
> pp->constant (idx);
> - if (!addr)
> - pp_c_right_bracket (pp);
> + pp_c_right_bracket (pp);
> }
> }
>
> --- gcc/testsuite/gcc.dg/uninit-38.c.jj 2021-01-07 09:34:09.725641679 +0100
> +++ gcc/testsuite/gcc.dg/uninit-38.c 2021-01-14 17:43:33.442029629 +0100
> @@ -29,28 +29,28 @@ void sink (void*, ...);
> } \
> typedef void dummy_type
>
> -T (int, 0, 0); // { dg-warning "'\\*\\(int\\*\\)p' is used uninitialized" }
> -T (int, 0, 1); // { dg-warning "'\\*\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)'" }
> -T (int, 0, 2); // { dg-warning "'\\*\\(int\\*\\)\\(\\(char\\*\\)p \\+ 2\\)'" }
> -T (int, 0, 3); // { dg-warning "'\\*\\(int\\*\\)\\(\\(char\\*\\)p \\+ 3\\)'" }
> -T (int, 0, 4); // { dg-warning "'\\(\\(int\\*\\)p\\)\\\[1]'" }
> -T (int, 0, 5); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)\\)\\\[1]'" }
> -T (int, 0, 6); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 2\\)\\)\\\[1]'" }
> -T (int, 0, 7); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 3\\)\\)\\\[1]'" }
> -T (int, 0, 8); // { dg-warning "'\\(\\(int\\*\\)p\\)\\\[2]'" }
> -T (int, 0, 9); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)\\)\\\[2]'" }
> -
> -
> -T (int, 1, 0); // { dg-warning "'\\(\\(int\\*\\)p\\)\\\[1]' is used uninitialized" }
> -T (int, 1, 1); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)\\)\\\[1]'" }
> -T (int, 1, 2); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 2\\)\\)\\\[1]'" }
> -T (int, 1, 3); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 3\\)\\)\\\[1]'" }
> -T (int, 1, 4); // { dg-warning "'\\(\\(int\\*\\)p\\)\\\[2]'" }
> -T (int, 1, 5); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)\\)\\\[2]'" }
> -T (int, 1, 6); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 2\\)\\)\\\[2]'" }
> -T (int, 1, 7); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 3\\)\\)\\\[2]'" }
> -T (int, 1, 8); // { dg-warning "'\\(\\(int\\*\\)p\\)\\\[3]'" }
> -T (int, 1, 9); // { dg-warning "'\\(\\(int\\*\\)\\(\\(char\\*\\)p \\+ 1\\)\\)\\\[3]'" }
> +T (int, 0, 0); // { dg-warning "'\\*\\(int \\*\\)p' is used uninitialized" }
> +T (int, 0, 1); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)'" }
> +T (int, 0, 2); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)'" }
> +T (int, 0, 3); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)'" }
> +T (int, 0, 4); // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[1]'" }
> +T (int, 0, 5); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[1]'" }
> +T (int, 0, 6); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[1]'" }
> +T (int, 0, 7); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[1]'" }
> +T (int, 0, 8); // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[2]'" }
> +T (int, 0, 9); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[2]'" }
> +
> +
> +T (int, 1, 0); // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[1]' is used uninitialized" }
> +T (int, 1, 1); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[1]'" }
> +T (int, 1, 2); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[1]'" }
> +T (int, 1, 3); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[1]'" }
> +T (int, 1, 4); // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[2]'" }
> +T (int, 1, 5); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[2]'" }
> +T (int, 1, 6); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 2\\)\\)\\\[2]'" }
> +T (int, 1, 7); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 3\\)\\)\\\[2]'" }
> +T (int, 1, 8); // { dg-warning "'\\(\\(int \\*\\)p\\)\\\[3]'" }
> +T (int, 1, 9); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)p \\+ 1\\)\\)\\\[3]'" }
>
> #undef T
> #define T(Type, idx, off) \
> @@ -63,25 +63,25 @@ T (int, 1, 9); // { dg-warning "'\\
> } \
> typedef void dummy_type
>
> -T (int, 0, 0); // { dg-warning "'\\*\\(int\\*\\)a' is used uninitialized" }
> -T (int, 0, 1); // { dg-warning "'\\*\\(int\\*\\)\\(a \\+ 1\\)'" }
> -T (int, 0, 2); // { dg-warning "'\\*\\(int\\*\\)\\(a \\+ 2\\)'" }
> -T (int, 0, 3); // { dg-warning "'\\*\\(int\\*\\)\\(a \\+ 3\\)'" }
> -T (int, 0, 4); // { dg-warning "'\\(\\(int\\*\\)a\\)\\\[1]'" }
> -T (int, 0, 5); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 1\\)\\)\\\[1]'" }
> -T (int, 0, 6); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 2\\)\\)\\\[1]'" }
> -T (int, 0, 7); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 3\\)\\)\\\[1]'" }
> -T (int, 0, 8); // { dg-warning "'\\(\\(int\\*\\)a\\)\\\[2]'" }
> -T (int, 0, 9); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 1\\)\\)\\\[2]'" }
> -
> -
> -T (int, 1, 0); // { dg-warning "'\\(\\(int\\*\\)a\\)\\\[1]' is used uninitialized" }
> -T (int, 1, 1); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 1\\)\\)\\\[1]'" }
> -T (int, 1, 2); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 2\\)\\)\\\[1]'" }
> -T (int, 1, 3); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 3\\)\\)\\\[1]'" }
> -T (int, 1, 4); // { dg-warning "'\\(\\(int\\*\\)a\\)\\\[2]'" }
> -T (int, 1, 5); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 1\\)\\)\\\[2]'" }
> -T (int, 1, 6); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 2\\)\\)\\\[2]'" }
> -T (int, 1, 7); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 3\\)\\)\\\[2]'" }
> -T (int, 1, 8); // { dg-warning "'\\(\\(int\\*\\)a\\)\\\[3]'" }
> -T (int, 1, 9); // { dg-warning "'\\(\\(int\\*\\)\\(a \\+ 1\\)\\)\\\[3]'" }
> +T (int, 0, 0); // { dg-warning "'\\*\\(int \\*\\)a' is used uninitialized" }
> +T (int, 0, 1); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)'" }
> +T (int, 0, 2); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)a \\+ 2\\)'" }
> +T (int, 0, 3); // { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)a \\+ 3\\)'" }
> +T (int, 0, 4); // { dg-warning "'\\(\\(int \\*\\)a\\)\\\[1]'" }
> +T (int, 0, 5); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)\\)\\\[1]'" }
> +T (int, 0, 6); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 2\\)\\)\\\[1]'" }
> +T (int, 0, 7); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 3\\)\\)\\\[1]'" }
> +T (int, 0, 8); // { dg-warning "'\\(\\(int \\*\\)a\\)\\\[2]'" }
> +T (int, 0, 9); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)\\)\\\[2]'" }
> +
> +
> +T (int, 1, 0); // { dg-warning "'\\(\\(int \\*\\)a\\)\\\[1]' is used uninitialized" }
> +T (int, 1, 1); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)\\)\\\[1]'" }
> +T (int, 1, 2); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 2\\)\\)\\\[1]'" }
> +T (int, 1, 3); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 3\\)\\)\\\[1]'" }
> +T (int, 1, 4); // { dg-warning "'\\(\\(int \\*\\)a\\)\\\[2]'" }
> +T (int, 1, 5); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)\\)\\\[2]'" }
> +T (int, 1, 6); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 2\\)\\)\\\[2]'" }
> +T (int, 1, 7); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 3\\)\\)\\\[2]'" }
> +T (int, 1, 8); // { dg-warning "'\\(\\(int \\*\\)a\\)\\\[3]'" }
> +T (int, 1, 9); // { dg-warning "'\\(\\(int \\*\\)\\(\\(char \\*\\)a \\+ 1\\)\\)\\\[3]'" }
> --- gcc/testsuite/gcc.dg/uninit-40.c.jj 2021-01-14 13:17:58.483432786 +0100
> +++ gcc/testsuite/gcc.dg/uninit-40.c 2021-01-14 19:03:08.039606122 +0100
> @@ -0,0 +1,50 @@
> +/* PR tree-optimization/98597 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -Wuninitialized" } */
> +
> +union U { double d; int i; float f; };
> +struct S { char a; int b; char c; unsigned d; union U e; int f[3]; unsigned g[3]; };
> +struct T { char t; struct S u; int v; };
> +typedef short V[2][2];
> +void baz (V *);
> +
> +static inline int
> +bar (char *p)
> +{
> + return *(int *) p;
> +}
> +
> +void
> +foo (int *q)
> +{
> + struct T t;
> + t.t = 1;
> + t.u.c = 2;
> + char *pt = (char *) &t;
> + q[0] = bar (pt + __builtin_offsetof (struct T, u.b)); /* { dg-warning "'t\\.u\\.b' is used uninitialized" } */
> + q[1] = bar (pt + __builtin_offsetof (struct T, u.e)); /* { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)&t \\+ offsetof\\(struct T, u\\.e\\)\\)' is used uninitialized" } */
> + q[2] = bar (pt + __builtin_offsetof (struct T, v)); /* { dg-warning "'t\\.v' is used uninitialized" } */
> + q[3] = bar (pt + __builtin_offsetof (struct T, u.d)); /* { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)&t \\+ offsetof\\(struct T, u\\.d\\)\\)' is used uninitialized" } */
> + q[4] = bar (pt + __builtin_offsetof (struct T, u.f[2])); /* { dg-warning "'t\\.u\\.f\\\[2\\\]' is used uninitialized" } */
> + q[5] = bar (pt + __builtin_offsetof (struct T, u.g[2])); /* { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)&t \\+ offsetof\\(struct T, u\\.g\\\[2\\\]\\)\\)' is used uninitialized" } */
> + int s[3];
> + s[0] = 1;
> + char *ps = (char *) s;
> + q[6] = bar (ps + sizeof (int)); /* { dg-warning "'s\\\[1\\\]' is used uninitialized" } */
> + unsigned w[2][2];
> + w[0][0] = 1;
> + char *pw = (char *) w;
> + q[7] = bar (pw + 3 * sizeof (unsigned)); /* { dg-warning "'\\*\\(int \\*\\)\\(&w\\\[1\\\]\\\[1\\\]\\)' is used uninitialized" } */
> + struct T x[3][3];
> + x[0][0].t = 1;
> + char *px = (char *) x;
> + q[8] = bar (px + 5 * sizeof (struct T) + __builtin_offsetof (struct T, u.b)); /* { dg-warning "'x\\\[1\\\]\\\[2\\\]\\.u\\.b' is used uninitialized" } */
> + q[9] = bar (px + 6 * sizeof (struct T) + __builtin_offsetof (struct T, u.d)); /* { dg-warning "'\\*\\(int \\*\\)\\(\\(char \\*\\)&x\\\[2\\\]\\\[0\\\] \\+ offsetof\\(struct T, u\\.d\\)\\)' is used uninitialized" } */
> +#if defined(__i386__) || defined(__x86_64__)
> + /* memcpy folding is too target dependent to test it everywhere. */
> + V u[2], v[2];
> + u[0][0][0] = 1;
> + __builtin_memcpy (&v[1], &u[1], sizeof (V)); /* { dg-warning "'\\*\\(\(long \)?long unsigned int \\*\\)\\(&u\\\[1\\\]\\\[0\\\]\\\[0\\\]\\)' is used uninitialized" "" { target i?86-*-* x86_64-*-* } } */
> + baz (&v[1]);
> +#endif
> +}
>
>
> Jakub
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
prev parent reply other threads:[~2021-01-15 10:43 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-13 19:11 [PATCH] c-family: " Jakub Jelinek
2021-01-14 7:43 ` Richard Biener
2021-01-14 8:28 ` Jakub Jelinek
2021-01-14 8:34 ` Jakub Jelinek
2021-01-14 10:05 ` Richard Biener
2021-01-14 10:09 ` Jakub Jelinek
2021-01-14 10:17 ` Richard Biener
2021-01-14 17:49 ` Martin Sebor
2021-01-14 18:26 ` [PATCH] c-family, v2: " Jakub Jelinek
2021-01-15 8:58 ` Jakub Jelinek
2021-01-15 10:46 ` Richard Biener
2021-01-15 10:43 ` Richard Biener [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=nycvar.YFH.7.76.2101151143120.17979@zhemvz.fhfr.qr \
--to=rguenther@suse.de \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=msebor@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).