diff options
author | Martin Sebor <msebor@redhat.com> | 2021-10-26 14:40:33 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-10-26 16:53:54 -0600 |
commit | 1ff4dbddcf74203a1e16316b18e12f9e1b5085f0 (patch) | |
tree | 5f6066e4ea74c6ac5a9a3e6e52ae5abb0a6cc95b /gcc/testsuite | |
parent | 9a27acc30a34b7854db32eac562306cebac6fa1e (diff) | |
download | gcc-1ff4dbddcf74203a1e16316b18e12f9e1b5085f0.zip gcc-1ff4dbddcf74203a1e16316b18e12f9e1b5085f0.tar.gz gcc-1ff4dbddcf74203a1e16316b18e12f9e1b5085f0.tar.bz2 |
Improve/correct detection of overlapping aggregates [PR102238, PR102919].
Resolves:
PR tree-optimization/102238 - alias_offset in gimple-ssa-sprintf.c is broken
PR tree-optimization/102919 - spurious -Wrestrict warning for sprintf into the same member array as argument plus offset
gcc/ChangeLog:
PR tree-optimization/102238
PR tree-optimization/102919
* gimple-ssa-sprintf.c (get_string_length): Add an argument.
(array_elt_at_offset): Move to pointer-query.
(set_aggregate_size_and_offset): New function.
(field_at_offset): Move to pointer-query.
(get_origin_and_offset): Rename...
(get_origin_and_offset_r): this. Add an argument. Make aggregate
handling more robust.
(get_origin_and_offset): New.
(alias_offset): Add an argument.
(format_string): Use subobject size determined by get_origin_and_offset.
* pointer-query.cc (field_at_offset): Move from gimple-ssa-sprintf.c.
Improve/correct handling of aggregates.
(array_elt_at_offset): Same.
* pointer-query.h (field_at_offset): Declare.
(array_elt_at_offset): Declare.
gcc/testsuite/ChangeLog:
PR tree-optimization/102238
PR tree-optimization/102919
* gcc.dg/tree-ssa/builtin-sprintf-warn-23.c: Remove warnings.
* gcc.dg/Wrestrict-23.c: New test.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/gcc.dg/Wrestrict-23.c | 146 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c | 24 |
2 files changed, 159 insertions, 11 deletions
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-23.c b/gcc/testsuite/gcc.dg/Wrestrict-23.c new file mode 100644 index 0000000..c7a828b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-23.c @@ -0,0 +1,146 @@ +/* PR tree-optimization/102238 - missing -Wrestrict on sprintf formatting + a struct member into enclosing object + { dg-do compile } + { dg-options "-O2 -Wall -Wno-format-overflow" } */ + +extern int sprintf (char*, const char*, ...); + +extern void sink (void*, ...); + +struct A +{ + char a[4]; +}; + +struct B +{ + struct A a1, a2; +}; + +extern struct B eb; + +enum { B_a2_a_off = __builtin_offsetof (struct B, a2.a) }; + + +void test_warn_src_decl_plus (void) +{ + { + char *s = (char*)&eb + B_a2_a_off; + char *d = eb.a2.a; + sprintf (d, "%s", s); // { dg-warning "overlaps" } + } + + { + // If strlen (s) > 0 there is overlap with a[1]. + char *s = (char*)&eb + B_a2_a_off + 1; + char *d = eb.a2.a; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // strlen (s) must be at most 1 so there can be no overlap with a. + char *s = (char*)&eb + B_a2_a_off + 2; + char *d = eb.a2.a; + sprintf (d, "%s", s); // { dg-bogus "-Wrestrict" } + } + + { + // strlen (s) must be at most 0 so there can be no overlap with a. + char *s = (char*)&eb + B_a2_a_off + 3; + char *d = eb.a2.a; + sprintf (d, "%s", s); // { dg-bogus "-Wrestrict" } + } +} + + +void test_warn_src_ptr_plus (struct B *p) +{ + { + char *s = (char*)p + B_a2_a_off; + char *d = p->a2.a; + sprintf (d, "%s", s); // { dg-warning "overlaps" } + } + + { + // If strlen (s) > 0 there is overlap with a[1]. + char *s = (char*)p + B_a2_a_off + 1; + char *d = p->a2.a; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // strlen (s) must be at most 1 so there can be no overlap with a. + char *s = (char*)p + B_a2_a_off + 2; + char *d = p->a2.a; + sprintf (d, "%s", s); // { dg-bogus "-Wrestrict" } + } + + { + // strlen (s) must be at most 0 so there can be no overlap with a. + char *s = (char*)p + B_a2_a_off + 3; + char *d = p->a2.a; + sprintf (d, "%s", s); // { dg-bogus "-Wrestrict" } + } +} + + +void test_warn_dst_decl_plus (void) +{ + { + char *s = eb.a2.a; + char *d = (char*)&eb + B_a2_a_off; + sprintf (d, "%s", s); // { dg-warning "overlaps" } + } + + { + // If strlen (a) > 0 there is overlap with a[1]. + char *s = eb.a2.a; + char *d = (char*)&eb + B_a2_a_off + 1; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // If strlen (a) > 1 there is overlap with a[2]. + char *s = eb.a2.a; + char *d = (char*)&eb + B_a2_a_off + 2; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // If strlen (a) > 2 there is overlap with a[3]. + char *s = eb.a2.a; + char *d = (char*)&eb + B_a2_a_off + 3; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } +} + + +void test_warn_dst_ptr_plus (struct B *p) +{ + { + char *s = p->a2.a; + char *d = (char*)p + B_a2_a_off; + sprintf (d, "%s", s); // { dg-warning "overlaps" } + } + + { + // If strlen (a) > 0 there is overlap with a[1]. + char *s = p->a2.a; + char *d = (char*)p + B_a2_a_off + 1; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // If strlen (a) > 1 there is overlap with a[2]. + char *s = p->a2.a; + char *d = (char*)p + B_a2_a_off + 2; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } + + { + // If strlen (a) > 2 there is overlap with a[3]. + char *s = p->a2.a; + char *d = (char*)p + B_a2_a_off + 3; + sprintf (d, "%s", s); // { dg-warning "may overlap" } + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c index 7fb9651..112b08a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-23.c @@ -214,12 +214,14 @@ void test_struct_member_array (struct S3 *s3, int i) T (d, "%s", d); /* { dg-warning "overlaps" } */ T (d, "%s", d + 0); /* { dg-warning "overlaps" } */ T (d, "%s", d + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", d + 2); /* { dg-warning "may overlap" } */ + /* Since d below points to char[4], strlen(d + 2) must be at most 1 + and so the call cannot overlap. */ + T (d, "%s", d + 2); T (d, "%s", d + i); /* { dg-warning "may overlap" } */ T (d, "%s", &d[0]); /* { dg-warning "overlaps" } */ T (d, "%s", &d[1]); /* { dg-warning "may overlap" } */ - T (d, "%s", &d[2]); /* { dg-warning "may overlap" } */ + T (d, "%s", &d[2]); T (d, "%s", &d[i]); /* { dg-warning "may overlap" } */ T (d + 0, "%s", d); /* { dg-warning "overlaps" } */ @@ -236,7 +238,7 @@ void test_struct_member_array (struct S3 *s3, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ s = s3->s2_1.s_1.b; @@ -324,7 +326,7 @@ void test_struct_member_array (struct S3 *s3, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ s = s3->s2_2.s_2.a; @@ -368,7 +370,7 @@ void test_struct_member_array (struct S3 *s3, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ s = s3->s2_2.s_2.a; @@ -394,12 +396,12 @@ void test_struct_member_array_array (struct S3 *s3, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 0); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ T (d, "%s", &s[0]); /* { dg-warning "overlaps" } */ T (d, "%s", &s[1]); /* { dg-warning "may overlap" } */ - T (d, "%s", &s[2]); /* { dg-warning "may overlap" } */ + T (d, "%s", &s[2]); T (d, "%s", &s[i]); /* { dg-warning "may overlap" } */ T (d + 0, "%s", s); /* { dg-warning "overlaps" } */ @@ -566,12 +568,12 @@ void test_union_member_array (union U *un, int i) T (d, "%s", d); /* { dg-warning "overlaps" } */ T (d, "%s", d + 0); /* { dg-warning "overlaps" } */ T (d, "%s", d + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", d + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", d + 2); T (d, "%s", d + i); /* { dg-warning "may overlap" } */ T (d, "%s", &d[0]); /* { dg-warning "overlaps" } */ T (d, "%s", &d[1]); /* { dg-warning "may overlap" } */ - T (d, "%s", &d[2]); /* { dg-warning "may overlap" } */ + T (d, "%s", &d[2]); T (d, "%s", &d[i]); /* { dg-warning "may overlap" } */ T (d + 0, "%s", d); /* { dg-warning "overlaps" } */ @@ -588,7 +590,7 @@ void test_union_member_array (union U *un, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ s = un->s2_1.s_1.b; @@ -616,7 +618,7 @@ void test_union_member_array (union U *un, int i) T (d, "%s", s); /* { dg-warning "overlaps" } */ T (d, "%s", s + 1); /* { dg-warning "may overlap" } */ - T (d, "%s", s + 2); /* { dg-warning "may overlap" } */ + T (d, "%s", s + 2); T (d, "%s", s + i); /* { dg-warning "may overlap" } */ s = un->s2_2.s_1.b; |