From ebbcd0c6ea5d565ffa743079449e9ad6169fcf4e Mon Sep 17 00:00:00 2001
From: Paul Koning <pkoning@gcc.gnu.org>
Date: Wed, 12 Oct 2011 11:16:14 -0400
Subject: [PATCH] re PR middle-end/50189 (Wrong code error in -O2
 [-fstrict-enums] compile, target independent)

2011-10-12  Paul Koning  <pkoning@gcc.gnu.org>

	PR tree-optimization/50189
	* tree-vrp.c (extract_range_from_assert): Use the type of
	the variable, not the limit.

	* g++.dg/torture/pr50189.C: New testcase.

From-SVN: r179857
---
 gcc/ChangeLog                          |   6 ++
 gcc/testsuite/ChangeLog                |   5 +
 gcc/testsuite/g++.dg/torture/pr50189.C | 121 +++++++++++++++++++++++++
 gcc/tree-vrp.c                         |  10 +-
 4 files changed, 137 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr50189.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6bc0bd6809be..194fdb5a7ada 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-12  Paul Koning  <pkoning@gcc.gnu.org>
+
+	PR tree-optimization/50189
+	* tree-vrp.c (extract_range_from_assert): Use the type of
+	the variable, not the limit.
+
 2011-10-12  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/50700
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 827aa2dced85..5af301f78237 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-10-12  Paul Koning  <pkoning@gcc.gnu.org>
+
+	PR tree-optimization/50189
+	* g++.dg/torture/pr50189.C: New testcase.
+
 2011-10-12  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/50700
diff --git a/gcc/testsuite/g++.dg/torture/pr50189.C b/gcc/testsuite/g++.dg/torture/pr50189.C
new file mode 100644
index 000000000000..06f1d3695c1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr50189.C
@@ -0,0 +1,121 @@
+// { dg-do run }
+// { dg-options "-fstrict-enums" }
+
+extern "C" void abort (void);
+class CCUTILS_KeyedScalarLevelPosition
+{
+public:
+
+    typedef enum
+    {
+        UNINITED = 0,
+        AT_BEGIN = 1,
+        AT_END = 2,
+        AT_KEY = 3
+
+    } position_t;
+
+    bool is_init() const
+    { return(m_timestamp != UNINITED); }
+
+    bool is_at_begin() const
+    { return(m_timestamp == AT_BEGIN); }
+
+    position_t get_state() const
+    {
+        return((m_timestamp >= AT_KEY)
+             ? AT_KEY
+             : ((position_t)m_timestamp));
+    }
+
+    void set_at_begin()
+    { m_timestamp = AT_BEGIN; }
+
+    unsigned int get_index() const
+    { return(m_index); }
+
+    void set_pos(unsigned int a_index, unsigned int a_timestmap)
+    {
+        m_index = a_index;
+        m_timestamp = a_timestmap;
+    }
+
+    bool check_pos(unsigned int a_num_entries, unsigned int a_timestamp) const
+    {
+        if (get_state() != AT_KEY)
+            return(false);
+
+        if (m_timestamp != a_timestamp)
+            return(false);
+
+        return(m_index < a_num_entries);
+    }
+
+    void set_not_init()
+    { m_timestamp = 0; }
+
+private:
+
+    unsigned int m_timestamp;
+    unsigned int m_index;
+
+};
+
+class CCUTILS_KeyedScalarPosition
+{
+public:
+
+    CCUTILS_KeyedScalarLevelPosition m_L1;
+    CCUTILS_KeyedScalarLevelPosition m_L2;
+};
+
+class baz
+{
+public:
+    int *n[20];
+    unsigned int m_cur_array_len;
+    unsigned int m_timestamp;
+
+    unsigned int _get_timestamp() const
+    { return(m_timestamp); }
+
+    bool _check_L1_pos(const CCUTILS_KeyedScalarPosition &a_position) const
+    {
+        return(a_position.m_L1.check_pos(
+                   m_cur_array_len, _get_timestamp()));
+    }
+
+    void *next (CCUTILS_KeyedScalarPosition &);
+};
+
+void * baz::next (CCUTILS_KeyedScalarPosition &a_position)
+{
+    if (a_position.m_L1.is_at_begin() || (!a_position.m_L1.is_init()))
+    {
+        a_position.m_L1.set_pos(0, _get_timestamp());
+        a_position.m_L2.set_at_begin();
+    }
+    else if (!_check_L1_pos(a_position))
+        return(0);
+
+    return n[a_position.m_L1.get_index ()];
+}
+
+int main (int, char **)
+{
+    baz obj;
+    CCUTILS_KeyedScalarPosition a_pos;
+    void *ret;
+    int n[5];
+    
+    obj.n[0] = n;
+    obj.m_cur_array_len = 1;
+    obj.m_timestamp = 42;
+    
+    a_pos.m_L1.set_pos (0, 42);
+    
+    ret = obj.next (a_pos);
+    if (ret == 0)
+      abort ();
+    return 0;
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 56fc5a20b2b4..604e7f0ad02a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1519,7 +1519,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 
   limit = avoid_overflow_infinity (limit);
 
-  type = TREE_TYPE (limit);
+  type = TREE_TYPE (var);
   gcc_assert (limit != var);
 
   /* For pointer arithmetic, we only keep track of pointer equality
@@ -1693,8 +1693,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 	  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
 	  if (cond_code == LT_EXPR)
 	    {
-	      tree one = build_int_cst (type, 1);
-	      max = fold_build2 (MINUS_EXPR, type, max, one);
+	      tree one = build_int_cst (TREE_TYPE (max), 1);
+	      max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, one);
 	      if (EXPR_P (max))
 		TREE_NO_WARNING (max) = 1;
 	    }
@@ -1728,8 +1728,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 	  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
 	  if (cond_code == GT_EXPR)
 	    {
-	      tree one = build_int_cst (type, 1);
-	      min = fold_build2 (PLUS_EXPR, type, min, one);
+	      tree one = build_int_cst (TREE_TYPE (min), 1);
+	      min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, one);
 	      if (EXPR_P (min))
 		TREE_NO_WARNING (min) = 1;
 	    }
-- 
GitLab