diff options
Diffstat (limited to 'gcc/opts.cc')
-rw-r--r-- | gcc/opts.cc | 44 |
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 |