Qing Zhao <qing.z...@oracle.com> writes:

> Control this with a new option -fdiagnostics-details.

It would be useful to be also able to print the inline call stack,
maybe with a separate option.

In some array bounds cases I looked at the problem was hidden in some inlines
and it wasn't trivial to figure it out.

I wrote this patch for it at some point.


    Print inline stack for warn access warnings
    
    The warnings reported by gimple-ssa-warn-access often depend on the
    caller with inlining, and when there are a lot of callers it can be
    difficult to figure out which caller triggered a warning.
    
    Print the function context including inline stack for these
    warnings.
    
    gcc/ChangeLog:
    
            * gimple-ssa-warn-access.cc (maybe_inform_function): New
            function to report function context.
            (warn_string_no_nul): Use maybe_inform_function.
            (maybe_warn_nonstring_arg): Dito.
            (maybe_warn_for_bound): Dito.
            (warn_for_access): Dito.
            (check_access): Dito.
            (warn_dealloc_offset): Dito.
            (maybe_warn_alloc_args_overflow): Dito.
            (pass_waccess::check_strncat): Dito.
            (pass_waccess::maybe_check_access_sizes): Dito.
            (pass_waccess::maybe_check_dealloc_call): Dito.
            (pass_waccess::warn_invalid_pointer): Dito.
            (maybe_warn_mismatched_realloc): Dito.
            (pass_waccess::check_dangling_stores): Dito.
            (pass_waccess::execute): Reset last_function variable.

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 61f9f0f3d310..94c043531988 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -125,6 +125,21 @@ call_arg (tree expr, unsigned argno)
   return CALL_EXPR_ARG (expr, argno);
 }
 
