On 12/14/21 9:43 AM, Qing Zhao wrote:
Hi,

On Dec 9, 2021, at 12:13 PM, Qing Zhao via Gcc-patches 
<gcc-patches@gcc.gnu.org> wrote:

+             return;
+
+         /* Get the variable declaration location from the def_stmt.  */
+         var_decl_loc = gimple_location (def_stmt);
+
+         /* The LHS of the call is a temporary variable, we use it as a
+            placeholder to record the information on whether the warning
+            has been issued or not.  */
+         repl_var = gimple_call_lhs (def_stmt);
+       }
     }
-  if (var == NULL_TREE)
+  if (var == NULL_TREE && var_name == NULL_TREE)
     return;
     /* Avoid warning if we've already done so or if the warning has been
@@ -207,36 +245,56 @@ warn_uninit (opt_code opt, tree t, tree var, const char 
*gmsgid,
   if (((warning_suppressed_p (context, OPT_Wuninitialized)
        || (gimple_assign_single_p (context)
            && get_no_uninit_warning (gimple_assign_rhs1 (context)))))
-      || get_no_uninit_warning (var))
+      || (var && get_no_uninit_warning (var))
+      || (repl_var && get_no_uninit_warning (repl_var)))
     return;
     /* Use either the location of the read statement or that of the PHI
      argument, or that of the uninitialized variable, in that order,
      whichever is valid.  */
-  location_t location;
+  location_t location = UNKNOWN_LOCATION;
   if (gimple_has_location (context))
     location = gimple_location (context);
   else if (phi_arg_loc != UNKNOWN_LOCATION)
     location = phi_arg_loc;
-  else
+  else if (var)
     location = DECL_SOURCE_LOCATION (var);
+  else if (var_name)
+    location = var_decl_loc;
+
   location = linemap_resolve_location (line_table, location,
                                       LRK_SPELLING_LOCATION, NULL);
     auto_diagnostic_group d;
-  if (!warning_at (location, opt, gmsgid, var))
+  char *gmsgid_final = XNEWVEC (char, strlen (gmsgid) + 5);
+  gmsgid_final[0] = 0;
+  if (var)
+    strcat (gmsgid_final, "%qD ");
+  else if (var_name)
+    strcat (gmsgid_final, "%qs ");
+  strcat (gmsgid_final, gmsgid);
+
+  if (var && !warning_at (location, opt, gmsgid_final, var))
+    return;
+  else if (var_name && !warning_at (location, opt, gmsgid_final, var_name_str))
     return;

Dynamically creating the string seems quite cumbersome here, and
it leaks the allocated block.  I wonder if it might be better to
remove the gmsgid argument from the function and assign it to
one of the literals based on the other arguments.

Since only one of var and var_name is used, I also wonder if
the %qs form could be used for both to simplify the overall
logic.  (I.e., get the IDENTIFIER_POINTER string from var and
use it instead of %qD).

Looks like that using “%qs” + get the IDENTIFIER_POINTER string from var did 
not work very well for the following testing case:

   1 /* PR tree-optimization/45083 */
   2 /* { dg-do compile } */
   3 /* { dg-options "-O2 -Wuninitialized" } */
   4
   5 struct S { char *a; unsigned b; unsigned c; };
   6 extern int foo (const char *);
   7 extern void bar (int, int);
   8
   9 static void
  10 baz (void)
  11 {
  12   struct S cs[1];       /* { dg-message "was declared here" } */
  13   switch (cs->b)        /* { dg-warning "cs\[^\n\r\]*\\.b\[^\n\r\]*is used 
uninitialized" } */
  14     {
  15     case 101:
  16       if (foo (cs->a))  /* { dg-warning "cs\[^\n\r\]*\\.a\[^\n\r\]*may be used 
uninitialized" } */
  17         bar (cs->c, cs->b);     /* { dg-warning "cs\[^\n\r\]*\\.c\[^\n\r\]*may 
be used uninitialized"     } */
  18     }
  19 }
  20
  21 void
  22 test (void)
  23 {
  24   baz ();
  25 }


For the uninitialized usages at line 13, 16, 17: the IDENTIFIER_POINTER string 
of var are:
cs$0$b, cs$0$a ,cs$0$c

However, with %qD, they are printed as cs[0].b, cs[0].a, cs[0].c
But with %qs, they are printed as cs$0$b, cs$0$a ,cs$0$c.

Looks like that %qD does not simplify print out the IDENTIFIER_POINTER string 
directly, it specially handle it for some cases.

I tried to see how %qD specially handle the strings, but didn’t get it so far.

Do you know where the %qD handle this case specially?

In the front end's pretty printer where it handles %D (e.g.,
for C in c_tree_printer in c/c-objc-common.c).  For VARs with
DECL_HAS_DEBUG_EXPR_P (temp) the code uses DECL_DEBUG_EXPR().

There's also print_generic_expr_to_str(tree) that formats a decl
or an expression to a dynamically allocated string (the string
needs to be freed).

Martin


Thanks.

Qing


Both are good suggestions, I will try to update the code based on this.

Thanks again.

Qing




Reply via email to