From 3e8e935d0c88ecbdf1b0c2de9c4a5a4e922f92d9 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 29 Jul 2016 17:53:29 -0400
Subject: [PATCH 12/38] FIXME: fixits for c_parser_require

---
 gcc/c-family/c-common.c                    | 17 +++----
 gcc/c-family/c-common.h                    |  3 +-
 gcc/c/c-parser.c                           | 74 ++++++++++++++++++++++++++++--
 gcc/cp/parser.c                            |  3 +-
 gcc/testsuite/c-c++-common/missing-paren.c | 21 +++++++++
 5 files changed, 104 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/missing-paren.c

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index ec1d87a..d862e74 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -10247,12 +10247,13 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
   return result;
 }
 
-/* Issue the error given by GMSGID, indicating that it occurred before
-   TOKEN, which had the associated VALUE.  */
+/* Issue the error given by GMSGID at RICHLOC, indicating that it occurred
+   before TOKEN, which had the associated VALUE.  */
 
 void
 c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
-	       tree value, unsigned char token_flags)
+	       tree value, unsigned char token_flags,
+	       rich_location *richloc)
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
@@ -10293,7 +10294,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
       else
 	message = catenate_messages (gmsgid, " before %s'\\x%x'");
 
-      error (message, prefix, val);
+      error_at_rich_loc (richloc, message, prefix, val);
       free (message);
       message = NULL;
     }
@@ -10321,7 +10322,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
   else if (token_type == CPP_NAME)
     {
       message = catenate_messages (gmsgid, " before %qE");
-      error (message, value);
+      error_at_rich_loc (richloc, message, value);
       free (message);
       message = NULL;
     }
@@ -10334,16 +10335,16 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
   else if (token_type < N_TTYPES)
     {
       message = catenate_messages (gmsgid, " before %qs token");
-      error (message, cpp_type2name (token_type, token_flags));
+      error_at_rich_loc (richloc, message, cpp_type2name (token_type, token_flags));
       free (message);
       message = NULL;
     }
   else
-    error (gmsgid);
+    error_at_rich_loc (richloc, gmsgid);
 
   if (message)
     {
-      error (message);
+      error_at_rich_loc (richloc, message);
       free (message);
     }
 #undef catenate_messages
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 1d923c9..dad453b 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1165,7 +1165,8 @@ extern void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
 extern void builtin_define_type_sizeof (const char *, tree);
 extern void c_stddef_cpp_builtins (void);
 extern void fe_file_change (const line_map_ordinary *);
-extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char);
+extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char,
+			   rich_location *richloc);
 
 /* In c-ppoutput.c  */
 extern void init_pp_output (FILE *);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 88fe1fd..dac2f53 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -255,6 +255,9 @@ struct GTY(()) c_parser {
   /* Buffer to hold all the tokens from parsing the vector attribute for the
      SIMD-enabled functions (formerly known as elemental functions).  */
   vec <c_token, va_gc> *cilk_simd_fn_tokens;
+
+  /* Location of the most-recently consumed token.  */
+  location_t previous_token_loc;
 };
 
 
@@ -833,6 +836,7 @@ c_parser_consume_token (c_parser *parser)
   gcc_assert (parser->tokens[0].type != CPP_EOF);
   gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
   gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+  parser->previous_token_loc = parser->tokens[0].location;
   if (parser->tokens != &parser->tokens_buf[0])
     parser->tokens++;
   else if (parser->tokens_avail == 2)
@@ -920,7 +924,8 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
    used.  */
 
 static void
