case REAL_CST:
{
- real_value *rv1 = TREE_REAL_CST_PTR (t1);
- real_value *rv2 = TREE_REAL_CST_PTR (t2);
+ const real_value *rv1 = TREE_REAL_CST_PTR (t1);
+ const real_value *rv2 = TREE_REAL_CST_PTR (t2);
+ if (real_compare (UNORDERED_EXPR, rv1, rv2))
+ {
+ /* Impose an arbitrary order on NaNs relative to other NaNs
+ and to non-NaNs. */
+ if (int cmp_isnan = real_isnan (rv1) - real_isnan (rv2))
+ return cmp_isnan;
+ if (int cmp_issignaling_nan
+ = real_issignaling_nan (rv1) - real_issignaling_nan (rv2))
+ return cmp_issignaling_nan;
+ return real_isneg (rv1) - real_isneg (rv2);
+ }
if (real_compare (LT_EXPR, rv1, rv2))
return -1;
- if (real_compare (LT_EXPR, rv2, rv1))
+ if (real_compare (GT_EXPR, rv1, rv2))
return 1;
return 0;
}
namespace selftest {
+/* Build a constant tree of the given type from STR. */
+
+static tree
+build_real_cst_from_string (tree type, const char *str)
+{
+ REAL_VALUE_TYPE real;
+ real_from_string (&real, str);
+ return build_real (type, real);
+}
+
+/* Append various "interesting" constants to OUT (e.g. NaN). */
+
+static void
+append_interesting_constants (auto_vec<tree> *out)
+{
+ out->safe_push (build_int_cst (integer_type_node, 0));
+ out->safe_push (build_int_cst (integer_type_node, 42));
+ out->safe_push (build_int_cst (unsigned_type_node, 0));
+ out->safe_push (build_int_cst (unsigned_type_node, 42));
+ out->safe_push (build_real_cst_from_string (float_type_node, "QNaN"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "-QNaN"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "SNaN"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "-SNaN"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "0.0"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "-0.0"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "Inf"));
+ out->safe_push (build_real_cst_from_string (float_type_node, "-Inf"));
+}
+
+/* Verify that tree_cmp is a well-behaved comparator for qsort, even
+ if the underlying constants aren't comparable. */
+
+static void
+test_tree_cmp_on_constants ()
+{
+ auto_vec<tree> csts;
+ append_interesting_constants (&csts);
+
+ /* Try sorting every triple. */
+ const unsigned num = csts.length ();
+ for (unsigned i = 0; i < num; i++)
+ for (unsigned j = 0; j < num; j++)
+ for (unsigned k = 0; k < num; k++)
+ {
+ auto_vec<tree> v (3);
+ v.quick_push (csts[i]);
+ v.quick_push (csts[j]);
+ v.quick_push (csts[k]);
+ v.qsort (tree_cmp);
+ }
+}
+
/* Implementation detail of the ASSERT_CONDITION_* macros. */
void
ASSERT_EQ (model0, model1);
}
+/* Verify that we can canonicalize a model containing NaN and other real
+ constants. */
+
+static void
+test_canonicalization_4 ()
+{
+ auto_vec<tree> csts;
+ append_interesting_constants (&csts);
+
+ region_model model;
+
+ unsigned i;
+ tree cst;
+ FOR_EACH_VEC_ELT (csts, i, cst)
+ model.get_rvalue (cst, NULL);
+
+ model.canonicalize (NULL);
+}
+
/* Assert that if we have two region_model instances
with values VAL_A and VAL_B for EXPR that they are
mergable. Write the merged model to *OUT_MERGED_MODEL,
void
analyzer_region_model_cc_tests ()
{
+ test_tree_cmp_on_constants ();
test_dump ();
test_unique_constants ();
test_svalue_equality ();
test_canonicalization_1 ();
test_canonicalization_2 ();
test_canonicalization_3 ();
+ test_canonicalization_4 ();
test_state_merging ();
test_constraint_merging ();
}