diff options
author | Mike Frysinger <vapier@gentoo.org> | 2007-06-22 01:25:37 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2007-06-22 01:25:37 +0000 |
commit | 9b3a427724818e8c30f0bd0a481e135ff380bdb3 (patch) | |
tree | 0c984e3d7518e8f8b54ca00062ee65779f54ce27 /4.2.0 | |
parent | merge pending patch for avr guys #173328 (diff) | |
download | gcc-patches-9b3a427724818e8c30f0bd0a481e135ff380bdb3.tar.gz gcc-patches-9b3a427724818e8c30f0bd0a481e135ff380bdb3.tar.bz2 gcc-patches-9b3a427724818e8c30f0bd0a481e135ff380bdb3.zip |
fix from upstream for bad code #179554
Diffstat (limited to '4.2.0')
-rw-r--r-- | 4.2.0/gentoo/42_all_gcc42-PR30252.patch | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/4.2.0/gentoo/42_all_gcc42-PR30252.patch b/4.2.0/gentoo/42_all_gcc42-PR30252.patch new file mode 100644 index 0000000..1b66f8c --- /dev/null +++ b/4.2.0/gentoo/42_all_gcc42-PR30252.patch @@ -0,0 +1,350 @@ +http://bugs.gentoo.org/182728 +http://gcc.gnu.org/PR30252 + +2007-06-19 Richard Guenther <rguenther@suse.de> + Michael Matz <matz@suse.de> + + PR tree-optimization/30252 + * tree-ssa-structalias.c (solution_set_add): Make sure to + preserve all relevant vars. + (handle_ptr_arith): Make sure to only handle positive + offsets. + (push_fields_onto_fieldstack): Create fields for empty + bases. + +Index: gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C +=================================================================== +--- gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C (revision 0) ++++ gcc-4_2-branch/gcc/testsuite/g++.dg/opt/pr30252.C (revision 125844) +@@ -0,0 +1,226 @@ ++/* { dg-do run } */ ++/* { dg-options "-O -fstrict-aliasing" } */ ++ ++extern "C" void abort (void); ++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_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 ++ { ++ }; ++ template <class T_functor> ++ struct functor_trait<T_functor,true> ++ { ++ typedef typename T_functor::result_type result_type; ++ typedef T_functor functor_type; ++ }; ++ template <class T_arg1, class T_return> ++ class pointer_functor1 : public functor_base ++ { ++ typedef T_return (*function_type)(T_arg1); ++ function_type func_ptr_; ++ public: ++ typedef T_return result_type; ++ explicit pointer_functor1(function_type _A_func): func_ptr_(_A_func) {} ++ T_return operator()(typename type_trait<T_arg1>::take _A_a1) const ++ { return func_ptr_(_A_a1); } ++ }; ++ template <class T_arg1, class T_return> ++ inline pointer_functor1<T_arg1, T_return> ++ ptr_fun1(T_return (*_A_func)(T_arg1)) ++ { return pointer_functor1<T_arg1, T_return>(_A_func); } ++ struct adaptor_base : public functor_base {}; ++ template <class T_functor, ++ class T_arg1=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> ++ struct deduce_result_type ++ { typedef typename sigc::deduce_result_type<T_functor, T_arg1>::type type; }; ++ typedef typename functor_trait<T_functor>::result_type result_type; ++ result_type ++ operator()() const; ++ template <class T_arg1> ++ typename deduce_result_type<T_arg1>::type ++ operator()(T_arg1 _A_arg1) const ++ { return functor_(_A_arg1); } ++ explicit adaptor_functor(const T_functor& _A_functor) ++ : functor_(_A_functor) ++ {} ++ mutable T_functor functor_; ++ }; ++ template <class T_functor> ++ typename adaptor_functor<T_functor>::result_type ++ adaptor_functor<T_functor>::operator()() const ++ { return 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 reference_wrapper ++ { ++ }; ++ 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() ++ { return visited_; } ++ T_type visited_; ++ }; ++ template <class T_wrapped> ++ class bound_argument< reference_wrapper<T_wrapped> > ++ { ++ }; ++ template <int I_location, class T_functor, class T_type1=nil> ++ struct bind_functor; ++ template <class T_functor, class T_type1> ++ struct bind_functor<-1, T_functor, T_type1> : public adapts<T_functor> ++ { ++ typedef typename adapts<T_functor>::adaptor_type adaptor_type; ++ typedef typename adaptor_type::result_type result_type; ++ result_type ++ operator()() ++ { ++ return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_type1>::type>::pass> (bound1_.invoke()); ++ } ++ bind_functor(typename type_trait<T_functor>::take _A_func, typename type_trait<T_type1>::take _A_bound1) ++ : adapts<T_functor>(_A_func), bound1_(_A_bound1) ++ {} ++ bound_argument<T_type1> bound1_; ++ }; ++ template <class T_type1, class T_functor> ++ inline bind_functor<-1, T_functor, ++ T_type1> ++ bind(const T_functor& _A_func, T_type1 _A_b1) ++ { return bind_functor<-1, T_functor, ++ T_type1> ++ (_A_func, _A_b1); ++ } ++ namespace internal { ++ struct slot_rep; ++ typedef void* (*hook)(slot_rep *); ++ struct slot_rep ++ { ++ hook call_; ++ }; ++ } ++ class slot_base : public functor_base ++ { ++ public: ++ typedef internal::slot_rep rep_type; ++ explicit slot_base(rep_type* rep) ++ : rep_(rep) ++ { ++ } ++ mutable rep_type *rep_; ++ }; ++ namespace internal { ++ template <class T_functor> ++ struct typed_slot_rep : public slot_rep ++ { ++ typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type; ++ adaptor_type functor_; ++ inline typed_slot_rep(const T_functor& functor) ++ : functor_(functor) ++ { ++ } ++ }; ++ template<class T_functor> ++ struct slot_call0 ++ { ++ static void *call_it(slot_rep* rep) ++ { ++ typedef typed_slot_rep<T_functor> typed_slot; ++ typed_slot *typed_rep = static_cast<typed_slot*>(rep); ++ return (typed_rep->functor_)(); ++ } ++ static hook address() ++ { ++ return &call_it; ++ } ++ }; ++ } ++ ++ class slot0 : public slot_base ++ { ++ public: ++ typedef void * (*call_type)(rep_type*); ++ inline void *operator()() const ++ { ++ return slot_base::rep_->call_ (slot_base::rep_); ++ } ++ template <class T_functor> ++ slot0(const T_functor& _A_func) ++ : slot_base(new internal::typed_slot_rep<T_functor>(_A_func)) ++ { ++ slot_base::rep_->call_ = internal::slot_call0<T_functor>::address(); ++ } ++ }; ++} ++struct A ++{ ++ static void *foo (void *p) { return p; } ++ typedef sigc::slot0 C; ++ C bar(); ++}; ++A::C A::bar () ++{ ++ return sigc::bind (sigc::ptr_fun1 (&A::foo), (void*)0); ++} ++int main (void) ++{ ++ A a; ++ if (a.bar ()() != 0) ++ abort (); ++} +Index: gcc-4_2-branch/gcc/tree-ssa-structalias.c +=================================================================== +--- gcc-4_2-branch/gcc/tree-ssa-structalias.c (revision 125843) ++++ gcc-4_2-branch/gcc/tree-ssa-structalias.c (revision 125844) +@@ -708,6 +708,26 @@ solution_set_add (bitmap set, unsigned H + bitmap result = BITMAP_ALLOC (&iteration_obstack); + unsigned int i; + bitmap_iterator bi; ++ unsigned HOST_WIDE_INT min = -1, max = 0; ++ ++ /* Compute set of vars we can reach from set + offset. */ ++ ++ EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) ++ { ++ if (get_varinfo (i)->is_artificial_var ++ || get_varinfo (i)->has_union ++ || get_varinfo (i)->is_unknown_size_var) ++ continue; ++ ++ if (get_varinfo (i)->offset + offset < min) ++ min = get_varinfo (i)->offset + offset; ++ if (get_varinfo (i)->offset + get_varinfo (i)->size + offset > max) ++ { ++ max = get_varinfo (i)->offset + get_varinfo (i)->size + offset; ++ if (max > get_varinfo (i)->fullsize) ++ max = get_varinfo (i)->fullsize; ++ } ++ } + + EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) + { +@@ -715,13 +735,10 @@ solution_set_add (bitmap set, unsigned H + less than end. Otherwise, it is globbed to a single + variable. */ + +- if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize) ++ if (get_varinfo (i)->offset + get_varinfo (i)->size - 1 >= min ++ && get_varinfo (i)->offset < max) + { +- unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset; +- varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset); +- if (!v) +- continue; +- bitmap_set_bit (result, v->id); ++ bitmap_set_bit (result, i); + } + else if (get_varinfo (i)->is_artificial_var + || get_varinfo (i)->has_union +@@ -3258,7 +3275,7 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc + unsigned int i = 0; + unsigned int j = 0; + VEC (ce_s, heap) *temp = NULL; +- unsigned int rhsoffset = 0; ++ unsigned HOST_WIDE_INT rhsoffset = 0; + + if (TREE_CODE (expr) != PLUS_EXPR + && TREE_CODE (expr) != MINUS_EXPR) +@@ -3269,9 +3286,12 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc + + get_constraint_for (op0, &temp); + if (POINTER_TYPE_P (TREE_TYPE (op0)) +- && TREE_CODE (op1) == INTEGER_CST ++ && host_integerp (op1, 1) + && TREE_CODE (expr) == PLUS_EXPR) + { ++ if ((TREE_INT_CST_LOW (op1) * BITS_PER_UNIT) / BITS_PER_UNIT ++ != TREE_INT_CST_LOW (op1)) ++ return false; + rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT; + } + else +@@ -3661,6 +3681,7 @@ push_fields_onto_fieldstack (tree type, + { + tree field; + int count = 0; ++ unsigned HOST_WIDE_INT minoffset = -1; + + if (TREE_CODE (type) == COMPLEX_TYPE) + { +@@ -3773,8 +3794,25 @@ push_fields_onto_fieldstack (tree type, + } + else + count += pushed; ++ ++ if (bitpos_of_field (field) < minoffset) ++ minoffset = bitpos_of_field (field); + } + ++ /* We need to create a fake subvar for empty bases. But _only_ for non-empty ++ classes. */ ++ if (minoffset != 0 && count != 0) ++ { ++ fieldoff_s *pair; ++ ++ pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); ++ pair->type = void_type_node; ++ pair->size = build_int_cst (size_type_node, minoffset); ++ pair->decl = NULL; ++ pair->offset = offset; ++ count++; ++ } ++ + return count; + } + |