On Sat, 19 Feb 2022, Qing Zhao wrote: > Hi, > > This is the 2nd patch for fixing pr102276. > > Adding -Wtrivial-auto-var-init and update documentation. > > Adding a new warning option -Wtrivial-auto-var-init to report cases when > -ftrivial-auto-var-init cannot initialize the auto variable. At the same > time, update documentation for -ftrivial-auto-var-init to connect it with > the new warning option -Wtrivial-auto-var-init, and add documentation > for -Wtrivial-auto-var-init. > > Bootstraped and regression tested on both x86 and aarch64. > > Okay for committing? > > thanks. > > Qing. > > ============================== > From 4346890b8f4258489c4841f1992ba3ce816d7689 Mon Sep 17 00:00:00 2001 > From: Qing Zhao <qing.z...@oracle.com> > Date: Fri, 18 Feb 2022 15:53:15 +0000 > Subject: [PATCH 2/2] Adding -Wtrivial-auto-var-init and update documentation. > > Adding a new warning option -Wtrivial-auto-var-init to report cases when > -ftrivial-auto-var-init cannot initialize the auto variable. At the same > time, update documentation for -ftrivial-auto-var-init to connect it with > the new warning option -Wtrivial-auto-var-init, and add documentation > for -Wtrivial-auto-var-init. > > 2022-02-18 Qing Zhao <qing.z...@oracle.com> > gcc/ChangeLog: > > * common.opt (-Wtrivial-auto-var-init): New option. > * doc/invoke.texi (-Wtrivial-auto-var-init): Document new option. > (-ftrivial-auto-var-init): Update option; > * gimplify.cc (maybe_warn_switch_unreachable): Rename... > (maybe_warn_switch_unreachable_and_auto_init): ...to this. > (gimplify_switch_expr): Call new function. > > gcc/testsuite/ChangeLog: > > * gcc.dg/auto-init-pr102276-3.c: New test. > * gcc.dg/auto-init-pr102276-4.c: New test. > --- > gcc/common.opt | 4 + > gcc/doc/invoke.texi | 14 ++- > gcc/gimplify.cc | 100 +++++++++++++++----- > gcc/testsuite/gcc.dg/auto-init-pr102276-3.c | 40 ++++++++ > gcc/testsuite/gcc.dg/auto-init-pr102276-4.c | 40 ++++++++ > 5 files changed, 175 insertions(+), 23 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/auto-init-pr102276-3.c > create mode 100644 gcc/testsuite/gcc.dg/auto-init-pr102276-4.c > > diff --git a/gcc/common.opt b/gcc/common.opt > index c21e5273ae3..22c95dbfa49 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -801,6 +801,10 @@ Wtrampolines > Common Var(warn_trampolines) Warning > Warn whenever a trampoline is generated. > > +Wtrivial-auto-var-init > +Common Var(warn_trivial_auto_var_init) Warning Init(0) > +Warn about where -ftrivial-auto-var-init cannot initialize the auto variable. > +
Warn about cases where ... initialize a variable. > Wtype-limits > Common Var(warn_type_limits) Warning EnabledBy(Wextra) > Warn if a comparison is always true or always false due to the limited range > of the data type. > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index e1a00c80307..c61a5b4b4a5 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -399,7 +399,7 @@ Objective-C and Objective-C++ Dialects}. > -Wswitch -Wno-switch-bool -Wswitch-default -Wswitch-enum @gol > -Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand @gol > -Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs @gol > --Wtsan -Wtype-limits -Wundef @gol > +-Wtrivial-auto-var-init -Wtsan -Wtype-limits -Wundef @gol > -Wuninitialized -Wunknown-pragmas @gol > -Wunsuffixed-float-constants -Wunused @gol > -Wunused-but-set-parameter -Wunused-but-set-variable @gol > @@ -6953,6 +6953,14 @@ This warning is enabled by default for C and C++ > programs. > Warn when @code{__sync_fetch_and_nand} and @code{__sync_nand_and_fetch} > built-in functions are used. These functions changed semantics in GCC 4.4. > > +@item -Wtrivial-auto-var-init > +@opindex Wtrivial-auto-var-init > +@opindex Wno-trivial-auto-var-init > +Warn when @code{-ftrivial-auto-var-init} cannot initialize the automatic > +variable. A common situation is an automatic variable that is declared > +between the controlling expression and the first case lable of a > @code{switch} > +statement. > + > @item -Wunused-but-set-parameter > @opindex Wunused-but-set-parameter > @opindex Wno-unused-but-set-parameter > @@ -12314,6 +12322,10 @@ initializer as uninitialized, > @option{-Wuninitialized} and > warning messages on such automatic variables. > With this option, GCC will also initialize any padding of automatic variables > that have structure or union types to zeroes. > +However, the current implementation cannot initialize automatic variables > that > +are declared between the controlling expression and the first case of a > +@code{switch} statement. Using @option{-Wtrivial-auto-var-init} to report > all > +such cases. > > The three values of @var{choice} are: > > diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc > index 4e3bbf5314d..7e52794691f 100644 > --- a/gcc/gimplify.cc > +++ b/gcc/gimplify.cc > @@ -2079,13 +2079,59 @@ warn_switch_unreachable_r (gimple_stmt_iterator > *gsi_p, bool *handled_ops_p, > return NULL_TREE; > } > > +/* Callback for walk_gimple_seq. */ > + > +static tree > +warn_switch_unreachable_auto_init_r (gimple_stmt_iterator *gsi_p, > + bool *handled_ops_p, > + struct walk_stmt_info *) > +{ > + gimple *stmt = gsi_stmt (*gsi_p); > + > + *handled_ops_p = true; > + switch (gimple_code (stmt)) > + { > + case GIMPLE_TRY: > + case GIMPLE_BIND: > + case GIMPLE_CATCH: > + case GIMPLE_EH_FILTER: > + case GIMPLE_TRANSACTION: > + /* Walk the sub-statements. */ > + *handled_ops_p = false; > + break; > + case GIMPLE_CALL: > + if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT) > + && flag_auto_var_init > AUTO_INIT_UNINITIALIZED) > + { > + /* Get the variable name from the 3rd argument of call. */ > + tree var_name = gimple_call_arg (stmt, 2); > + var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0); > + const char *var_name_str = TREE_STRING_POINTER (var_name); > + > + warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init, > + "%qs cannot be initialized with" > + "%<-ftrivial-auto-var_init%>", > + var_name_str); > + } > + break; > + case GIMPLE_LABEL: > + /* Stop till the first Label. */ > + return integer_zero_node; > + default: > + break; > + } > + return NULL_TREE; > +} > + > /* Possibly warn about unreachable statements between switch's controlling > - expression and the first case. SEQ is the body of a switch expression. > */ > + expression and the first case. Also warn about -ftrivial-auto-var-init > + cannot initialize the auto variable under such situation. > + SEQ is the body of a switch expression. */ > > static void > -maybe_warn_switch_unreachable (gimple_seq seq) > +maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq) > { > - if (!warn_switch_unreachable > + if ((!warn_switch_unreachable && !warn_trivial_auto_var_init) > /* This warning doesn't play well with Fortran when optimizations > are on. */ > || lang_GNU_Fortran () > @@ -2093,26 +2139,36 @@ maybe_warn_switch_unreachable (gimple_seq seq) > return; > > struct walk_stmt_info wi; > - memset (&wi, 0, sizeof (wi)); > - walk_gimple_seq (seq, warn_switch_unreachable_r, NULL, &wi); > - gimple *stmt = (gimple *) wi.info; > > - if (stmt && gimple_code (stmt) != GIMPLE_LABEL) > + if (warn_switch_unreachable) > { > - if (gimple_code (stmt) == GIMPLE_GOTO > - && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL > - && DECL_ARTIFICIAL (gimple_goto_dest (stmt))) > - /* Don't warn for compiler-generated gotos. These occur > - in Duff's devices, for example. */ > - ; > - else if ((flag_auto_var_init > AUTO_INIT_UNINITIALIZED) > - && (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))) > - /* Don't warn for compiler-generated initializations for > - -ftrivial-auto-var-init. */ > - ; > - else > - warning_at (gimple_location (stmt), OPT_Wswitch_unreachable, > - "statement will never be executed"); > + memset (&wi, 0, sizeof (wi)); > + walk_gimple_seq (seq, warn_switch_unreachable_r, NULL, &wi); > + gimple *stmt = (gimple *) wi.info; > + > + if (stmt && gimple_code (stmt) != GIMPLE_LABEL) > + { > + if (gimple_code (stmt) == GIMPLE_GOTO > + && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL > + && DECL_ARTIFICIAL (gimple_goto_dest (stmt))) > + /* Don't warn for compiler-generated gotos. These occur > + in Duff's devices, for example. */ > + ; > + else if ((flag_auto_var_init > AUTO_INIT_UNINITIALIZED) > + && (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))) > + /* Don't warn for compiler-generated initializations for > + -ftrivial-auto-var-init. */ > + ; > + else > + warning_at (gimple_location (stmt), OPT_Wswitch_unreachable, > + "statement will never be executed"); > + } > + } Hmm. I'd re-organize the code to emit both the Wswitch-unreachable and -Wtrivial_auto_var_init diagnostic from the existing warn_switch_unreachable_r callback. You can use wi.info to keep track whether a Wswitch-unreachable diagnostic was already emitted (and if -Wtrivial_auto_var_init is not enabled abort the walk) for example. Thanks, Richard. > + if (warn_trivial_auto_var_init) > + { > + memset (&wi, 0, sizeof (wi)); > + walk_gimple_seq (seq, warn_switch_unreachable_auto_init_r, NULL, &wi); > } > } > > @@ -2646,7 +2702,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) > gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq); > > gimplify_ctxp->in_switch_expr = old_in_switch_expr; > - maybe_warn_switch_unreachable (switch_body_seq); > + maybe_warn_switch_unreachable_and_auto_init (switch_body_seq); > maybe_warn_implicit_fallthrough (switch_body_seq); > /* Only do this for the outermost GIMPLE_SWITCH. */ > if (!gimplify_ctxp->in_switch_expr) > diff --git a/gcc/testsuite/gcc.dg/auto-init-pr102276-3.c > b/gcc/testsuite/gcc.dg/auto-init-pr102276-3.c > new file mode 100644 > index 00000000000..f113f46e29d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/auto-init-pr102276-3.c > @@ -0,0 +1,40 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wtrivial-auto-var-init -ftrivial-auto-var-init=zero" } > */ > + > +int g(int *, int *); > +int f() > +{ > + switch (0) { > + int x; /* { dg-warning "cannot be initialized with" } */ > + int y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g(&x, &y); > + } > +} > + > +int g1(int, int); > +int f1() > +{ > + switch (0) { > + int x; /* { dg-warning "cannot be initialized with" } */ > + int y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g1(x, y); > + } > +} > + > +struct S > +{ > + char a; > + int b; > +}; > +int g2(int); > +int f2(int input) > +{ > + switch (0) { > + struct S x; /* { dg-warning "cannot be initialized with" } */ > + struct S y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g2(input) + x.b + y.b; > + } > +} > diff --git a/gcc/testsuite/gcc.dg/auto-init-pr102276-4.c > b/gcc/testsuite/gcc.dg/auto-init-pr102276-4.c > new file mode 100644 > index 00000000000..662e0d1182e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/auto-init-pr102276-4.c > @@ -0,0 +1,40 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wtrivial-auto-var-init > -ftrivial-auto-var-init=pattern" } */ > + > +int g(int *, int *); > +int f() > +{ > + switch (0) { > + int x; /* { dg-warning "cannot be initialized with" } */ > + int y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g(&x, &y); > + } > +} > + > +int g1(int, int); > +int f1() > +{ > + switch (0) { > + int x; /* { dg-warning "cannot be initialized with" } */ > + int y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g1(x, y); > + } > +} > + > +struct S > +{ > + char a; > + int b; > +}; > +int g2(int); > +int f2(int input) > +{ > + switch (0) { > + struct S x; /* { dg-warning "cannot be initialized with" } */ > + struct S y; /* { dg-warning "cannot be initialized with" } */ > + default: > + return g2(input) + x.b + y.b; > + } > +} > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)