+/* Already printed inform for the function.  */
+static bool printed_function;
+
+/* Inform about the function stack unless warning is suppressed at LOC
+   with opt code OPT.  */
+static void
+maybe_inform_function (location_t loc, int opt)
+{
+  if (printed_function)
+    return;
+  printed_function = true;
+  if (!warning_suppressed_at (loc, (opt_code)opt))
+    inform (DECL_SOURCE_LOCATION (cfun->decl), "in function %qD", cfun->decl);
+}
+
 /* For a call EXPR at LOC to a function FNAME that expects a string
    in the argument ARG, issue a diagnostic due to it being a called
    with an argument that is a character array with no terminating
@@ -162,6 +177,8 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, 
const char *fname,
 
   auto_diagnostic_group d;
 
+  maybe_inform_function (loc, opt);
+
   const tree maxobjsize = max_object_size ();
   const wide_int maxsiz = wi::to_wide (maxobjsize);
   if (expr)
@@ -485,6 +502,7 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
       if (tree_int_cst_lt (maxobjsize, bndrng[0]))
        {
          bool warned = false;
+         maybe_inform_function (loc, OPT_Wstringop_overread);
          if (tree_int_cst_equal (bndrng[0], bndrng[1]))
            warned = warning_at (loc, OPT_Wstringop_overread,
                                 "%qD specified bound %E "
@@ -638,6 +656,7 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
       auto_diagnostic_group d;
       if (wi::ltu_p (asize, wibnd))
        {
+         maybe_inform_function (loc, OPT_Wstringop_overread);
          if (bndrng[0] == bndrng[1])
            warned = warning_at (loc, OPT_Wstringop_overread,
                                 "%qD argument %i declared attribute "
@@ -723,6 +742,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
       auto_diagnostic_group d;
       if (tree_int_cst_lt (maxobjsize, bndrng[0]))
        {
+         maybe_inform_function (loc, opt);
          if (bndrng[0] == bndrng[1])
            warned = (func
                      ? warning_at (loc, opt,
@@ -760,7 +780,9 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
       else if (!size || tree_int_cst_le (bndrng[0], size))
        return false;
       else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
-       warned = (func
+       {
+         maybe_inform_function (loc, opt);
+         warned = (func
                  ? warning_at (loc, opt,
                                (maybe
                                 ? G_("%qD specified bound %E may exceed "
@@ -775,8 +797,11 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                                 : G_("specified bound %E exceeds "
                                      "source size %E")),
                                bndrng[0], size));
+       }
       else
-       warned = (func
+       {
+         maybe_inform_function (loc, opt);
+         warned = (func
                  ? warning_at (loc, opt,
                                (maybe
                                 ? G_("%qD specified bound [%E, %E] may "
@@ -791,6 +816,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                                 : G_("specified bound [%E, %E] exceeds "
                                      "source size %E")),
                                bndrng[0], bndrng[1], size));
+       }
       if (warned)
        {
          if (pad && pad->src.ref
@@ -816,7 +842,9 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
   if (tree_int_cst_lt (maxobjsize, bndrng[0]))
     {
       if (bndrng[0] == bndrng[1])
-       warned = (func
+       {
+         maybe_inform_function (loc, opt);
+         warned = (func
                  ? warning_at (loc, opt,
                                (maybe
                                 ? G_("%qD specified size %E may "
@@ -831,8 +859,11 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                                 : G_("specified size %E exceeds "
                                      "maximum object size %E")),
                                bndrng[0], maxobjsize));
+       }
       else
-       warned = (func
+       {
+         maybe_inform_function (loc, opt);
+         warned = (func
                  ? warning_at (loc, opt,
                                (maybe
                                 ? G_("%qD specified size between %E and %E "
@@ -847,11 +878,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                                 : G_("specified size between %E and %E "
                                      "exceeds maximum object size %E")),
                                bndrng[0], bndrng[1], maxobjsize));
+      }
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
-    warned = (func
+    {
+      maybe_inform_function (loc, opt);
+      warned = (func
              ? warning_at (loc, opt,
                            (maybe
                             ? G_("%qD specified bound %E may exceed "
@@ -866,8 +900,11 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                             : G_("specified bound %E exceeds "
                                  "destination size %E")),
                            bndrng[0], size));
+    }
   else
-    warned = (func
+    {
+      maybe_inform_function (loc, opt);
+      warned = (func
              ? warning_at (loc, opt,
                            (maybe
                             ? G_("%qD specified bound [%E, %E] may exceed "
@@ -882,6 +919,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, 
GimpleOrTree exp, tree func,
                             : G_("specified bound [%E, %E] exceeds "
                                  "destination size %E")),
                            bndrng[0], bndrng[1], size));
+    }
 
   if (warned)
     {
@@ -928,6 +966,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree 
exp, int opt,
 
   if (write && read)
     {
+      maybe_inform_function (loc, opt);
       if (tree_int_cst_equal (range[0], range[1]))
        warned = (func
                  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
@@ -994,6 +1033,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree 
exp, int opt,
 
   if (write)
     {
+      maybe_inform_function (loc, opt);
       if (tree_int_cst_equal (range[0], range[1]))
        warned = (func
                  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
@@ -1064,6 +1104,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree 
exp, int opt,
 
   if (read)
     {
+      maybe_inform_function (loc, OPT_Wstringop_overread);
       if (tree_int_cst_equal (range[0], range[1]))
        warned = (func
                  ? warning_n (loc, OPT_Wstringop_overread,
@@ -1134,6 +1175,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree 
exp, int opt,
       return warned;
     }
 
+  maybe_inform_function (loc, OPT_Wstringop_overread);
   if (tree_int_cst_equal (range[0], range[1])
       || tree_int_cst_sign_bit (range[1]))
     warned = (func
@@ -1400,6 +1442,7 @@ check_access (GimpleOrTree exp, tree dstwrite,
          bool warned = false;
          if (dstwrite == slen && at_least_one)
            {
+             maybe_inform_function (loc, opt);
              /* This is a call to strcpy with a destination of 0 size
                 and a source of unknown length.  The call will write
                 at least one byte past the end of the destination.  */
@@ -2046,6 +2089,7 @@ warn_dealloc_offset (location_t loc, gimple *call, const 
access_ref &aref)
     }
 
   auto_diagnostic_group d;
+  maybe_inform_function (loc, OPT_Wfree_nonheap_object);
   if (!warning_at (loc, OPT_Wfree_nonheap_object,
                   "%qD called on pointer %qE with nonzero offset%s",
                   dealloc_decl, aref.ref, offstr))
