diff options
author | Richard Biener <rguenth@gcc.gnu.org> | 2007-06-19 12:57:58 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2007-06-19 12:57:58 +0000 |
commit | 9bf448b9057dee370741ca48edfc9bec954894a6 (patch) | |
tree | bd94d5dc228225eeb3ef8f7672769335206713d3 /gcc | |
parent | 258d0b9b9e7ca27b5e7e3a2dbb1488a9f4e13bfd (diff) | |
download | gcc-9bf448b9057dee370741ca48edfc9bec954894a6.zip gcc-9bf448b9057dee370741ca48edfc9bec954894a6.tar.gz gcc-9bf448b9057dee370741ca48edfc9bec954894a6.tar.bz2 |
tree-ssa-structalias.c (handle_ptr_arith): Make sure to only handle positive offsets that fit in a HOST_WIDE_INT.
2007-06-19 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (handle_ptr_arith): Make sure to
only handle positive offsets that fit in a HOST_WIDE_INT.
* g++.dg/torture/pr30252.C: New testcase.
From-SVN: r125849
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr30252.C | 226 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 13 |
4 files changed, 246 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3b9f881..409885a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,9 @@ -2007-06-18 Uros Bizjak <ubizjak@gmail.com> +2007-06-19 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.c (handle_ptr_arith): Make sure to + only handle positive offsets that fit in a HOST_WIDE_INT. + +2007-06-19 Uros Bizjak <ubizjak@gmail.com> * config/i386/i386.c (ix86_emit_swsqrtsf): Limit the result of rsqrt insn to FLT_MAX to avoid NaN for zero input argument. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 467635d..dd2a1a4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-06-19 Richard Guenther <rguenther@suse.de> + + * g++.dg/torture/pr30252.C: New testcase. + 2007-06-19 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/32353 diff --git a/gcc/testsuite/g++.dg/torture/pr30252.C b/gcc/testsuite/g++.dg/torture/pr30252.C new file mode 100644 index 0000000..aabf88f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr30252.C @@ -0,0 +1,226 @@ +/* { dg-do run } */ +/* { dg-options "-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 (); +} diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 2b69728..663dff0 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3291,7 +3291,7 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr) 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) != POINTER_PLUS_EXPR) return false; @@ -3302,8 +3302,15 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr) get_constraint_for (op0, &temp); - if (TREE_CODE (op1) == INTEGER_CST) - rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT; + /* We can only handle positive offsets that do not overflow + if we multiply it by BITS_PER_UNIT. */ + if (host_integerp (op1, 1)) + { + rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT; + + if (rhsoffset / BITS_PER_UNIT != TREE_INT_CST_LOW (op1)) + return false; + } for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++) for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++) |