From f8d165baee38c7e7fdacda8713fd775577450fff Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 15 Aug 2018 12:05:37 -0400
Subject: [PATCH 48/49] FIXME: c-indentation.c: experiments with a class
 visual_column_t

---
 gcc/c-family/c-indentation.c | 158 ++++++++++++++++++++++++++++++-------------
 1 file changed, 110 insertions(+), 48 deletions(-)

diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
index cff5aec..b63ccea 100644
--- a/gcc/c-family/c-indentation.c
+++ b/gcc/c-family/c-indentation.c
@@ -25,15 +25,67 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-indentation.h"
 #include "selftest.h"
 
+#if 0
+/* FIXME.  */
+
+class indentation_checker
+{
+ public:
+ private:
+  unsigned int m_tab_width;
+};
+#endif
+
+/* A 0-based column, respecting tabs (as opposed to libcpp's notion
+   of column, which is a 1-based char count).  */
+
+class visual_column_t
+{
+ public:
+  visual_column_t next_tab_stop (unsigned int tab_width) const;
+
+  //private:
+  visual_column_t () {}
+  visual_column_t (unsigned int value) : m_value (value) {}
+
+  bool operator< (visual_column_t other)
+  {
+    return m_value < other.m_value;
+  }
+  bool operator<= (visual_column_t other)
+  {
+    return m_value <= other.m_value;
+  }
+  bool operator> (visual_column_t other)
+  {
+    return m_value > other.m_value;
+  }
+
+  bool operator== (visual_column_t other)
+  {
+    return m_value == other.m_value;
+  }
+
+  bool operator!= (visual_column_t other)
+  {
+    return m_value == other.m_value;
+  }
+
+  //private:
+  unsigned int m_value;
+};
+
+/* FIXME.  */
+
 extern cpp_options *cpp_opts;
 
 /* Round up VIS_COLUMN to nearest tab stop. */
 
-static unsigned int
-next_tab_stop (unsigned int vis_column, unsigned int tab_width)
+visual_column_t
+visual_column_t::next_tab_stop (unsigned int tab_width) const
 {
-  vis_column = ((vis_column + tab_width) / tab_width) * tab_width;
-  return vis_column;
+  unsigned int new_value = ((m_value + tab_width) / tab_width) * tab_width;
+  return visual_column_t (new_value);
 }
 
 /* Convert libcpp's notion of a column (a 1-based char count) to
@@ -47,8 +99,8 @@ next_tab_stop (unsigned int vis_column, unsigned int tab_width)
 
 static bool
 get_visual_column (expanded_location exploc, location_t loc,
-		   unsigned int *out,
-		   unsigned int *first_nws,
+		   visual_column_t *out,
+		   visual_column_t *first_nws,
 		   unsigned int tab_width)
 {
   /* PR c++/68819: if the column number is zero, we presumably
@@ -76,27 +128,27 @@ get_visual_column (expanded_location exploc, location_t loc,
     return false;
   if ((size_t)exploc.column > line.length ())
     return false;
-  unsigned int vis_column = 0;
+  visual_column_t result (0);
   for (int i = 1; i < exploc.column; i++)
     {
       unsigned char ch = line[i - 1];
 
       if (first_nws != NULL && !ISSPACE (ch))
 	{
-	  *first_nws = vis_column;
+	  *first_nws = result;
 	  first_nws = NULL;
 	}
 
       if (ch == '\t')
-	vis_column = next_tab_stop (vis_column, tab_width);
+	result = result.next_tab_stop (tab_width);
       else
-       vis_column++;
+	result.m_value++;
     }
 
   if (first_nws != NULL)
-    *first_nws = vis_column;
+    *first_nws = result;
 
-  *out = vis_column;
+  *out = result;
   return true;
 }
 
@@ -109,7 +161,7 @@ get_visual_column (expanded_location exploc, location_t loc,
 
 static bool
 get_first_nws_vis_column (const char *file, int line_num,
-			  unsigned int *first_nws,
+			  visual_column_t *first_nws,
 			  unsigned int tab_width)
 {
   gcc_assert (first_nws);
@@ -117,21 +169,21 @@ get_first_nws_vis_column (const char *file, int line_num,
   char_span line = location_get_source_line (file, line_num);
   if (!line)
     return false;
-  unsigned int vis_column = 0;
+  visual_column_t result (0);
   for (size_t i = 1; i < line.length (); i++)
     {
       unsigned char ch = line[i - 1];
 
       if (!ISSPACE (ch))
 	{
-	  *first_nws = vis_column;
+	  *first_nws = result;
 	  return true;
 	}
 
       if (ch == '\t')
-	vis_column = next_tab_stop (vis_column, tab_width);
+	result = result.next_tab_stop (tab_width);
       else
-	vis_column++;
+	result.m_value++;
     }
 
   /* No non-whitespace characters found.  */
