aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDaniel Berlin <dberlin@dberlin.org>2005-11-03 15:39:48 +0000
committerDaniel Berlin <dberlin@gcc.gnu.org>2005-11-03 15:39:48 +0000
commit031905948adabb18c9a4f1fe9156cbf5aea964b2 (patch)
tree9dcbe9162456b36aa816086c8de751f7d2af94ad /gcc
parent08330ec2ad5a413f7e88fbb48092dd0d27000850 (diff)
downloadgcc-031905948adabb18c9a4f1fe9156cbf5aea964b2.zip
gcc-031905948adabb18c9a4f1fe9156cbf5aea964b2.tar.gz
gcc-031905948adabb18c9a4f1fe9156cbf5aea964b2.tar.bz2
re PR tree-optimization/24351 (ICE in do_simple_structure_copy with some C++ code)
2005-11-03 Daniel Berlin <dberlin@dberlin.org> Fix PR tree-optimization/24351 * tree-ssa-structalias.c (struct variable_info): Add collapsed_into. (get_varinfo_fc): New function to follow collapsing. (new_var_info): Set collapsed_to to NULL. (dump_constraint): Follow collapsing. (build_constraint_graph): Handle collapsing. (do_simple_structure_copy): Return false if something bad happened. (collapse_rest_of_var): New function. (do_structure_copy): Collapse if do_simple_structure_copy returns false. From-SVN: r106437
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr24351-1.C24
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr24351-2.C25
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr24351-3.C101
-rw-r--r--gcc/tree-ssa-structalias.c94
5 files changed, 245 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e449baa..a1b0097 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2005-11-03 Daniel Berlin <dberlin@dberlin.org>
+
+ Fix PR tree-optimization/24351
+
+ * tree-ssa-structalias.c (struct variable_info): Add
+ collapsed_into.
+ (get_varinfo_fc): New function to follow collapsing.
+ (new_var_info): Set collapsed_to to NULL.
+ (dump_constraint): Follow collapsing.
+ (build_constraint_graph): Handle collapsing.
+ (do_simple_structure_copy): Return false if something bad
+ happened.
+ (collapse_rest_of_var): New function.
+ (do_structure_copy): Collapse if do_simple_structure_copy returns
+ false.
+
2005-11-03 Andrew Pinski <pinskia@physics.uc.edu>
PR middle-end/24589
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr24351-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr24351-1.C
new file mode 100644
index 0000000..40959ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr24351-1.C
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+struct adaptor_base {
+};
+struct bound_argument {
+ bound_argument();
+};
+template <class T_functor> struct adaptor_functor : public adaptor_base {
+ explicit adaptor_functor(const T_functor& _A_functor) : functor_(_A_functor)
+{
+ }
+ T_functor functor_;
+ bound_argument bound_;
+};
+template <class T_functor> struct adapts : public adaptor_base {
+ explicit adapts(const T_functor& _A_functor) : functor_(_A_functor) {
+ }
+ adaptor_functor<T_functor> functor_;
+};
+int main() {
+ adapts<adapts<int> > a (adapts<int>(1));
+}
+
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr24351-2.C b/gcc/testsuite/g++.dg/tree-ssa/pr24351-2.C
new file mode 100644
index 0000000..cfc0e4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr24351-2.C
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+struct adaptor_base {};
+struct bound_argument {
+ bound_argument();
+};
+struct adaptor_functorint : public adaptor_base {};
+struct adaptsint : public adaptor_base {
+ adaptsint(const int& _A_functor);
+ adaptor_functorint functor_;
+};
+struct adaptor_functor_adaptsint {
+ adaptor_functor_adaptsint(const adaptsint& _A_functor) : functor_(_A_functor)
+ {}
+ adaptsint functor_;
+ bound_argument bound_;
+};
+struct adapts_adaptsint {
+ adapts_adaptsint(const adaptsint& _A_functor) : functor_(_A_functor)
+ {}
+ adaptor_functor_adaptsint functor_;
+};
+int main() {
+ adapts_adaptsint a (adaptsint(1));
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr24351-3.C b/gcc/testsuite/g++.dg/tree-ssa/pr24351-3.C
new file mode 100644
index 0000000..09a3f94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr24351-3.C
@@ -0,0 +1,101 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+namespace sigc {
+ template <class T_type> struct type_trait {
+ typedef T_type& pass;
+ typedef const T_type& take;
+ typedef T_type* pointer;
+ };
+ template <class T_type> struct type_trait<T_type&> {
+ typedef T_type& pass;
+ };
+ template<> struct type_trait<void> {
+ typedef void pass;
+ };
+ template <class T_base, class T_derived> struct is_base_and_derived {
+ struct big {
+ char memory[64];
+ };
+ static big is_base_class_(...);
+ static char is_base_class_(typename type_trait<T_base>::pointer);
+ static const bool value = sizeof(is_base_class_(reinterpret_cast<typename type_trait<T_derived>::pointer>(0))) == sizeof(char);
+ };
+ struct nil;
+ struct functor_base {
+ };
+ template <class T_functor, bool I_derives_functor_base=is_base_and_derived<functor_base,T_functor>::value> struct functor_trait {
+ typedef typename T_functor::result_type result_type;
+ typedef T_functor functor_type;
+ };
+ struct adaptor_base : public functor_base {
+ };
+ template <class T_functor, class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void, bool I_derives_adaptor_base=is_base_and_derived<adaptor_base,T_functor>::value> struct deduce_result_type {
+ typedef typename functor_trait<T_functor>::result_type type;
+ };
+ template <class T_functor> struct adaptor_functor
+ : public adaptor_base {
+ template <class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void> struct deduce_result_type {
+ typedef typename sigc::deduce_result_type<T_functor, T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,T_arg6,T_arg7>::type type;
+ };
+ typedef typename functor_trait<T_functor>::result_type result_type;
+ template <class T_arg1,class T_arg2> typename deduce_result_type<T_arg1,T_arg2>::type operator()(T_arg1 _A_arg1,T_arg2 _A_arg2) const {
+ return functor_(_A_arg1,_A_arg2);
+ }
+ explicit adaptor_functor(const T_functor& _A_functor) : functor_(_A_functor) {
+ }
+ mutable T_functor functor_;
+ };
+ template <class T_functor, bool I_isadaptor = is_base_and_derived<adaptor_base, T_functor>::value> struct adaptor_trait;
+ template <class T_functor> struct adaptor_trait<T_functor, true> {
+ typedef T_functor adaptor_type;
+ };
+ template <class T_functor> struct adaptor_trait<T_functor, false> {
+ typedef typename functor_trait<T_functor>::functor_type functor_type;
+ typedef adaptor_functor<functor_type> adaptor_type;
+ };
+ template <class T_functor> struct adapts
+ : public adaptor_base {
+ typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
+ explicit adapts(const T_functor& _A_functor) : functor_(_A_functor) {
+ }
+ mutable adaptor_type functor_;
+ };
+ template <class T_type> struct unwrap_reference {
+ typedef T_type type;
+ };
+ template <class T_type> class bound_argument {
+ public:
+ bound_argument(const T_type& _A_argument) : visited_(_A_argument) {
+ }
+ inline T_type& invoke() {
+ }
+ T_type visited_;
+ };
+ template <int I_location, class T_functor, class T_type1=nil,class T_type2=nil,class T_type3=nil,class T_type4=nil,class T_type5=nil,class T_type6=nil,class T_type7=nil> struct bind_functor;
+ template <class T_functor, class T_bound> struct bind_functor<0, T_functor, T_bound, nil,nil,nil,nil,nil,nil> : public adapts<T_functor> {
+ typedef typename adapts<T_functor>::adaptor_type adaptor_type;
+ template <class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void> struct deduce_result_type {
+ typedef typename adaptor_type::template deduce_result_type<typename type_trait<typename unwrap_reference<T_bound>::type>::pass, typename type_trait<T_arg1>::pass, typename type_trait<T_arg2>::pass, typename type_trait<T_arg3>::pass, typename type_trait<T_arg4>::pass, typename type_trait<T_arg5>::pass, typename type_trait<T_arg6>::pass>::type type;
+ };
+ typedef typename adaptor_type::result_type result_type;
+ result_type operator()() {
+ return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_bound>::type>::pass> (bound_.invoke());
+ }
+ template <class T_arg1> typename deduce_result_type<T_arg1>::type operator()(T_arg1 _A_arg1) {
+ return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_bound>::type>::pass, typename type_trait<T_arg1>::pass> (bound_.invoke(), _A_arg1);
+ }
+ bind_functor(typename type_trait<T_functor>::take _A_func, typename type_trait<T_bound>::take _A_bound) : adapts<T_functor>(_A_func), bound_(_A_bound) {
+ }
+ bound_argument<T_bound> bound_;
+ };
+ template <int I_location, class T_bound1, class T_functor> inline bind_functor<I_location, T_functor, T_bound1> bind(const T_functor& _A_func, T_bound1 _A_b1) {
+ return bind_functor<I_location, T_functor, T_bound1>(_A_func, _A_b1);
+ };
+}
+struct foo {
+ typedef int result_type;
+ int operator()(int i, int j);
+};
+int main() {
+ sigc::bind<0>(sigc::bind<0>(foo(),7),8)();
+}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 1e1d64d..cee6502 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -239,6 +239,11 @@ struct variable_info
/* Vector of complex constraints for this node. Complex
constraints are those involving dereferences. */
VEC(constraint_t,heap) *complex;
+
+ /* Variable id this was collapsed to due to type unsafety.
+ This should be unused completely after build_constraint_graph, or
+ something is broken. */
+ struct variable_info *collapsed_to;
};
typedef struct variable_info *varinfo_t;
@@ -258,11 +263,23 @@ static VEC(varinfo_t,heap) *varmap;
/* Return the varmap element N */
static inline varinfo_t
-get_varinfo(unsigned int n)
+get_varinfo (unsigned int n)
{
return VEC_index(varinfo_t, varmap, n);
}
+/* Return the varmap element N, following the collapsed_to link. */
+
+static inline varinfo_t
+get_varinfo_fc (unsigned int n)
+{
+ varinfo_t v = VEC_index(varinfo_t, varmap, n);
+
+ if (v->collapsed_to)
+ return v->collapsed_to;
+ return v;
+}
+
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
static tree anything_tree;
@@ -316,6 +333,7 @@ new_var_info (tree t, unsigned int id, const char *name, unsigned int node)
bitmap_clear (ret->variables);
ret->complex = NULL;
ret->next = NULL;
+ ret->collapsed_to = NULL;
return ret;
}
@@ -429,7 +447,7 @@ dump_constraint (FILE *file, constraint_t c)
fprintf (file, "&");
else if (c->lhs.type == DEREF)
fprintf (file, "*");
- fprintf (file, "%s", get_varinfo (c->lhs.var)->name);
+ fprintf (file, "%s", get_varinfo_fc (c->lhs.var)->name);
if (c->lhs.offset != 0)
fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->lhs.offset);
fprintf (file, " = ");
@@ -437,7 +455,7 @@ dump_constraint (FILE *file, constraint_t c)
fprintf (file, "&");
else if (c->rhs.type == DEREF)
fprintf (file, "*");
- fprintf (file, "%s", get_varinfo (c->rhs.var)->name);
+ fprintf (file, "%s", get_varinfo_fc (c->rhs.var)->name);
if (c->rhs.offset != 0)
fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->rhs.offset);
fprintf (file, "\n");
@@ -982,33 +1000,36 @@ build_constraint_graph (void)
{
struct constraint_expr lhs = c->lhs;
struct constraint_expr rhs = c->rhs;
+ unsigned int lhsvar = get_varinfo_fc (lhs.var)->id;
+ unsigned int rhsvar = get_varinfo_fc (rhs.var)->id;
+
if (lhs.type == DEREF)
{
/* *x = y or *x = &y (complex) */
- if (rhs.type == ADDRESSOF || rhs.var > anything_id)
- insert_into_complex (lhs.var, c);
+ if (rhs.type == ADDRESSOF || rhsvar > anything_id)
+ insert_into_complex (lhsvar, c);
}
else if (rhs.type == DEREF)
{
/* !special var= *y */
- if (!(get_varinfo (lhs.var)->is_special_var))
- insert_into_complex (rhs.var, c);
+ if (!(get_varinfo (lhsvar)->is_special_var))
+ insert_into_complex (rhsvar, c);
}
else if (rhs.type == ADDRESSOF)
{
/* x = &y */
- bitmap_set_bit (get_varinfo (lhs.var)->solution, rhs.var);
+ bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
}
- else if (lhs.var > anything_id)
+ else if (lhsvar > anything_id)
{
/* Ignore 0 weighted self edges, as they can't possibly contribute
anything */
- if (lhs.var != rhs.var || rhs.offset != 0 || lhs.offset != 0)
+ if (lhsvar != rhsvar || rhs.offset != 0 || lhs.offset != 0)
{
struct constraint_edge edge;
- edge.src = lhs.var;
- edge.dest = rhs.var;
+ edge.src = lhsvar;
+ edge.dest = rhsvar;
/* x = y (simple) */
add_graph_edge (graph, edge);
bitmap_set_bit (get_graph_weights (graph, edge),
@@ -2300,9 +2321,12 @@ get_constraint_for (tree t, bool *need_anyoffset)
For each field of the lhs variable (lhsfield)
For each field of the rhs variable at lhsfield.offset (rhsfield)
add the constraint lhsfield = rhsfield
-*/
-static void
+ If we fail due to some kind of type unsafety or other thing we
+ can't handle, return false. We expect the caller to collapse the
+ variable in that case. */
+
+static bool
do_simple_structure_copy (const struct constraint_expr lhs,
const struct constraint_expr rhs,
const unsigned HOST_WIDE_INT size)
@@ -2322,9 +2346,12 @@ do_simple_structure_copy (const struct constraint_expr lhs,
q = get_varinfo (temprhs.var);
fieldoffset = p->offset - pstart;
q = first_vi_for_offset (q, q->offset + fieldoffset);
+ if (!q)
+ return false;
temprhs.var = q->id;
process_constraint (new_constraint (templhs, temprhs));
}
+ return true;
}
@@ -2406,6 +2433,32 @@ do_lhs_deref_structure_copy (const struct constraint_expr lhs,
}
}
+/* Sometimes, frontends like to give us bad type information. This
+ function will collapse all the fields from VAR to the end of VAR,
+ into VAR, so that we treat those fields as a single variable.
+ We return the variable they were collapsed into. */
+
+static unsigned int
+collapse_rest_of_var (unsigned int var)
+{
+ varinfo_t currvar = get_varinfo (var);
+ varinfo_t field;
+
+ for (field = currvar->next; field; field = field->next)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Type safety: Collapsing var %s into %s\n",
+ field->name, currvar->name);
+
+ gcc_assert (!field->collapsed_to);
+ field->collapsed_to = currvar;
+ }
+
+ currvar->next = NULL;
+ currvar->size = currvar->fullsize - currvar->offset;
+
+ return currvar->id;
+}
/* Handle aggregate copies by expanding into copies of the respective
fields of the structures. */
@@ -2492,7 +2545,18 @@ do_structure_copy (tree lhsop, tree rhsop)
if (rhs.type == SCALAR && lhs.type == SCALAR)
- do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
+ {
+ if (!do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize)))
+ {
+ lhs.var = collapse_rest_of_var (lhs.var);
+ rhs.var = collapse_rest_of_var (rhs.var);
+ lhs.offset = 0;
+ rhs.offset = 0;
+ lhs.type = SCALAR;
+ rhs.type = SCALAR;
+ process_constraint (new_constraint (lhs, rhs));
+ }
+ }
else if (lhs.type != DEREF && rhs.type == DEREF)
do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
else if (lhs.type == DEREF && rhs.type != DEREF)