[Bug middle-end/115913] [11/12/13/14/15 Regression] ICE with pragma GCC pop_options with diagnostic since r11-1141
lhyatt at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Jul 18 21:47:03 GMT 2024
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115913
Lewis Hyatt <lhyatt at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |lhyatt at gcc dot gnu.org,
| |marxin at gcc dot gnu.org
Summary|[11/12/13/14/15 Regression] |[11/12/13/14/15 Regression]
|ICE with pragma GCC |ICE with pragma GCC
|pop_options with diagnostic |pop_options with diagnostic
| |since r11-1141
See Also| |https://gcc.gnu.org/bugzill
| |a/show_bug.cgi?id=92860
--- Comment #6 from Lewis Hyatt <lhyatt at gcc dot gnu.org> ---
Started with r11-1141 (which added the checking assert in the first place). I
think this check is ensuring that after this sequence:
#pragma GCC push_options
#pragma GCC optimize ...
#pragma GCC pop_options
all the options have been restored to their previous values. But it doesn't
consider that the options might have been deliberately changed by another
pragma, in which case they are not expected to retain their previous values.
I think the fix in the spirit of this check is to disable the check while a
diagnostic pragma is in force. This untested patch resolves it that way, if the
approach seems reasonable I could prepare it?
diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc
index 25251c2b69f..0080bac99bf 100644
--- a/gcc/c-family/c-pragma.cc
+++ b/gcc/c-family/c-pragma.cc
@@ -866,6 +866,9 @@ pragma_diagnostic_lex (pragma_diagnostic_data *result)
result->valid = true;
}
+static void
+options_stack_disable_checking ();
+
/* Handle #pragma GCC diagnostic. Early mode is used by frontends (such as
C++)
that do not process the deferred pragma while they are consuming tokens;
they
can use early mode to make sure diagnostics affecting the preprocessor
itself
@@ -1020,6 +1023,7 @@ handle_pragma_diagnostic_impl ()
input_location, lang_mask, &handlers,
&global_options, &global_options_set,
global_dc);
+ options_stack_disable_checking ();
}
static void
@@ -1192,10 +1196,18 @@ struct GTY(()) opt_stack {
tree optimize_binary;
tree optimize_strings;
gcc_options * GTY ((skip)) saved_global_options;
+ bool disable_checking;
};
static GTY(()) struct opt_stack * options_stack;
+static void
+options_stack_disable_checking ()
+{
+ if (options_stack)
+ options_stack->disable_checking = true;
+}
+
/* Handle #pragma GCC push_options to save the current target and optimization
options. */
@@ -1212,7 +1224,7 @@ handle_pragma_push_options (cpp_reader *)
return;
}
- opt_stack *p = ggc_alloc<opt_stack> ();
+ opt_stack *p = ggc_cleared_alloc<opt_stack> ();
p->prev = options_stack;
options_stack = p;
@@ -1260,6 +1272,14 @@ handle_pragma_pop_options (cpp_reader *)
p = options_stack;
options_stack = p->prev;
+ if (flag_checking && p->disable_checking)
+ {
+ XDELETEVEC (p->saved_global_options);
+ p->saved_global_options = nullptr;
+ if (p->prev)
+ p->prev->disable_checking = true;
+ }
+
if (p->target_binary != target_option_current_node)
{
(void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
@@ -1279,7 +1299,7 @@ handle_pragma_pop_options (cpp_reader *)
p->optimize_binary);
optimization_current_node = p->optimize_binary;
}
- if (flag_checking && !seen_error ())
+ if (flag_checking && p->saved_global_options && !seen_error ())
{
cl_optimization_compare (p->saved_global_options, &global_options);
free (p->saved_global_options);
More information about the Gcc-bugs
mailing list