@@ -2273,6 +2317,7 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree 
args[2],
 
          if (tree_int_cst_lt (args[i], integer_zero_node))
            {
+             maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
              warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                                   "argument %i value %qE is negative",
                                   idx[i] + 1, args[i]);
@@ -2290,9 +2335,12 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree 
args[2],
                  ? IDENTIFIER_LENGTH (DECL_NAME (fn)) != 6
                  : !lookup_attribute ("returns_nonnull",
                                       TYPE_ATTRIBUTES (fntype)))
-               warned = warning_at (loc, OPT_Walloc_zero,
+               {
+                 maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
+                 warned = warning_at (loc, OPT_Walloc_zero,
                                     "argument %i value is zero",
                                     idx[i] + 1);
+               }
            }
          else if (tree_int_cst_lt (maxobjsize, args[i]))
            {
@@ -2308,6 +2356,7 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree 
args[2],
                  && integer_all_onesp (args[i]))
                continue;
 
+             maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
              warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                                   "argument %i value %qE exceeds "
                                   "maximum object size %E",
@@ -2322,6 +2371,7 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree 
args[2],
          if (tree_int_cst_lt (argrange[i][0], integer_zero_node)
              && tree_int_cst_le (argrange[i][1], integer_zero_node))
            {
+             maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
              warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                                   "argument %i range [%E, %E] is negative",
                                   idx[i] + 1,
@@ -2329,6 +2379,7 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const tree 
args[2],
            }
          else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
            {
+             maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
              warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                                   "argument %i range [%E, %E] exceeds "
                                   "maximum object size %E",
@@ -2359,18 +2410,24 @@ maybe_warn_alloc_args_overflow (gimple *stmt, const 
tree args[2],
       wide_int prod = wi::umul (x, y, &vflow);
 
       if (vflow)
-       warned = warning_at (loc, OPT_Walloc_size_larger_than_,
+       {
+         maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
+         warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                             "product %<%E * %E%> of arguments %i and %i "
                             "exceeds %<SIZE_MAX%>",
                             argrange[0][0], argrange[1][0],
                             idx[0] + 1, idx[1] + 1);
+       }
       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
-       warned = warning_at (loc, OPT_Walloc_size_larger_than_,
+       {
+         maybe_inform_function (loc, OPT_Walloc_size_larger_than_);
+         warned = warning_at (loc, OPT_Walloc_size_larger_than_,
                             "product %<%E * %E%> of arguments %i and %i "
                             "exceeds maximum object size %E",
                             argrange[0][0], argrange[1][0],
                             idx[0] + 1, idx[1] + 1,
                             maxobjsize);
+       }
 
       if (warned)
        {
@@ -2563,6 +2620,7 @@ pass_waccess::check_strncat (gcall *stmt)
       && tree_int_cst_equal (destsize, maxread))
     {
       location_t loc = get_location (stmt);
+      maybe_inform_function (loc, OPT_Wstringop_overflow_);
       warning_at (loc, OPT_Wstringop_overflow_,
                  "%qD specified bound %E equals destination size",
                  get_callee_fndecl (stmt), maxread);
@@ -3454,6 +3512,7 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, 
tree fndecl, tree fntype,
              const std::string argtypestr
                = access.second.array_as_string (ptrtype);
 
+             maybe_inform_function (loc, OPT_Wstringop_overflow_);
              if (warning_at (loc, OPT_Wstringop_overflow_,
                              "bound argument %i value %s is "
                              "negative for a variable length array "
@@ -3508,6 +3567,7 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, 
tree fndecl, tree fntype,
                 different from also declaring the pointer argument with
                 attribute nonnull when the function accepts null pointers
                 only when the corresponding size is zero.  */
+             maybe_inform_function (loc, OPT_Wnonnull);
              if (warning_at (loc, OPT_Wnonnull,
                                   "argument %i is null but "
                                   "the corresponding size argument "
@@ -3706,6 +3766,7 @@ pass_waccess::maybe_check_dealloc_call (gcall *call)
       if (aref.ref_declared ())
        {
          auto_diagnostic_group d;
+         maybe_inform_function (loc, OPT_Wfree_nonheap_object);
          if (warning_at (loc, OPT_Wfree_nonheap_object,
                          "%qD called on unallocated object %qD",
                          dealloc_decl, ref))
@@ -3725,6 +3786,7 @@ pass_waccess::maybe_check_dealloc_call (gcall *call)
   else if (CONSTANT_CLASS_P (ref))
     {
       auto_diagnostic_group d;
+      maybe_inform_function (loc, OPT_Wfree_nonheap_object);
       if (warning_at (loc, OPT_Wfree_nonheap_object,
                      "%qD called on a pointer to an unallocated "
                      "object %qE", dealloc_decl, ref))
@@ -3767,6 +3829,7 @@ pass_waccess::maybe_check_dealloc_call (gcall *call)
                     || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
                     ? OPT_Wmismatched_new_delete
                     : OPT_Wmismatched_dealloc);
+                 maybe_inform_function (loc, opt);
                  warned = warning_at (loc, opt,
                                       "%qD called on pointer returned "
                                       "from a mismatched allocation "
@@ -3776,10 +3839,13 @@ pass_waccess::maybe_check_dealloc_call (gcall *call)
          else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
                   || gimple_call_builtin_p (def_stmt,
                                             BUILT_IN_ALLOCA_WITH_ALIGN))
-           warned = warning_at (loc, OPT_Wfree_nonheap_object,
+           {
+             maybe_inform_function (loc, OPT_Wfree_nonheap_object);
+             warned = warning_at (loc, OPT_Wfree_nonheap_object,
                                 "%qD called on pointer to "
                                 "an unallocated object",
                                 dealloc_decl);
+           }
          else if (warn_dealloc_offset (loc, call, aref))
            return;
 
@@ -3923,6 +3989,7 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple 
*use_stmt,
       const tree inval_decl = gimple_call_fndecl (inval_stmt);
 
       auto_diagnostic_group d;
+      maybe_inform_function (use_loc, OPT_Wuse_after_free);
       if ((ref && warning_at (use_loc, OPT_Wuse_after_free,
                              (maybe
                               ? G_("pointer %qE may be used after %qD")
@@ -3949,6 +4016,7 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple 
*use_stmt,
   if (DECL_NAME (var))
     {
       auto_diagnostic_group d;
+      maybe_inform_function (use_loc, OPT_Wdangling_pointer_);
       if ((ref
           && warning_at (use_loc, OPT_Wdangling_pointer_,
                          (maybe
@@ -3967,6 +4035,7 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple 
*use_stmt,
       return;
     }
 
+  maybe_inform_function (use_loc, OPT_Wdangling_pointer_);
   if ((ref
        && warning_at (use_loc, OPT_Wdangling_pointer_,
                      (maybe
@@ -4073,6 +4142,7 @@ maybe_warn_mismatched_realloc (tree ptr, gimple 
*realloc_stmt, gimple *stmt)
   location_t loc = gimple_location (stmt);
   tree realloc_decl = gimple_call_fndecl (realloc_stmt);
   tree dealloc_decl = gimple_call_fndecl (stmt);
+  maybe_inform_function (loc, OPT_Wmismatched_dealloc);
   if (ptr && !warning_at (loc, OPT_Wmismatched_dealloc,
                          "%qD called on pointer %qE passed to mismatched "
                          "allocation function %qD",
@@ -4603,6 +4673,7 @@ pass_waccess::check_dangling_stores (basic_block bb,
 
       auto_diagnostic_group d;
       location_t loc = gimple_location (stmt);
+      maybe_inform_function (loc, OPT_Wdangling_pointer_);
       if (warning_at (loc, OPT_Wdangling_pointer_,
                      "storing the address of local variable %qD in %qE",
                      rhs_ref.ref, lhs))
@@ -4750,6 +4821,7 @@ pass_waccess::check_call_dangling (gcall *call)
 unsigned
 pass_waccess::execute (function *fun)
 {
+  printed_function = false;
   calculate_dominance_info (CDI_DOMINATORS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
 



-Andi

Reply via email to