From d11fc02f19ef54d97162e94abd9b60505cb4af16 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 31 Aug 2015 21:33:16 -0400
Subject: [PATCH 22/66] FIXME: Add gcc/location-hacks.[ch]

---
 gcc/location-hacks.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 216 insertions(+)
 create mode 100644 gcc/location-hacks.c

diff --git a/gcc/location-hacks.c b/gcc/location-hacks.c
new file mode 100644
index 0000000..08e0596
--- /dev/null
+++ b/gcc/location-hacks.c
@@ -0,0 +1,216 @@
+/* A file containing kludges and hardcoded data
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree-core.h"
+#include "tree.h"
+#include "diagnostic-core.h"
+#include "gcc-rich-location.h"
+#include "print-tree.h"
+#include "pretty-print.h"
+#include "intl.h"
+#include "location-hacks.h"
+
+/* We need to come up with an efficient way of storing information on
+   source code *ranges* (rather than mere points) for various constructs
+   such as expressions and macros.
+
+   Ideally the location data would preserve range information, and we'd
+   consult that.
+
+   In the meantime, here's a massive kludge: a magical location "oracle",
+   that simply hardcodes the data for each testcase.
+
+   Obviously this needs to be eliminated, but having it allows us to work on
+   other aspects of rich location reporting (e.g. to extend the diagnostics
+   API, and to write testcases) without needing to address the range
+   representation issue up-front.
+
+   Note that the column numbers here are 0-based convention, for ease of
+   working with Emacs, whereas the GCC location data structures and
+   reporting mechanisms are 1-based.  */
+
+struct hacked_range
+{
+  int start_line;
+  int start_column;
+  int finish_line;
+  int finish_column;
+};
+
+struct expr_locations_for_testcase
+{
+  const char *testcase_name;
+  int num_locs;
+  struct hacked_range loc_range[3];
+};
+
+struct expr_locations_for_testcase expr_location_oracle[] = {
+  {"testsuite/gcc.dg/20150303-01.c",
+   3,
+   {{6, 2, 6, 14},
+    {7, 2, 7, 5},
+    {4, 16, 4, 19}}
+  },
+
+  {"testsuite/gcc.dg/20150303-04.c",
+   2,
+   {{9, 2, 9, 9},
+    {9, 11, 9, 11}}
+  },
+
+  {"testsuite/gcc.dg/20150304-01.c",
+   1,
+   {{11, 6, 11, 16}}
+  },
+
+  {"testsuite/gcc.dg/cpp-divbyzero.c",
+   1,
+   {15, 8, 15, 11},
+  },
+
+  {"testsuite/gcc.dg/divbyzero.c",
+   3,
+   {{13, 17, 13, 20},
+    {14, 17, 14, 17},
+    {15, 17, 15, 20}}
+  },
+
+  {"testsuite/g++.dg/diagnostic/20150304-02.C",
+   1,
+   {{10, 3, 10, 6}}
+  },
+
+  /* Sentinel.  */
+  {NULL, 0, {}}
+};
+
+static bool
+consult_the_range_oracle (location_range *r)
+{
+  const char *testcase = strstr (main_input_filename,
+				 "testsuite/");
+
+  if (0)
+    fprintf (stderr,
+	     "consulting the range oracle\n");
+
+  if (!testcase)
+    return false;
+
+  /* Locate testcase by name within "expr_location_oracle" array.  */
+  static int num_calls = 0;
+  for (expr_locations_for_testcase *iter = expr_location_oracle;
+       iter->testcase_name;
+       iter++)
+    if (0 == strcmp (testcase, iter->testcase_name))
+      {
+	if (num_calls >= iter->num_locs)
+	  {
+	    fprintf (stderr,
+		     "ran out of locations within location oracle"
+		     " (testcase: %s)\n",
+		     testcase);
+	    return false;
+	  }
+
+	gcc_assert (num_calls < iter->num_locs);
+	struct hacked_range *hr = &iter->loc_range[num_calls++];
+	r->m_start.file = main_input_filename;
+	r->m_finish.file = main_input_filename;
+	r->m_start.line = hr->start_line;
+	r->m_finish.line = hr->finish_line;
+	/* Convert from 0-based column numberings to 1-based numbering.  */
+	r->m_start.column = hr->start_column + 1;
+	r->m_finish.column = hr->finish_column + 1;
+	return true;
+      }
+
+  /* Testcase not found.  */
+  fprintf (stderr,
+	   "not found within location oracle (testcase: %s)\n",
+	   testcase);
+  return false;
+}
+
+/* Get the location_range for the given tree expression.
+   For now, this simply looks thinks up in the hardcoded data.  */
+
+bool
+get_range_for_expr (tree expr, location_range *r)
+{
+  if (EXPR_HAS_RANGE (expr))
+    {
+      source_range sr = EXPR_LOCATION_RANGE (expr);
+
+      /* Do we have meaningful data?  */
+      if (sr.m_start && sr.m_finish)
+	{
+	  r->m_start = expand_location (sr.m_start);
+	  r->m_finish = expand_location (sr.m_finish);
+	  return true;
+	}
+    }
+
+  /* Otherwise, fall back on the hack.  */
+  return consult_the_range_oracle (r);
+}
+
+/* Get the location_range for the given decl.
+   For now, this simply looks thinks up in the hardcoded data.  */
+
+bool
+get_range_for_decl (tree decl, location_range *r)
+{
+  source_range sr = DECL_LOCATION_RANGE (decl);
+
+  /* Do we have meaningful data?  */
+  if (sr.m_start && sr.m_finish)
+    {
+      r->m_start = expand_location (sr.m_start);
+      r->m_finish = expand_location (sr.m_finish);
+      return true;
+    }
+  else
+    /* Otherwise, fall back on the hack.  */
+    return consult_the_range_oracle (r);
+}
+
+/* Get the location_range for the given macro.
+   For now, this simply looks thinks up in the hardcoded data.  */
+
+bool
+get_range_for_macro (const line_map * /* macro */, location_range *r)
+{
+  /* Likewise, this is also currently a total hack.  */
+  return consult_the_range_oracle (r);
+}
-- 
1.8.5.3

