From a6ba6e57e862640a1d21710b81a8b62028867245 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 11 Sep 2018 03:44:48 +0100
Subject: [PATCH 08/11] FIXME: hack it all up to show directive sizes via
 labelled ranges

---
 gcc/gimple-ssa-sprintf.c | 86 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 5 deletions(-)

diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 3ffbe5429d1..e772b6d4bf7 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "alloc-pool.h"
 #include "vr-values.h"
 #include "gimple-ssa-evrp-analyze.h"
+#include "gcc-rich-location.h"
 
 /* The likely worst case value of MB_LEN_MAX for the target, large enough
    for UTF-8.  Ideally, this would be obtained by a target hook if it were
@@ -2422,7 +2423,12 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
   if (!should_warn_p (info, avail_range, res))
     return false;
 
+
+  // FIXME:
+  return true;
+
   /* A warning will definitely be issued below.  */
+  
 
   /* The maximum byte count to reference in the warning.  Larger counts
      imply that the upper bound is unknown (and could be anywhere between
@@ -2706,7 +2712,9 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
 static bool
 format_directive (const sprintf_dom_walker::call_info &info,
 		  format_result *res, const directive &dir,
-		  class vr_values *vr_values)
+		  class vr_values *vr_values,
+		  location_t *out_dir_loc,
+		  fmtresult *out_fmtres)
 {
   /* Offset of the beginning of the directive from the beginning
      of the format string.  */
@@ -2718,6 +2726,8 @@ format_directive (const sprintf_dom_walker::call_info &info,
      specifier.  */
   substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
 			offset, start, length);
+  if (out_dir_loc)
+    dirloc.get_location (out_dir_loc);
 
   /* Also get the location of the argument if possible.
      This doesn't work for integer literals or function calls.  */
@@ -2733,6 +2743,9 @@ format_directive (const sprintf_dom_walker::call_info &info,
   /* Compute the range of lengths of the formatted output.  */
   fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values);
 
+  if (out_fmtres)
+    *out_fmtres = fmtres;
+
   /* Record whether the output of all directives is known to be
      bounded by some maximum, implying that their arguments are
      either known exactly or determined to be in a known range
@@ -3416,6 +3429,59 @@ parse_directive (sprintf_dom_walker::call_info &info,
   return dir.len;
 }
 
+class buffer_range_label : public range_label
+{
+ public:
+  label_text get_text () const FINAL OVERRIDE
+  {
+    return label_text (const_cast <char *> ("capacity: FIXME"), false);
+  }
+
+ private:
+  const char *m_text;
+};
+
+class directive_range_label : public range_label
+{
+ public:
+  directive_range_label (fmtresult fmtres) : m_fmtres (fmtres) {}
+
+  label_text get_text () const FINAL OVERRIDE
+  {
+    pretty_printer pp;
+    pp_printf (&pp, "FIXME: min: %wu max: %wu",
+	       m_fmtres.range.min,
+	       m_fmtres.range.max);
+    return label_text (xstrdup (pp_formatted_text (&pp)), true);
+  }
+
+ private:
+  fmtresult m_fmtres;
+};
+
+/* FIXME.  */
+
+class format_result_t : public gcc_rich_location
+{
+ public:
+  format_result_t (location_t loc_of_dest)
+    : gcc_rich_location (loc_of_dest)
+  {
+  }
+
+  ~format_result_t () { /* FIXME.  */ }
+  
+  void add_directive_location (location_t dir_loc, fmtresult fmtres)
+  {
+    directive_range_label *label = new directive_range_label (fmtres);
+    m_directive_labels.safe_push (label);
+    add_range (dir_loc, SHOW_RANGE_WITHOUT_CARET, label);
+  }
+
+  buffer_range_label m_buffer_label;
+  auto_vec<directive_range_label *> m_directive_labels;
+};
+
 /* Compute the length of the output resulting from the call to a formatted
    output function described by INFO and store the result of the call in
    *RES.  Issue warnings for detected past the end writes.  Return true
@@ -3427,9 +3493,9 @@ bool
 sprintf_dom_walker::compute_format_length (call_info &info,
 					   format_result *res)
 {
+  location_t callloc = gimple_location (info.callstmt);
   if (dump_file)
     {
-      location_t callloc = gimple_location (info.callstmt);
       fprintf (dump_file, "%s:%i: ",
 	       LOCATION_FILE (callloc), LOCATION_LINE (callloc));
       print_generic_expr (dump_file, info.func, dump_flags);
@@ -3457,6 +3523,8 @@ sprintf_dom_walker::compute_format_length (call_info &info,
   /* The variadic argument counter.  */
   unsigned argno = info.argidx;
 
+  format_result_t rich_loc (get_start (callloc)); // FIXME
+
   for (const char *pf = info.fmtstr; ; ++dirno)
     {
       directive dir = directive ();
@@ -3465,21 +3533,29 @@ sprintf_dom_walker::compute_format_length (call_info &info,
       size_t n = parse_directive (info, dir, res, pf, &argno,
 				  evrp_range_analyzer.get_vr_values ());
 
+      location_t dir_loc = UNKNOWN_LOCATION;
+      fmtresult fmtres;
+	
       /* Return failure if the format function fails.  */
       if (!format_directive (info, res, dir,
-			     evrp_range_analyzer.get_vr_values ()))
-	return false;
+			     evrp_range_analyzer.get_vr_values (),
+			     &dir_loc, &fmtres))
+	; // return false;
+      if (dir_loc != UNKNOWN_LOCATION)
+	rich_loc.add_directive_location (dir_loc, fmtres);
 
       /* Return success the directive is zero bytes long and it's
 	 the last think in the format string (i.e., it's the terminating
 	 nul, which isn't really a directive but handling it as one makes
 	 things simpler).  */
       if (!n)
-	return *pf == '\0';
+	break; // return *pf == '\0';
 
       pf += n;
     }
 
+  inform (&rich_loc, "FIXME: rich loc here");
+
   /* The complete format string was processed (with or without warnings).  */
   return true;
 }
-- 
2.13.6

