summaryrefslogtreecommitdiff
path: root/gcc/opts.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/opts.cc')
-rw-r--r--gcc/opts.cc44
1 files changed, 44 insertions, 0 deletions
diff --git a/gcc/opts.cc b/gcc/opts.cc
index dfdc4d78389..733f3943871 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3709,12 +3709,56 @@ test_get_option_html_page ()
#endif
}
+/* Verify EnumSet requirements. */
+
+static void
+test_enum_sets ()
+{
+ for (unsigned i = 0; i < cl_options_count; ++i)
+ if (cl_options[i].var_type == CLVC_ENUM && cl_options[i].var_value)
+ {
+ const struct cl_enum *e = &cl_enums[cl_options[i].var_enum];
+ unsigned HOST_WIDE_INT used_sets = 0;
+ unsigned HOST_WIDE_INT mask = 0;
+ unsigned highest_set = 0;
+ for (unsigned j = 0; e->values[j].arg; ++j)
+ {
+ unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
+ /* Test that enumerators referenced in EnumSet have all
+ Set(n) on them within the valid range. */
+ ASSERT_TRUE (set >= 1 && set <= HOST_BITS_PER_WIDE_INT);
+ highest_set = MAX (set, highest_set);
+ used_sets |= HOST_WIDE_INT_1U << (set - 1);
+ }
+ /* If there is just one set, no point to using EnumSet. */
+ ASSERT_TRUE (highest_set >= 2);
+ /* Test that there are no gaps in between the sets. */
+ if (highest_set == HOST_BITS_PER_WIDE_INT)
+ ASSERT_TRUE (used_sets == HOST_WIDE_INT_M1U);
+ else
+ ASSERT_TRUE (used_sets == (HOST_WIDE_INT_1U << highest_set) - 1);
+ for (unsigned int j = 1; j <= highest_set; ++j)
+ {
+ unsigned HOST_WIDE_INT this_mask = 0;
+ for (unsigned k = 0; e->values[k].arg; ++k)
+ {
+ unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
+ if (set == j)
+ this_mask |= e->values[j].value;
+ }
+ ASSERT_TRUE ((mask & this_mask) == 0);
+ mask |= this_mask;
+ }
+ }
+}
+
/* Run all of the selftests within this file. */
void
opts_cc_tests ()
{
test_get_option_html_page ();
+ test_enum_sets ();
}
} // namespace selftest