-c_parser_error (c_parser *parser, const char *gmsgid)
+c_parser_error_richloc (c_parser *parser, const char *gmsgid,
+			rich_location *richloc)
 {
   c_token *token = c_parser_peek_token (parser);
   if (parser->error)
@@ -965,7 +970,7 @@ c_parser_error (c_parser *parser, const char *gmsgid)
 
   /* This diagnostic makes more sense if it is tagged to the line of
      the token we just peeked at.  */
-  c_parser_set_source_position_from_token (token);
+  //c_parser_set_source_position_from_token (token);
   c_parse_error (gmsgid,
 		 /* Because c_parse_error does not understand
 		    CPP_KEYWORD, keywords are treated like
@@ -975,7 +980,48 @@ c_parser_error (c_parser *parser, const char *gmsgid)
 		    token, we need to pass 0 here and we will not get
 		    the source spelling of some tokens but rather the
 		    canonical spelling.  */
-		 token->value, /*flags=*/0);
+		 token->value, /*flags=*/0, richloc);
+}
+
+/* FIXME.  */
+
+static void
+c_parser_error (c_parser *parser, const char *gmsgid)
+{
+  c_token *token = c_parser_peek_token (parser);
+  rich_location richloc (line_table, token->location);
+  c_parser_error_richloc (parser, gmsgid, &richloc);
+}
+
+/* FIXME: probably to be shared in c-family.  */
+static location_t
+get_insertion_point_FIXME (location_t previous_token_loc)
+{
+  location_t prev_tok_finish = get_finish (previous_token_loc);
+  const struct line_map *line_map
+    = linemap_lookup (line_table, prev_tok_finish);
+  gcc_assert (line_map);
+  if (linemap_macro_expansion_map_p (line_map))
+    return UNKNOWN_LOCATION;
+  return linemap_position_for_loc_and_offset (line_table,
+					      prev_tok_finish,
+					      1);
+}
+
+/* FIXME: likewise, probably to be shared in c-family.  */
+static bool
+suggested_replacement_p_FIXME (enum cpp_ttype type)
+{
+  switch (type)
+    {
+    case CPP_OPEN_PAREN:
+    case CPP_CLOSE_PAREN:
+    case CPP_OPEN_SQUARE:
+    case CPP_CLOSE_SQUARE:
+      return true;
+    default:
+      return false;
+    }
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
@@ -995,7 +1041,27 @@ c_parser_require (c_parser *parser,
     }
   else
     {
-      c_parser_error (parser, msgid);
+      rich_location richloc (line_table, c_parser_peek_token (parser)->location);
+      // FIXME: fixit hint for insertion; location of *previous* token,
+      // presumably immediately after...
+      if (!parser->error && suggested_replacement_p_FIXME (type))
+	{
+	  /* Offset to immediately *after* that token.  */
+	  location_t after_loc
+	    = get_insertion_point_FIXME (parser->previous_token_loc);
+	  if (after_loc)
+	    {
+	      //rich_location richloc (line_table, after_loc);
+	      richloc.add_fixit_insert (after_loc, cpp_type2name (type, 0));
+	      //inform_at_rich_loc (&richloc, "FIXME: insertion");
+	      // FIXME: ideally would be merged in with the c_parser_error call...
+	      // doing so puts the fixit on a line that isn't covered
+	      // by the ranges within the diagnostic range itself
+	      // for now, add it as a secondary location..
+	      richloc.add_range (after_loc, true);
+	    }
+	}
+      c_parser_error_richloc (parser, msgid, &richloc);
       return false;
     }
 }
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ca9f8b9..d2e7bae 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2800,12 +2800,13 @@ cp_parser_error (cp_parser* parser, const char* gmsgid)
 	    }
 	}
 
+      rich_location richloc (line_table, token->location);
       c_parse_error (gmsgid,
 		     /* Because c_parser_error does not understand
 			CPP_KEYWORD, keywords are treated like
 			identifiers.  */
 		     (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-		     token->u.value, token->flags);
+		     token->u.value, token->flags, &richloc);
     }
 }
 
diff --git a/gcc/testsuite/c-c++-common/missing-paren.c b/gcc/testsuite/c-c++-common/missing-paren.c
new file mode 100644
index 0000000..bb18bb7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/missing-paren.c
@@ -0,0 +1,21 @@
+extern int foo (void);
+extern int bar (void);
+
+int test_1 (const char *pass_name)
+{
+  if (foo ()
+      && bar ()
+    {
+    }
+}
+
+#include <string.h>
+
+int test_2 (const char *pass_name)
+{
+
+  if (0 == strcmp (pass_name, "rtl-ira")
+      || 0 == strcmp (pass_name, "rtl-reload")
+    {
+    }
+}
-- 
1.8.5.3

