+2018-06-21 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2017-08-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81884
+ * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses
+ at struct end conservatively when comparing common bases.
+
+ 2017-05-04 Richard Biener <rguenther@suse.de>
+
+ * tree.c (array_at_struct_end_p): Handle arrays at struct
+ end with flexarrays more conservatively. Refactor and treat
+ arrays of arrays or aggregates more strict. Fix
+ VIEW_CONVERT_EXPR handling.
+
+ 2018-04-06 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/85244
+ * tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref
+ after seeing a component reference with an adjacent field. Treat
+ refs to arrays at struct end of external decls similar to
+ refs to unconstrained commons.
+
2018-06-20 Richard Biener <rguenther@suse.de>
* tree-ssa-alias.c (stmt_kills_ref_p): Revert accidentially
+2018-06-21 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2017-08-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81884
+ * g++.dg/torture/pr81884.C: New testcase.
+
+ 2018-04-06 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/85244
+ * gcc.dg/torture/pr85244-1.c: New testcase.
+ * gcc.dg/torture/pr85244-2.c: Likewise.
+
+ * gcc.dg/tree-prof/pr66295.c: Remove unsupported dg-error scanning.
+
2018-06-20 Richard Biener <rguenther@suse.de>
Backport from mainline
--- /dev/null
+/* { dg-do run } */
+
+typedef unsigned long uint64_t;
+
+struct value_t {
+ uint64_t _count;
+ value_t(uint64_t c) : _count(c) {}
+};
+
+struct X {
+ value_t eventTime;
+ uint64_t arr[0];
+};
+
+X* x;
+
+__attribute__((noclone, noinline))
+void initialize()
+{
+ x->arr[0] = 11;
+ x->arr[1] = 12;
+ x->eventTime = value_t(10);
+ x->arr[2] = 13;
+ x->arr[3] = 14;
+}
+
+int main()
+{
+ char buffer[sizeof(X) + sizeof(uint64_t)*4];
+ x = (X*)buffer;
+ x->eventTime = value_t(999);
+ x->arr[0] = 1;
+ x->arr[1] = 2;
+ x->arr[2] = 3;
+ x->arr[3] = 4;
+ initialize();
+ if (x->arr[0] != 11 || x->arr[1] != 12 || x->arr[2] != 13 || x->arr[3] != 14)
+ __builtin_abort ();
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-additional-sources "pr85244-2.c" } */
+
+struct s {
+ long a;
+ int b;
+ int tab[];
+};
+
+extern const struct s val;
+extern int idx;
+extern void abort (void);
+
+int main()
+{
+ if (val.tab[0] != 42 || val.tab[1] != 1337 || val.tab[idx] != 1337)
+ abort ();
+ return 0;
+}
--- /dev/null
+struct s {
+ long a;
+ int b;
+ int tab[];
+};
+
+int idx = 1;
+const struct s val = { 0, 0, { 42, 1337 } };
}
double
-bar (double *__restrict a, double *__restrict b, int n) /* { dg-error "attribute\[^\n\r]*foo\[^\n\r]* is unknown" } */
+bar (double *__restrict a, double *__restrict b, int n)
{
double s;
int i;
referenced the last field of a struct or a union member
then we have to adjust maxsize by the padding at the end
of our field. */
- if (seen_variable_array_ref && maxsize != -1)
+ if (seen_variable_array_ref)
{
tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
tree next = DECL_CHAIN (field);
|| ssize == NULL
|| TREE_CODE (ssize) != INTEGER_CST)
maxsize = -1;
- else
+ else if (maxsize != -1)
{
offset_int tem = (wi::to_offset (ssize)
- wi::to_offset (fsize));
maxsize += tem;
}
}
+ /* An component ref with an adjacent field up in the
+ structure hierarchy constrains the size of any variable
+ array ref lower in the access hierarchy. */
+ else
+ seen_variable_array_ref = false;
}
}
else
if (DECL_P (exp))
{
- if (flag_unconstrained_commons
- && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp))
+ if (VAR_P (exp)
+ && ((flag_unconstrained_commons && DECL_COMMON (exp))
+ || (DECL_EXTERNAL (exp) && seen_variable_array_ref)))
{
tree sz_tree = TYPE_SIZE (TREE_TYPE (exp));
/* If size is unknown, or we have read to the end, assume there
if (ref->ref)
{
tree base = ref->ref;
+ tree innermost_dropped_array_ref = NULL_TREE;
if (handled_component_p (base))
{
tree saved_lhs0 = NULL_TREE;
TREE_OPERAND (base, 0) = saved_base0;
if (res)
break;
+ /* Remember if we drop an array-ref that we need to
+ double-check not being at struct end. */
+ if (TREE_CODE (base) == ARRAY_REF
+ || TREE_CODE (base) == ARRAY_RANGE_REF)
+ innermost_dropped_array_ref = base;
/* Otherwise drop handled components of the access. */
base = saved_base0;
}
TREE_OPERAND (lhs, 0) = saved_lhs0;
}
/* Finally check if the lhs has the same address and size as the
- base candidate of the access. */
- if (lhs == base
- || (((TYPE_SIZE (TREE_TYPE (lhs))
- == TYPE_SIZE (TREE_TYPE (base)))
- || (TYPE_SIZE (TREE_TYPE (lhs))
- && TYPE_SIZE (TREE_TYPE (base))
- && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
- TYPE_SIZE (TREE_TYPE (base)), 0)))
- && operand_equal_p (lhs, base, OEP_ADDRESS_OF)))
+ base candidate of the access. Watch out if we have dropped
+ an array-ref that was at struct end, this means ref->ref may
+ be outside of the TYPE_SIZE of its base. */
+ if ((! innermost_dropped_array_ref
+ || ! array_at_struct_end_p (innermost_dropped_array_ref))
+ && (lhs == base
+ || (((TYPE_SIZE (TREE_TYPE (lhs))
+ == TYPE_SIZE (TREE_TYPE (base)))
+ || (TYPE_SIZE (TREE_TYPE (lhs))
+ && TYPE_SIZE (TREE_TYPE (base))
+ && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
+ TYPE_SIZE (TREE_TYPE (base)),
+ 0)))
+ && operand_equal_p (lhs, base,
+ OEP_ADDRESS_OF
+ | OEP_MATCH_SIDE_EFFECTS))))
return true;
}
return NULL_TREE;
}
-/* Returns true if REF is an array reference to an array at the end of
- a structure. If this is the case, the array may be allocated larger
+/* Returns true if REF is an array reference or a component reference
+ to an array at the end of a structure.
+ If this is the case, the array may be allocated larger
than its upper bound implies. */
bool
array_at_struct_end_p (tree ref)
{
- if (TREE_CODE (ref) != ARRAY_REF
- && TREE_CODE (ref) != ARRAY_RANGE_REF)
+ tree atype;
+
+ if (TREE_CODE (ref) == ARRAY_REF
+ || TREE_CODE (ref) == ARRAY_RANGE_REF)
+ {
+ atype = TREE_TYPE (TREE_OPERAND (ref, 0));
+ ref = TREE_OPERAND (ref, 0);
+ }
+ else if (TREE_CODE (ref) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
+ atype = TREE_TYPE (TREE_OPERAND (ref, 1));
+ else
return false;
while (handled_component_p (ref))
/* If the reference chain contains a component reference to a
non-union type and there follows another field the reference
is not at the end of a structure. */
- if (TREE_CODE (ref) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+ if (TREE_CODE (ref) == COMPONENT_REF)
{
- tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
- while (nextf && TREE_CODE (nextf) != FIELD_DECL)
- nextf = DECL_CHAIN (nextf);
- if (nextf)
- return false;
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+ {
+ tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+ while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+ nextf = DECL_CHAIN (nextf);
+ if (nextf)
+ return false;
+ }
}
+ /* If we have a multi-dimensional array we do not consider
+ a non-innermost dimension as flex array if the whole
+ multi-dimensional array is at struct end.
+ Same for an array of aggregates with a trailing array
+ member. */
+ else if (TREE_CODE (ref) == ARRAY_REF)
+ return false;
+ else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
+ ;
+ /* If we view an underlying object as sth else then what we
+ gathered up to now is what we have to rely on. */
+ else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+ break;
+ else
+ gcc_unreachable ();
ref = TREE_OPERAND (ref, 0);
}
+ /* The array now is at struct end. Treat flexible arrays as
+ always subject to extend, even into just padding constrained by
+ an underlying decl. */
+ if (! TYPE_SIZE (atype))
+ return true;
+
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. (Do not trust commons PR/69368). */
if (DECL_P (ref)
&& !(flag_unconstrained_commons
- && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref)))
+ && VAR_P (ref) && DECL_COMMON (ref)))
return false;
return true;