> On Feb 24, 2022, at 4:16 AM, Richard Biener <rguent...@suse.de> wrote:
>
> 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.
Okay.
>
>> 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.
Okay. Will try this.
A question here: for the current -Wswitch-unreachable, the warning will be emit
only once for the first unreachable stmt.
Shall we emit warning for each unreachable stmt instead?
thanks.
Qing
>
> 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)