Hi. As seen in the mentioned PR we do have issues related to modification of global_options in context of #pragma GCC optimize/target and the corresponding function attributes. The patch brings a sanity check that these context related option modifications should not affect global state. The patch lists known limitations (mentioned in the PR).
So far I bootstrapped and tested the patch on x86_64-linux-gnu and ppc64le-linux-gnu. I'm planning to work on the problematic options in next stage1 and this patch will help me to catch another violations. Ready to be installed in next stage1? Thanks, Martin gcc/ChangeLog: 2020-03-17 Martin Liska <mli...@suse.cz> PR tree-optimization/92860 * opth-gen.awk: Generate new function gcc_options_check. Include known exceptions. gcc/c-family/ChangeLog: 2020-03-17 Martin Liska <mli...@suse.cz> PR tree-optimization/92860 * c-attribs.c (handle_optimize_attribute): Save global options before parsing of an optimization attribute. * c-pragma.c (opt_stack): Add saved_global_options field. (handle_pragma_push_options): Save current global_options. (handle_pragma_pop_options): Check current options. --- gcc/c-family/c-attribs.c | 3 +++ gcc/c-family/c-pragma.c | 4 ++++ gcc/opth-gen.awk | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+)
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 9abf81d0248..c99b1256186 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -4448,6 +4448,7 @@ handle_optimize_attribute (tree *node, tree name, tree args, /* If we previously had some optimization options, use them as the default. */ + gcc_options saved_global_options = global_options; if (old_opts) cl_optimization_restore (&global_options, TREE_OPTIMIZATION (old_opts)); @@ -4459,6 +4460,8 @@ handle_optimize_attribute (tree *node, tree name, tree args, /* Restore current options. */ cl_optimization_restore (&global_options, &cur_opts); + if (flag_checking) + gcc_assert (gcc_options_check (&saved_global_options, &global_options)); } return NULL_TREE; diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 7c35741745b..8b3b4f218ba 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1003,6 +1003,7 @@ struct GTY(()) opt_stack { tree target_strings; tree optimize_binary; tree optimize_strings; + gcc_options saved_global_options; }; static GTY(()) struct opt_stack * options_stack; @@ -1028,6 +1029,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy)) options_stack = p; /* Save optimization and target flags in binary format. */ + p->saved_global_options = global_options; p->optimize_binary = build_optimization_node (&global_options); p->target_binary = build_target_option_node (&global_options); @@ -1079,6 +1081,8 @@ handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) p->optimize_binary); optimization_current_node = p->optimize_binary; } + if (flag_checking) + gcc_assert (gcc_options_check (&p->saved_global_options, &global_options)); current_target_pragma = p->target_strings; current_optimize_pragma = p->optimize_strings; diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk index 856a69168a5..586213da3d3 100644 --- a/gcc/opth-gen.awk +++ b/gcc/opth-gen.awk @@ -119,6 +119,41 @@ print "#endif" print "#endif" print "" +print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)" +print "#ifndef GENERATOR_FILE" +print "static inline bool gcc_options_check (gcc_options *ptr1, gcc_options *ptr2)" +print "{" +print " bool result = true;" + +# all these options are mentioned in PR92860 +checked_options["flag_merge_constants"]++ +checked_options["param_max_fields_for_field_sensitive"]++ +checked_options["flag_omit_frame_pointer"]++ +checked_options["unroll_only_small_loops"]++ + +for (i = 0; i < n_opts; i++) { + name = var_name(flags[i]); + if (name == "") + continue; + + if (name in checked_options) + continue; + checked_options[name]++ + + print " if (ptr1->x_" name " != ptr2->x_" name ")" + print " {" + print " if (result)" + print " fprintf (stderr, \"Error: global_options are modified in local context:\\n\");" + print " fprintf (stderr, \" " name " (%ld/%ld)\\n\", (long int)ptr1->x_" name ", (long int)ptr2->x_" name ");" + print " result = false;" + print " }" +} + +print " return result;" +print "}" +print "#endif" +print "#endif" + # All of the optimization switches gathered together so they can be saved and restored. # This will allow attribute((cold)) to turn on space optimization.