On 3/19/20 10:09 AM, Jakub Jelinek wrote:
I mean, optimize for the !flag_checking case...

Sure, I transformed both situations into heap memory allocation.
In gcc/c-family/c-attribs.c I faced maybe uninitialized warning when
I only assigned (and checked) the variable in flag_checking context.

Martin
>From a336c110cbefda2a1febddc56e0fd8289bb08c94 Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Tue, 10 Dec 2019 19:41:08 +0100
Subject: [PATCH] Add gcc_assert that &global_options are not dirty modified.

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 | 12 ++++++++++++
 gcc/c-family/c-pragma.c  | 11 +++++++++++
 gcc/opth-gen.awk         | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 9abf81d0248..4ac44128407 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -4448,6 +4448,13 @@ 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 = NULL;
+      if (flag_checking)
+	{
+	  saved_global_options = (gcc_options *) xmalloc (sizeof (gcc_options));
+	  *saved_global_options = global_options;
+	}
+
       if (old_opts)
 	cl_optimization_restore (&global_options,
 				 TREE_OPTIMIZATION (old_opts));
@@ -4459,6 +4466,11 @@ handle_optimize_attribute (tree *node, tree name, tree args,
 
       /* Restore current options.  */
       cl_optimization_restore (&global_options, &cur_opts);
+      if (saved_global_options != NULL)
+	{
+	  gcc_assert (gcc_options_check (saved_global_options, &global_options));
+	  free (saved_global_options);
+	}
     }
 
   return NULL_TREE;
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 7c35741745b..94a1c486fc1 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,11 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
   options_stack = p;
 
   /* Save optimization and target flags in binary format.  */
+  if (flag_checking)
+    {
+      p->saved_global_options = (gcc_options *) xmalloc (sizeof (gcc_options));
+      *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 +1085,11 @@ 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));
+      free (p->saved_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.
 
-- 
2.25.1

Reply via email to