From f04dda3093541436d9ebd3194761ff8199c5ac79 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 23 Jan 2014 19:18:49 +0000 Subject: [PATCH] re PR c/58346 (ICE with SIGFPE at -O1 and above on x86_64-linux-gnu (affecting trunk, 4.8, 4.7, and 4.6)) PR c/58346 c-family/ * c-common.c (pointer_to_zero_sized_aggr_p): New function. * c-common.h: Declare it. cp/ * typeck.c (pointer_diff): Give an error on arithmetic on pointer to an empty aggregate. c/ * c-typeck.c (pointer_diff): Give an error on arithmetic on pointer to an empty aggregate. testsuite/ * c-c++-common/pr58346-1.c: New test. * c-c++-common/pr58346-2.c: New test. * c-c++-common/pr58346-3.c: New test. From-SVN: r207004 --- gcc/c-family/ChangeLog | 6 ++++++ gcc/c-family/c-common.c | 11 +++++++++++ gcc/c-family/c-common.h | 1 + gcc/c/ChangeLog | 6 ++++++ gcc/c/c-typeck.c | 3 +++ gcc/cp/ChangeLog | 6 ++++++ gcc/cp/typeck.c | 8 ++++++++ gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/c-c++-common/pr58346-1.c | 24 ++++++++++++++++++++++++ gcc/testsuite/c-c++-common/pr58346-2.c | 8 ++++++++ gcc/testsuite/c-c++-common/pr58346-3.c | 16 ++++++++++++++++ 11 files changed, 96 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/pr58346-1.c create mode 100644 gcc/testsuite/c-c++-common/pr58346-2.c create mode 100644 gcc/testsuite/c-c++-common/pr58346-3.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 31985585b59..cba9f4e1484 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2014-01-23 Marek Polacek + + PR c/58346 + * c-common.c (pointer_to_zero_sized_aggr_p): New function. + * c-common.h: Declare it. + 2014-01-20 Eric Botcazou * c-ada-spec.h (dump_ada_specs): Revert prototype change. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 35958ea41f0..09128016ba4 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -11823,4 +11823,15 @@ cxx_fundamental_alignment_p (unsigned align) TYPE_ALIGN (long_double_type_node))); } +/* Return true if T is a pointer to a zero-sized aggregate. */ + +bool +pointer_to_zero_sized_aggr_p (tree t) +{ + if (!POINTER_TYPE_P (t)) + return false; + t = TREE_TYPE (t); + return (TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t))); +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 7e3ece6a691..dab0b8cd821 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -789,6 +789,7 @@ extern bool keyword_is_storage_class_specifier (enum rid); extern bool keyword_is_type_qualifier (enum rid); extern bool keyword_is_decl_specifier (enum rid); extern bool cxx_fundamental_alignment_p (unsigned); +extern bool pointer_to_zero_sized_aggr_p (tree); #define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, false, 1) #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, false, 1) diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 237ac1a959c..4088912db61 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2014-01-23 Marek Polacek + + PR c/58346 + * c-typeck.c (pointer_diff): Give an error on arithmetic on pointer to + an empty aggregate. + 2014-01-23 Marek Polacek PR c/59871 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 781d4df246d..77f3bddc469 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3536,6 +3536,9 @@ pointer_diff (location_t loc, tree op0, tree op1) /* This generates an error if op0 is pointer to incomplete type. */ op1 = c_size_in_bytes (target_type); + if (pointer_to_zero_sized_aggr_p (TREE_TYPE (orig_op1))) + error_at (loc, "arithmetic on pointer to an empty aggregate"); + /* Divide by the size, in easiest possible way. */ result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype, op0, convert (inttype, op1)); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 24282044fee..aee3fcf8a98 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2014-01-23 Marek Polacek + + PR c/58346 + * typeck.c (pointer_diff): Give an error on arithmetic on pointer to + an empty aggregate. + 2014-01-23 Jason Merrill PR c++/55189 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 84e287e56bc..9cd6a95a7f1 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5043,6 +5043,14 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) return error_mark_node; } + if (pointer_to_zero_sized_aggr_p (TREE_TYPE (op1))) + { + if (complain & tf_error) + error ("arithmetic on pointer to an empty aggregate"); + else + return error_mark_node; + } + op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) : integer_one_node); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3857078b1db..f3d8d3a7caa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-01-23 Marek Polacek + + PR c/58346 + * c-c++-common/pr58346-1.c: New test. + * c-c++-common/pr58346-2.c: New test. + * c-c++-common/pr58346-3.c: New test. + 2014-01-23 Marek Polacek PR c/59871 diff --git a/gcc/testsuite/c-c++-common/pr58346-1.c b/gcc/testsuite/c-c++-common/pr58346-1.c new file mode 100644 index 00000000000..371fcf48454 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr58346-1.c @@ -0,0 +1,24 @@ +/* PR c/58346 */ +/* { dg-do compile } */ + +struct U { +#ifdef __cplusplus + char a[0]; +#endif +}; +static struct U b[6]; +static struct U *u1, *u2; + +int +foo (struct U *p, struct U *q) +{ + return q - p; /* { dg-error "arithmetic on pointer to an empty aggregate" } */ +} + +void +bar (void) +{ + __PTRDIFF_TYPE__ d = u1 - u2; /* { dg-error "arithmetic on pointer to an empty aggregate" } */ + __asm volatile ("" : "+g" (d)); + foo (&b[0], &b[4]); +} diff --git a/gcc/testsuite/c-c++-common/pr58346-2.c b/gcc/testsuite/c-c++-common/pr58346-2.c new file mode 100644 index 00000000000..195060e420c --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr58346-2.c @@ -0,0 +1,8 @@ +/* PR c/58346 */ +/* { dg-do compile } */ + +__PTRDIFF_TYPE__ +foo (int p[3][0], int q[3][0]) +{ + return p - q; /* { dg-error "arithmetic on pointer to an empty aggregate" } */ +} diff --git a/gcc/testsuite/c-c++-common/pr58346-3.c b/gcc/testsuite/c-c++-common/pr58346-3.c new file mode 100644 index 00000000000..41627ed953c --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr58346-3.c @@ -0,0 +1,16 @@ +/* PR c/58346 */ +/* { dg-do compile } */ + +void +foo (void) +{ + __PTRDIFF_TYPE__ d; + const int i = 0; + int a1[2][0], a2[2][0]; + int b1[3][i], b2[4][i]; + d = a1 - a2; /* { dg-error "arithmetic on pointer to an empty aggregate" } */ + __asm volatile ("" : "+g" (d)); + /* No error here for C. */ + d = b1 - b2; /* { dg-error "arithmetic on pointer to an empty aggregate" "" { target c++ } } */ + __asm volatile ("" : "+g" (d)); +}