@@ -182,7 +234,7 @@ static bool
 detect_intervening_unindent (const char *file,
 			     int body_line,
 			     int next_stmt_line,
-			     unsigned int vis_column,
+			     visual_column_t vis_column,
 			     unsigned int tab_width)
 {
   gcc_assert (file);
@@ -190,7 +242,7 @@ detect_intervening_unindent (const char *file,
 
   for (int line = body_line + 1; line < next_stmt_line; line++)
     {
-      unsigned int line_vis_column;
+      visual_column_t line_vis_column;
       if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
 	if (line_vis_column < vis_column)
 	  return true;
@@ -337,8 +389,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 	  /* They're all on the same line.  */
 	  gcc_assert (guard_exploc.file == next_stmt_exploc.file);
 	  gcc_assert (guard_exploc.line == next_stmt_exploc.line);
-	  unsigned int guard_vis_column;
-	  unsigned int guard_line_first_nws;
+	  visual_column_t guard_vis_column;
+	  visual_column_t guard_line_first_nws;
 	  if (!get_visual_column (guard_exploc, guard_loc,
 				  &guard_vis_column,
 				  &guard_line_first_nws, tab_width))
@@ -389,12 +441,12 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
     {
       /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same
 	 "visual column"...  */
-      unsigned int next_stmt_vis_column;
-      unsigned int next_stmt_line_first_nws;
-      unsigned int body_vis_column;
-      unsigned int body_line_first_nws;
-      unsigned int guard_vis_column;
-      unsigned int guard_line_first_nws;
+      visual_column_t next_stmt_vis_column;
+      visual_column_t next_stmt_line_first_nws;
+      visual_column_t body_vis_column;
+      visual_column_t body_line_first_nws;
+      visual_column_t guard_vis_column;
+      visual_column_t guard_line_first_nws;
       /* If we can't determine it, don't issue a warning.  This is sometimes
 	 the case for input files containing #line directives, and these
 	 are often for autogenerated sources (e.g. from .md files), where
@@ -468,9 +520,9 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 	     indentation is misleading).  Using the column of the first
 	     non-whitespace character on the guard line makes that
 	     happen.  */
-	  unsigned int guard_column = (guard_tinfo.keyword == RID_ELSE
-				       ? guard_line_first_nws
-				       : guard_vis_column);
+	  visual_column_t guard_column = (guard_tinfo.keyword == RID_ELSE
+					  ? guard_line_first_nws
+					  : guard_vis_column);
 	  if (guard_column == body_vis_column)
 	    return false;
 
@@ -490,7 +542,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
 	    return false;
 
 	  /* Don't warn if there is an unindent between the two statements. */
-	  int vis_column = MIN (next_stmt_vis_column, body_vis_column);
+	  visual_column_t vis_column
+	    = MIN (next_stmt_vis_column, body_vis_column);
 	  if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
 					   next_stmt_exploc.line,
 					   vis_column, tab_width))
@@ -631,17 +684,26 @@ test_next_tab_stop ()
 {
   const unsigned int tab_width = 8;
 
-  ASSERT_EQ (next_tab_stop (0, tab_width), 8);
-  ASSERT_EQ (next_tab_stop (1, tab_width), 8);
-  ASSERT_EQ (next_tab_stop (7, tab_width), 8);
-
-  ASSERT_EQ (next_tab_stop (8, tab_width), 16);
-  ASSERT_EQ (next_tab_stop (9, tab_width), 16);
-  ASSERT_EQ (next_tab_stop (15, tab_width), 16);
-
-  ASSERT_EQ (next_tab_stop (16, tab_width), 24);
-  ASSERT_EQ (next_tab_stop (17, tab_width), 24);
-  ASSERT_EQ (next_tab_stop (23, tab_width), 24);
+  ASSERT_EQ (visual_column_t (0).next_tab_stop (tab_width),
+	     visual_column_t (8));
+  ASSERT_EQ (visual_column_t (1).next_tab_stop (tab_width),
+	     visual_column_t (8));
+  ASSERT_EQ (visual_column_t (7).next_tab_stop (tab_width),
+	     visual_column_t (8));
+
+  ASSERT_EQ (visual_column_t (8).next_tab_stop (tab_width),
+	     visual_column_t (16));
+  ASSERT_EQ (visual_column_t (9).next_tab_stop (tab_width),
+	     visual_column_t (16));
+  ASSERT_EQ (visual_column_t (15).next_tab_stop (tab_width),
+	     visual_column_t (16));
+
+  ASSERT_EQ (visual_column_t (16).next_tab_stop (tab_width),
+	     visual_column_t (24));
+  ASSERT_EQ (visual_column_t (17).next_tab_stop (tab_width),
+	     visual_column_t (24));
+  ASSERT_EQ (visual_column_t (23).next_tab_stop (tab_width),
+	     visual_column_t (24));
 }
 
 /* Verify that the given call to get_visual_column succeeds, with
@@ -651,8 +713,8 @@ static void
 assert_get_visual_column_succeeds (const location &loc,
 				   const char *file, int line, int column,
 				   const unsigned int tab_width,
-				   unsigned int expected_visual_column,
-				   unsigned int expected_first_nws)
+				   visual_column_t expected_visual_column,
+				   visual_column_t expected_first_nws)
 {
   expanded_location exploc;
   exploc.file = file;
@@ -660,8 +722,8 @@ assert_get_visual_column_succeeds (const location &loc,
   exploc.column = column;
   exploc.data = NULL;
   exploc.sysp = false;
-  unsigned int actual_visual_column;
-  unsigned int actual_first_nws;
+  visual_column_t actual_visual_column;
+  visual_column_t actual_first_nws;
   bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
 				   &actual_visual_column,
 				   &actual_first_nws, tab_width);
@@ -698,8 +760,8 @@ assert_get_visual_column_fails (const location &loc,
   exploc.column = column;
   exploc.data = NULL;
   exploc.sysp = false;
-  unsigned int actual_visual_column;
-  unsigned int actual_first_nws;
+  visual_column_t actual_visual_column;
+  visual_column_t actual_first_nws;
   bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
 				   &actual_visual_column,
 				   &actual_first_nws, tab_width);
-- 
1.8.5.3

