public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/4] add utility to poison globals that should not be used
@ 2021-06-30  5:35 Trevor Saunders
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-06-30  5:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

This provides a class to wrap globals like input_location or cfun that should
not be used directly and will ideally go away.  This class tracks if access to
the global is currently blocked and asserts if accessed when that is not
allowed.  It also adds a class to mark access as blocked for the lifetime of the
scope.

bootstrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/ChangeLog:

	* poison.h: New file.
---
 gcc/poison.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 gcc/poison.h

diff --git a/gcc/poison.h b/gcc/poison.h
new file mode 100644
index 00000000000..239ab1cb91a
--- /dev/null
+++ b/gcc/poison.h
@@ -0,0 +1,88 @@
+/* Simple utility to poison globals that should be avoided.
+
+   Copyright (C) 2021 the GNU Toolchain Authors
+
+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/>.  */
+
+#ifndef GCC_POISON_H
+#define GCC_POISON_H
+
+template<typename T> class auto_poison;
+
+/* This class is intended to be used as a transparent wrapper around the type of
+   a global object that we would like to stop using.  */
+template<typename T>
+class poisonable
+{
+public:
+  poisonable () : m_val (), m_poisoned (false) {}
+  explicit poisonable (T val) : m_val (val), m_poisoned (false) {}
+
+  operator T& ()
+    {
+      gcc_assert (!m_poisoned);
+      return m_val;
+    }
+
+  poisonable &operator= (T val)
+    {
+      gcc_assert (!m_poisoned);
+      m_val = val;
+      return *this;
+    }
+
+  T *operator& ()
+    {
+      gcc_assert (!m_poisoned);
+      return &m_val;
+    }
+
+  poisonable (const poisonable &) = delete;
+  poisonable (poisonable &&) = delete;
+  poisonable &operator= (const poisonable &) = delete;
+  poisonable &operator= (poisonable &&) = delete;
+
+private:
+  friend class auto_poison<T>;
+
+  T m_val;
+  bool m_poisoned;
+  };
+
+/* This class provides a way to make a global inaccessible in the given scope,
+   and any functions called within that scope.  */
+template<typename T>
+class auto_poison
+{
+public:
+  auto_poison (poisonable<T> &p) : m_target (p)
+  {
+    gcc_assert (!p.m_poisoned);
+    p.m_poisoned = true;
+  }
+  ~auto_poison () { m_target.m_poisoned = false; }
+
+  auto_poison (const auto_poison &) = delete;
+  auto_poison (auto_poison &&) = delete;
+  auto_poison &operator= (const auto_poison &) = delete;
+  auto_poison &operator= (auto_poison &&) = delete;
+
+private:
+  poisonable<T> &m_target;
+};
+
+#endif
-- 
2.20.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30  5:35 [PATCH 1/4] add utility to poison globals that should not be used Trevor Saunders
@ 2021-06-30  5:35 ` Trevor Saunders
  2021-06-30  9:00   ` Richard Biener
                     ` (2 more replies)
  2021-06-30  5:35 ` [PATCH 3/4] allow poisoning cfun Trevor Saunders
  2021-06-30  5:35 ` [PATCH 4/4] poison input_location and cfun in one spot Trevor Saunders
  2 siblings, 3 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-06-30  5:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

This makes it possible to assert if input_location is used during the lifetime
of a scope.  This will allow us to find places that currently use it within a
function and its callees, or prevent adding uses within the lifetime of a
function after all existing uses are removed.

bootstrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/cp/ChangeLog:

	* call.c (add_builtin_candidate): Adjust.
	* decl.c (compute_array_index_type_loc): Likewise.
	* decl2.c (get_guard_cond): Likewise.
	(one_static_initialization_or_destruction): Likewise.
	(do_static_initialization_or_destruction): Likewise.
	* init.c (build_new_1): Likewise.
	(build_vec_init): Likewise.
	* module.cc (finish_module_processing): Likewise.
	* parser.c (cp_convert_range_for): Likewise.
	(cp_parser_perform_range_for_lookup): Likewise.
	(cp_parser_omp_for_incr): Likewise.
	(cp_convert_omp_range_for): Likewise.
	* pt.c (fold_expression): Likewise.
	(tsubst_copy_and_build): Likewise.
	* typeck.c (common_pointer_type): Likewise.
	(cp_build_array_ref): Likewise.
	(get_member_function_from_ptrfunc): Likewise.
	(cp_build_unary_op): Likewise.
	(convert_ptrmem): Likewise.
	(cp_build_modify_expr): Likewise.
	(build_ptrmemfunc): Likewise.

gcc/ChangeLog:

	* diagnostic.c (internal_error): Remove use of input_location.
	* input.c (input_location): Change type to poisonable<location_t>.
	* input.h (input_location): Adjust prototype.

gcc/objc/ChangeLog:

	* objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
---
 gcc/cp/call.c                       |  2 +-
 gcc/cp/decl.c                       |  2 +-
 gcc/cp/decl2.c                      | 12 +++++------
 gcc/cp/init.c                       | 14 ++++++------
 gcc/cp/module.cc                    |  2 +-
 gcc/cp/parser.c                     | 11 +++++-----
 gcc/cp/pt.c                         |  4 ++--
 gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
 gcc/diagnostic.c                    |  2 +-
 gcc/input.c                         |  2 +-
 gcc/input.h                         |  3 ++-
 gcc/objc/objc-next-runtime-abi-02.c |  2 +-
 12 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4df72ec1a3..c94fe0b3bd2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
     {
       if (TYPE_PTR_OR_PTRMEM_P (type1))
 	{
-	  tree cptype = composite_pointer_type (input_location,
+	  tree cptype = composite_pointer_type (op_location_t (input_location),
 						type1, type2,
 						error_mark_node,
 						error_mark_node,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fa6af6fec11..84e2bdae6bf 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
 	 cp_build_binary_op will be appropriately folded.  */
       {
 	processing_template_decl_sentinel s;
-	itype = cp_build_binary_op (input_location,
+	itype = cp_build_binary_op (op_location_t (input_location),
 				    MINUS_EXPR,
 				    cp_convert (ssizetype, size, complain),
 				    cp_convert (ssizetype, integer_one_node,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 090a83bd670..ddb7e248c63 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
       guard_value = integer_one_node;
       if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
 	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
-      guard = cp_build_binary_op (input_location,
+      guard = cp_build_binary_op (location_t (input_location),
 				  BIT_AND_EXPR, guard, guard_value,
 				  tf_warning_or_error);
     }
@@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
     guard_value = fold_convert (TREE_TYPE (guard), guard_value);
-  return cp_build_binary_op (input_location,
+  return cp_build_binary_op (location_t (input_location),
 			     EQ_EXPR, guard, guard_value,
 			     tf_warning_or_error);
 }
@@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
 	 last to destroy the variable.  */
       else if (initp)
 	guard_cond
-	  = cp_build_binary_op (input_location,
+	  = cp_build_binary_op (location_t (input_location),
 				EQ_EXPR,
 				cp_build_unary_op (PREINCREMENT_EXPR,
 						   guard,
@@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
 				tf_warning_or_error);
       else
 	guard_cond
-	  = cp_build_binary_op (input_location,
+	  = cp_build_binary_op (location_t (input_location),
 				EQ_EXPR,
 				cp_build_unary_op (PREDECREMENT_EXPR,
 						   guard,
@@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
   /* Build the outer if-stmt to check for initialization or destruction.  */
   init_if_stmt = begin_if_stmt ();
   cond = initp ? integer_one_node : integer_zero_node;
-  cond = cp_build_binary_op (input_location,
+  cond = cp_build_binary_op (location_t (input_location),
 			     EQ_EXPR,
 			     initialize_p_decl,
 			     cond,
@@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
     /* Conditionalize this initialization on being in the right priority
        and being initializing/finalizing appropriately.  */
     priority_if_stmt = begin_if_stmt ();
-    cond = cp_build_binary_op (input_location,
+    cond = cp_build_binary_op (location_t (input_location),
 			       EQ_EXPR,
 			       priority_decl,
 			       build_int_cst (NULL_TREE, priority),
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 88f6f90a800..d9acdefae7c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	  nelts = error_mark_node;
 	}
       if (nelts != error_mark_node)
-	nelts = cp_build_binary_op (input_location,
+	nelts = cp_build_binary_op (location_t (input_location),
 				    MULT_EXPR, nelts,
 				    inner_nelts_cst,
 				    complain);
@@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
             }
 	  init_expr
 	    = build_vec_init (data_addr,
-			      cp_build_binary_op (input_location,
+			      cp_build_binary_op (location_t (input_location),
 						  MINUS_EXPR, outer_nelts,
 						  integer_one_node,
 						  complain),
@@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
     {
       if (check_new)
 	{
-	  tree ifexp = cp_build_binary_op (input_location,
+	  tree ifexp = cp_build_binary_op (location_t (input_location),
 					   NE_EXPR, alloc_node,
 					   nullptr_node,
 					   complain);
-	  rval = build_conditional_expr (input_location, ifexp, rval,
-					 alloc_node, complain);
+	  rval = build_conditional_expr (location_t (input_location), ifexp,
+					 rval, alloc_node, complain);
 	}
 
       /* Perform the allocation before anything else, so that ALLOC_NODE
@@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
       && from_array != 2)
     {
       tree e;
-      tree m = cp_build_binary_op (input_location,
+      tree m = cp_build_binary_op (location_t (input_location),
 				   MINUS_EXPR, maxindex, iterator,
 				   complain);
 
       /* Flatten multi-dimensional array since build_vec_delete only
 	 expects one-dimensional array.  */
       if (TREE_CODE (type) == ARRAY_TYPE)
-	m = cp_build_binary_op (input_location,
+	m = cp_build_binary_op (location_t (input_location),
 				MULT_EXPR, m,
 				/* Avoid mixing signed and unsigned.  */
 				convert (TREE_TYPE (m),
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index f259515a498..72f32487e51 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
 	  elf_out to (fd, e);
 	  if (to.begin ())
 	    {
-	      auto loc = input_location;
+	      location_t loc = input_location;
 	      /* So crashes finger-point the module decl.  */
 	      input_location = state->loc;
 	      state->write (&to, reader);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 02daa7a6f6a..e90ee873a94 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
   finish_init_stmt (statement);
 
   /* The new for condition.  */
-  condition = build_x_binary_op (input_location, NE_EXPR,
+  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
 				 begin, ERROR_MARK,
 				 end, ERROR_MARK,
 				 NULL, tf_warning_or_error);
@@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
 	  if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
 	    {
 	      if (cxx_dialect >= cxx17
-		  && (build_x_binary_op (input_location, NE_EXPR,
+		  && (build_x_binary_op (location_t (input_location), NE_EXPR,
 					 *begin, ERROR_MARK,
 					 *end, ERROR_MARK,
 					 NULL, tf_none)
@@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 					tf_warning_or_error);
 	    }
 	  else
-	    lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
-				     ERROR_MARK, NULL, tf_warning_or_error);
+	    lhs = build_x_binary_op (location_t (input_location), op, lhs,
+				     ERROR_MARK, rhs, ERROR_MARK, NULL,
+				     tf_warning_or_error);
 	}
     }
   while (token->type == CPP_PLUS || token->type == CPP_MINUS);
@@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
   if (CLASS_TYPE_P (iter_type))
     cond = build2 (NE_EXPR, boolean_type_node, begin, end);
   else
-    cond = build_x_binary_op (input_location, NE_EXPR,
+    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
 			      begin, ERROR_MARK,
 			      end, ERROR_MARK,
 			      NULL, tf_warning_or_error);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f2039e09cd7..b679e34bfa4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, tsubst_flags_t complain)
     case COMPOUND_EXPR:
       return build_x_compound_expr (input_location, left, right, complain);
     default:
-      return build_x_binary_op (input_location, code,
+      return build_x_binary_op (location_t (input_location), code,
                                 left, TREE_CODE (left),
                                 right, TREE_CODE (right),
                                 /*overload=*/NULL,
@@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
 	warning_sentinel s4(warn_tautological_compare, was_dep);
 
 	tree r = build_x_binary_op
-	  (input_location, TREE_CODE (t),
+	  (location_t (input_location), TREE_CODE (t),
 	   op0,
 	   (warning_suppressed_p (TREE_OPERAND (t, 0))
 	    ? ERROR_MARK
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a483e1f988d..98aa9e69612 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
               || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
               || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
 
-  return composite_pointer_type (input_location, t1, t2,
+  return composite_pointer_type (location_t (input_location), t1, t2,
 				 error_mark_node, error_mark_node,
                                  CPO_CONVERSION, tf_warning_or_error);
 }
@@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
 
     warn_array_subscript_with_type_char (loc, idx);
 
-    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
+    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
+			      complain);
     if (first)
       ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
     ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
@@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
 	{
 	  int flag_sanitize_save;
 	case ptrmemfunc_vbit_in_pfn:
-	  e1 = cp_build_binary_op (input_location,
+	  e1 = cp_build_binary_op (location_t (input_location),
 				   BIT_AND_EXPR, idx, integer_one_node,
 				   complain);
-	  idx = cp_build_binary_op (input_location,
+	  idx = cp_build_binary_op (location_t (input_location),
 				    MINUS_EXPR, idx, integer_one_node,
 				    complain);
 	  if (idx == error_mark_node)
@@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
 	  break;
 
 	case ptrmemfunc_vbit_in_delta:
-	  e1 = cp_build_binary_op (input_location,
+	  e1 = cp_build_binary_op (location_t (input_location),
 				   BIT_AND_EXPR, delta, integer_one_node,
 				   complain);
 	  /* Don't instrument the RSHIFT_EXPR we're about to create because
@@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
 	     well with SAVE_EXPRs therein.  */
 	  flag_sanitize_save = flag_sanitize;
 	  flag_sanitize = 0;
-	  delta = cp_build_binary_op (input_location,
+	  delta = cp_build_binary_op (location_t (input_location),
 				      RSHIFT_EXPR, delta, integer_one_node,
 				      complain);
 	  flag_sanitize = flag_sanitize_save;
@@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
 		     cp_build_addr_expr (e2, complain));
 
       e2 = fold_convert (TREE_TYPE (e3), e2);
-      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
+      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
+				   complain);
       if (e1 == error_mark_node)
 	return error_mark_node;
 
@@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
 
     case TRUTH_NOT_EXPR:
       if (gnu_vector_type_p (TREE_TYPE (arg)))
-	return cp_build_binary_op (input_location, EQ_EXPR, arg,
+	return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
 				   build_zero_cst (TREE_TYPE (arg)), complain);
       arg = perform_implicit_conversion (boolean_type_node, arg,
 					 complain);
@@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
 	  if (TREE_CODE (expr) == PTRMEM_CST)
 	    expr = cplus_expand_constant (expr);
 
-	  tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
+	  tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
+					  expr,
 					  build_int_cst (TREE_TYPE (expr), -1),
 					  complain);
 	  tree op1 = build_nop (ptrdiff_type_node, expr);
-	  tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
-					 complain);
+	  tree op2 = cp_build_binary_op (location_t (input_location),
+					 PLUS_EXPR, op1, delta, complain);
 
 	  expr = fold_build3_loc (input_location,
 				  COND_EXPR, ptrdiff_type_node, cond, op1, op2);
@@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	tree op2 = TREE_OPERAND (lhs, 2);
 	if (TREE_CODE (op2) != THROW_EXPR)
 	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
-	tree cond = build_conditional_expr (input_location,
+	tree cond = build_conditional_expr (location_t (input_location),
 					    TREE_OPERAND (lhs, 0), op1, op2,
 					    complain);
 
@@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	    /* Do the default thing.  */;
 	  else
 	    {
-	      result = build_new_op (input_location, MODIFY_EXPR,
+	      result = build_new_op (location_t (input_location), MODIFY_EXPR,
 				     LOOKUP_NORMAL, lhs, rhs,
 				     make_node (NOP_EXPR), /*overload=*/NULL,
 				     complain);
@@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
       if (!integer_zerop (n))
 	{
 	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
-	    n = cp_build_binary_op (input_location,
+	    n = cp_build_binary_op (location_t (input_location),
 				    LSHIFT_EXPR, n, integer_one_node,
 				    complain);
-	  delta = cp_build_binary_op (input_location,
+	  delta = cp_build_binary_op (location_t (input_location),
 				      PLUS_EXPR, delta, n, complain);
 	}
       return build_ptrmemfunc1 (to_type, delta, npfn);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d58586f2526..3f68d1d79eb 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
   auto_diagnostic_group d;
   va_list ap;
   va_start (ap, gmsgid);
-  rich_location richloc (line_table, input_location);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
   va_end (ap);
 
diff --git a/gcc/input.c b/gcc/input.c
index 9e39e7df83c..1843c3077aa 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -122,7 +122,7 @@ public:
 
 /* Current position in real source file.  */
 
-location_t input_location = UNKNOWN_LOCATION;
+poisonable<location_t> input_location (UNKNOWN_LOCATION);
 
 class line_maps *line_table;
 
diff --git a/gcc/input.h b/gcc/input.h
index f1ef5d76cfd..2b96ce8008e 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_INPUT_H
 #define GCC_INPUT_H
 
+#include "poison.h"
 #include "line-map.h"
 
 extern GTY(()) class line_maps *line_table;
@@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
 extern location_t expansion_point_location_if_in_system_header (location_t);
 extern location_t expansion_point_location (location_t);
 
-extern location_t input_location;
+extern poisonable<location_t> input_location;
 
 #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
 #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 3cfcd0b1a57..9ecb91cc56b 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
 			       fold_convert (rcv_p, integer_zero_node), 1);
 
 #ifdef OBJCPLUS
-      ret_val = build_conditional_expr (input_location,
+      ret_val = build_conditional_expr (location_t (input_location),
 					ifexp, ret_val, ftree,
 					tf_warning_or_error);
 #else
-- 
2.20.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 3/4] allow poisoning cfun
  2021-06-30  5:35 [PATCH 1/4] add utility to poison globals that should not be used Trevor Saunders
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
@ 2021-06-30  5:35 ` Trevor Saunders
  2021-06-30  5:35 ` [PATCH 4/4] poison input_location and cfun in one spot Trevor Saunders
  2 siblings, 0 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-06-30  5:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

Since cfun is already a macro in most of the compiler, we redefine it to point
to a second variable, to avoid having to support C++ objects as GC roots.
However we keep the existing function * global for internal use as a gc root.
It is unfortunate the two globals need to stay in sync, but there is only a
couple of places that update it, and this seems much easier than getting
gengtype to properly handle objects as roots and in pch generation and use.

bootstrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/cp/ChangeLog:

	* module.cc (module_state::read_cluster): Set cfun_poison as well as
	cfun.

gcc/ChangeLog:

	* function.c (cfun_poison): New global.
	(set_cfun): Set cfun_poison.
	(allocate_struct_function): Likewise.
	* function.h (cfun_poison): New declaration.
	(cfun): Adjust.
---
 gcc/cp/module.cc | 2 ++
 gcc/function.c   | 4 ++++
 gcc/function.h   | 4 +++-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 72f32487e51..2f1126211e6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -14868,6 +14868,8 @@ module_state::read_cluster (unsigned snum)
      redesigning that API right now.  */
 #undef cfun
   cfun = old_cfun;
+  cfun_poison = old_cfun;
+  cfun_poison = old_cfun;
   current_function_decl = old_cfd;
   comparing_dependent_aliases--;
 
diff --git a/gcc/function.c b/gcc/function.c
index 00b2fe70c7d..87e8bc86166 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "function-abi.h"
 #include "value-range.h"
 #include "gimple-range.h"
+#include "poison.h"
 
 /* So we can assign to cfun in this file.  */
 #undef cfun
@@ -118,6 +119,7 @@ struct machine_function * (*init_machine_status) (void);
 
 /* The currently compiled function.  */
 struct function *cfun = 0;
+poisonable<function *> cfun_poison (0);
 
 /* These hashes record the prologue and epilogue insns.  */
 
@@ -4715,6 +4717,7 @@ set_cfun (struct function *new_cfun, bool force)
   if (cfun != new_cfun || force)
     {
       cfun = new_cfun;
+      cfun_poison = new_cfun;
       invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
       redirect_edge_var_map_empty ();
     }
@@ -4797,6 +4800,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
   tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
 
   cfun = ggc_cleared_alloc<function> ();
+  cfun_poison = cfun;
 
   init_eh_for_function ();
 
diff --git a/gcc/function.h b/gcc/function.h
index 0db51775e7c..82f7510bdc3 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_FUNCTION_H
 #define GCC_FUNCTION_H
 
+template<typename T> class poisonable;
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -459,11 +460,12 @@ void record_dynamic_alloc (tree decl_or_exp);
 
 /* The function currently being compiled.  */
 extern GTY(()) struct function *cfun;
+extern poisonable<function *> cfun_poison;
 
 /* In order to ensure that cfun is not set directly, we redefine it so
    that it is not an lvalue.  Rather than assign to cfun, use
    push_cfun or set_cfun.  */
-#define cfun (cfun + 0)
+#define cfun (cfun_poison + 0)
 
 /* Nonzero if we've already converted virtual regs to hard regs.  */
 extern int virtuals_instantiated;
-- 
2.20.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 4/4] poison input_location and cfun in one spot
  2021-06-30  5:35 [PATCH 1/4] add utility to poison globals that should not be used Trevor Saunders
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
  2021-06-30  5:35 ` [PATCH 3/4] allow poisoning cfun Trevor Saunders
@ 2021-06-30  5:35 ` Trevor Saunders
  2021-06-30  9:02   ` Richard Biener
  2 siblings, 1 reply; 25+ messages in thread
From: Trevor Saunders @ 2021-06-30  5:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

This simply confirms we can poison them in a small region.

boostrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/ChangeLog:

	* gimple-range.cc (disable_ranger): Prevent access to cfun and
	input_location.
---
 gcc/gimple-range.cc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 1851339c528..d4a3a6e46be 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "poison.h"
 #include "backend.h"
 #include "tree.h"
 #include "gimple.h"
@@ -509,6 +510,8 @@ enable_ranger (struct function *fun)
 void
 disable_ranger (struct function *fun)
 {
+  auto_poison<location_t> pil (input_location);
+  auto_poison<function *> pcfun (cfun_poison);
   delete fun->x_range_query;
 
   fun->x_range_query = &global_ranges;
-- 
2.20.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
@ 2021-06-30  9:00   ` Richard Biener
  2021-06-30 12:33     ` Trevor Saunders
  2021-06-30 15:13   ` David Malcolm
  2021-07-02 19:20   ` Martin Sebor
  2 siblings, 1 reply; 25+ messages in thread
From: Richard Biener @ 2021-06-30  9:00 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>
> This makes it possible to assert if input_location is used during the lifetime
> of a scope.  This will allow us to find places that currently use it within a
> function and its callees, or prevent adding uses within the lifetime of a
> function after all existing uses are removed.
>
> bootstrapped and regtested on x86_64-linux-gnu, ok?

I'm not sure about the general approach but I have comments about
input_location.

IMHO a good first step would be to guard the input_location declaration with sth
like

#ifndef GCC_NEED_INPUT_LOCATION
extern location_t input_location;
#endif

and "white-list" it in the few files that refer to it.  (but not in
coretypes.h or rtl.h
which seem to include input.h).

Richard.

> Trev
>
> gcc/cp/ChangeLog:
>
>         * call.c (add_builtin_candidate): Adjust.
>         * decl.c (compute_array_index_type_loc): Likewise.
>         * decl2.c (get_guard_cond): Likewise.
>         (one_static_initialization_or_destruction): Likewise.
>         (do_static_initialization_or_destruction): Likewise.
>         * init.c (build_new_1): Likewise.
>         (build_vec_init): Likewise.
>         * module.cc (finish_module_processing): Likewise.
>         * parser.c (cp_convert_range_for): Likewise.
>         (cp_parser_perform_range_for_lookup): Likewise.
>         (cp_parser_omp_for_incr): Likewise.
>         (cp_convert_omp_range_for): Likewise.
>         * pt.c (fold_expression): Likewise.
>         (tsubst_copy_and_build): Likewise.
>         * typeck.c (common_pointer_type): Likewise.
>         (cp_build_array_ref): Likewise.
>         (get_member_function_from_ptrfunc): Likewise.
>         (cp_build_unary_op): Likewise.
>         (convert_ptrmem): Likewise.
>         (cp_build_modify_expr): Likewise.
>         (build_ptrmemfunc): Likewise.
>
> gcc/ChangeLog:
>
>         * diagnostic.c (internal_error): Remove use of input_location.
>         * input.c (input_location): Change type to poisonable<location_t>.
>         * input.h (input_location): Adjust prototype.
>
> gcc/objc/ChangeLog:
>
>         * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
> ---
>  gcc/cp/call.c                       |  2 +-
>  gcc/cp/decl.c                       |  2 +-
>  gcc/cp/decl2.c                      | 12 +++++------
>  gcc/cp/init.c                       | 14 ++++++------
>  gcc/cp/module.cc                    |  2 +-
>  gcc/cp/parser.c                     | 11 +++++-----
>  gcc/cp/pt.c                         |  4 ++--
>  gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
>  gcc/diagnostic.c                    |  2 +-
>  gcc/input.c                         |  2 +-
>  gcc/input.h                         |  3 ++-
>  gcc/objc/objc-next-runtime-abi-02.c |  2 +-
>  12 files changed, 47 insertions(+), 42 deletions(-)
>
> diff --git a/gcc/cp/call.c b/gcc/cp/call.c
> index e4df72ec1a3..c94fe0b3bd2 100644
> --- a/gcc/cp/call.c
> +++ b/gcc/cp/call.c
> @@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
>      {
>        if (TYPE_PTR_OR_PTRMEM_P (type1))
>         {
> -         tree cptype = composite_pointer_type (input_location,
> +         tree cptype = composite_pointer_type (op_location_t (input_location),
>                                                 type1, type2,
>                                                 error_mark_node,
>                                                 error_mark_node,
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index fa6af6fec11..84e2bdae6bf 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
>          cp_build_binary_op will be appropriately folded.  */
>        {
>         processing_template_decl_sentinel s;
> -       itype = cp_build_binary_op (input_location,
> +       itype = cp_build_binary_op (op_location_t (input_location),
>                                     MINUS_EXPR,
>                                     cp_convert (ssizetype, size, complain),
>                                     cp_convert (ssizetype, integer_one_node,
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index 090a83bd670..ddb7e248c63 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
>        guard_value = integer_one_node;
>        if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>         guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> -      guard = cp_build_binary_op (input_location,
> +      guard = cp_build_binary_op (location_t (input_location),
>                                   BIT_AND_EXPR, guard, guard_value,
>                                   tf_warning_or_error);
>      }
> @@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
>    guard_value = integer_zero_node;
>    if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>      guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> -  return cp_build_binary_op (input_location,
> +  return cp_build_binary_op (location_t (input_location),
>                              EQ_EXPR, guard, guard_value,
>                              tf_warning_or_error);
>  }
> @@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>          last to destroy the variable.  */
>        else if (initp)
>         guard_cond
> -         = cp_build_binary_op (input_location,
> +         = cp_build_binary_op (location_t (input_location),
>                                 EQ_EXPR,
>                                 cp_build_unary_op (PREINCREMENT_EXPR,
>                                                    guard,
> @@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>                                 tf_warning_or_error);
>        else
>         guard_cond
> -         = cp_build_binary_op (input_location,
> +         = cp_build_binary_op (location_t (input_location),
>                                 EQ_EXPR,
>                                 cp_build_unary_op (PREDECREMENT_EXPR,
>                                                    guard,
> @@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>    /* Build the outer if-stmt to check for initialization or destruction.  */
>    init_if_stmt = begin_if_stmt ();
>    cond = initp ? integer_one_node : integer_zero_node;
> -  cond = cp_build_binary_op (input_location,
> +  cond = cp_build_binary_op (location_t (input_location),
>                              EQ_EXPR,
>                              initialize_p_decl,
>                              cond,
> @@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>      /* Conditionalize this initialization on being in the right priority
>         and being initializing/finalizing appropriately.  */
>      priority_if_stmt = begin_if_stmt ();
> -    cond = cp_build_binary_op (input_location,
> +    cond = cp_build_binary_op (location_t (input_location),
>                                EQ_EXPR,
>                                priority_decl,
>                                build_int_cst (NULL_TREE, priority),
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index 88f6f90a800..d9acdefae7c 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>           nelts = error_mark_node;
>         }
>        if (nelts != error_mark_node)
> -       nelts = cp_build_binary_op (input_location,
> +       nelts = cp_build_binary_op (location_t (input_location),
>                                     MULT_EXPR, nelts,
>                                     inner_nelts_cst,
>                                     complain);
> @@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>              }
>           init_expr
>             = build_vec_init (data_addr,
> -                             cp_build_binary_op (input_location,
> +                             cp_build_binary_op (location_t (input_location),
>                                                   MINUS_EXPR, outer_nelts,
>                                                   integer_one_node,
>                                                   complain),
> @@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>      {
>        if (check_new)
>         {
> -         tree ifexp = cp_build_binary_op (input_location,
> +         tree ifexp = cp_build_binary_op (location_t (input_location),
>                                            NE_EXPR, alloc_node,
>                                            nullptr_node,
>                                            complain);
> -         rval = build_conditional_expr (input_location, ifexp, rval,
> -                                        alloc_node, complain);
> +         rval = build_conditional_expr (location_t (input_location), ifexp,
> +                                        rval, alloc_node, complain);
>         }
>
>        /* Perform the allocation before anything else, so that ALLOC_NODE
> @@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
>        && from_array != 2)
>      {
>        tree e;
> -      tree m = cp_build_binary_op (input_location,
> +      tree m = cp_build_binary_op (location_t (input_location),
>                                    MINUS_EXPR, maxindex, iterator,
>                                    complain);
>
>        /* Flatten multi-dimensional array since build_vec_delete only
>          expects one-dimensional array.  */
>        if (TREE_CODE (type) == ARRAY_TYPE)
> -       m = cp_build_binary_op (input_location,
> +       m = cp_build_binary_op (location_t (input_location),
>                                 MULT_EXPR, m,
>                                 /* Avoid mixing signed and unsigned.  */
>                                 convert (TREE_TYPE (m),
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index f259515a498..72f32487e51 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
>           elf_out to (fd, e);
>           if (to.begin ())
>             {
> -             auto loc = input_location;
> +             location_t loc = input_location;
>               /* So crashes finger-point the module decl.  */
>               input_location = state->loc;
>               state->write (&to, reader);
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index 02daa7a6f6a..e90ee873a94 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
>    finish_init_stmt (statement);
>
>    /* The new for condition.  */
> -  condition = build_x_binary_op (input_location, NE_EXPR,
> +  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
>                                  begin, ERROR_MARK,
>                                  end, ERROR_MARK,
>                                  NULL, tf_warning_or_error);
> @@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
>           if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
>             {
>               if (cxx_dialect >= cxx17
> -                 && (build_x_binary_op (input_location, NE_EXPR,
> +                 && (build_x_binary_op (location_t (input_location), NE_EXPR,
>                                          *begin, ERROR_MARK,
>                                          *end, ERROR_MARK,
>                                          NULL, tf_none)
> @@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
>                                         tf_warning_or_error);
>             }
>           else
> -           lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
> -                                    ERROR_MARK, NULL, tf_warning_or_error);
> +           lhs = build_x_binary_op (location_t (input_location), op, lhs,
> +                                    ERROR_MARK, rhs, ERROR_MARK, NULL,
> +                                    tf_warning_or_error);
>         }
>      }
>    while (token->type == CPP_PLUS || token->type == CPP_MINUS);
> @@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
>    if (CLASS_TYPE_P (iter_type))
>      cond = build2 (NE_EXPR, boolean_type_node, begin, end);
>    else
> -    cond = build_x_binary_op (input_location, NE_EXPR,
> +    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
>                               begin, ERROR_MARK,
>                               end, ERROR_MARK,
>                               NULL, tf_warning_or_error);
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f2039e09cd7..b679e34bfa4 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, tsubst_flags_t complain)
>      case COMPOUND_EXPR:
>        return build_x_compound_expr (input_location, left, right, complain);
>      default:
> -      return build_x_binary_op (input_location, code,
> +      return build_x_binary_op (location_t (input_location), code,
>                                  left, TREE_CODE (left),
>                                  right, TREE_CODE (right),
>                                  /*overload=*/NULL,
> @@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
>         warning_sentinel s4(warn_tautological_compare, was_dep);
>
>         tree r = build_x_binary_op
> -         (input_location, TREE_CODE (t),
> +         (location_t (input_location), TREE_CODE (t),
>            op0,
>            (warning_suppressed_p (TREE_OPERAND (t, 0))
>             ? ERROR_MARK
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index a483e1f988d..98aa9e69612 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
>                || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
>                || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
>
> -  return composite_pointer_type (input_location, t1, t2,
> +  return composite_pointer_type (location_t (input_location), t1, t2,
>                                  error_mark_node, error_mark_node,
>                                   CPO_CONVERSION, tf_warning_or_error);
>  }
> @@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
>
>      warn_array_subscript_with_type_char (loc, idx);
>
> -    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
> +    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
> +                             complain);
>      if (first)
>        ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
>      ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
> @@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>         {
>           int flag_sanitize_save;
>         case ptrmemfunc_vbit_in_pfn:
> -         e1 = cp_build_binary_op (input_location,
> +         e1 = cp_build_binary_op (location_t (input_location),
>                                    BIT_AND_EXPR, idx, integer_one_node,
>                                    complain);
> -         idx = cp_build_binary_op (input_location,
> +         idx = cp_build_binary_op (location_t (input_location),
>                                     MINUS_EXPR, idx, integer_one_node,
>                                     complain);
>           if (idx == error_mark_node)
> @@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>           break;
>
>         case ptrmemfunc_vbit_in_delta:
> -         e1 = cp_build_binary_op (input_location,
> +         e1 = cp_build_binary_op (location_t (input_location),
>                                    BIT_AND_EXPR, delta, integer_one_node,
>                                    complain);
>           /* Don't instrument the RSHIFT_EXPR we're about to create because
> @@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>              well with SAVE_EXPRs therein.  */
>           flag_sanitize_save = flag_sanitize;
>           flag_sanitize = 0;
> -         delta = cp_build_binary_op (input_location,
> +         delta = cp_build_binary_op (location_t (input_location),
>                                       RSHIFT_EXPR, delta, integer_one_node,
>                                       complain);
>           flag_sanitize = flag_sanitize_save;
> @@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>                      cp_build_addr_expr (e2, complain));
>
>        e2 = fold_convert (TREE_TYPE (e3), e2);
> -      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
> +      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
> +                                  complain);
>        if (e1 == error_mark_node)
>         return error_mark_node;
>
> @@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
>
>      case TRUTH_NOT_EXPR:
>        if (gnu_vector_type_p (TREE_TYPE (arg)))
> -       return cp_build_binary_op (input_location, EQ_EXPR, arg,
> +       return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
>                                    build_zero_cst (TREE_TYPE (arg)), complain);
>        arg = perform_implicit_conversion (boolean_type_node, arg,
>                                          complain);
> @@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
>           if (TREE_CODE (expr) == PTRMEM_CST)
>             expr = cplus_expand_constant (expr);
>
> -         tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
> +         tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
> +                                         expr,
>                                           build_int_cst (TREE_TYPE (expr), -1),
>                                           complain);
>           tree op1 = build_nop (ptrdiff_type_node, expr);
> -         tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
> -                                        complain);
> +         tree op2 = cp_build_binary_op (location_t (input_location),
> +                                        PLUS_EXPR, op1, delta, complain);
>
>           expr = fold_build3_loc (input_location,
>                                   COND_EXPR, ptrdiff_type_node, cond, op1, op2);
> @@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>         tree op2 = TREE_OPERAND (lhs, 2);
>         if (TREE_CODE (op2) != THROW_EXPR)
>           op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
> -       tree cond = build_conditional_expr (input_location,
> +       tree cond = build_conditional_expr (location_t (input_location),
>                                             TREE_OPERAND (lhs, 0), op1, op2,
>                                             complain);
>
> @@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>             /* Do the default thing.  */;
>           else
>             {
> -             result = build_new_op (input_location, MODIFY_EXPR,
> +             result = build_new_op (location_t (input_location), MODIFY_EXPR,
>                                      LOOKUP_NORMAL, lhs, rhs,
>                                      make_node (NOP_EXPR), /*overload=*/NULL,
>                                      complain);
> @@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
>        if (!integer_zerop (n))
>         {
>           if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
> -           n = cp_build_binary_op (input_location,
> +           n = cp_build_binary_op (location_t (input_location),
>                                     LSHIFT_EXPR, n, integer_one_node,
>                                     complain);
> -         delta = cp_build_binary_op (input_location,
> +         delta = cp_build_binary_op (location_t (input_location),
>                                       PLUS_EXPR, delta, n, complain);
>         }
>        return build_ptrmemfunc1 (to_type, delta, npfn);
> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index d58586f2526..3f68d1d79eb 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
>    auto_diagnostic_group d;
>    va_list ap;
>    va_start (ap, gmsgid);
> -  rich_location richloc (line_table, input_location);
> +  rich_location richloc (line_table, UNKNOWN_LOCATION);
>    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
>    va_end (ap);
>
> diff --git a/gcc/input.c b/gcc/input.c
> index 9e39e7df83c..1843c3077aa 100644
> --- a/gcc/input.c
> +++ b/gcc/input.c
> @@ -122,7 +122,7 @@ public:
>
>  /* Current position in real source file.  */
>
> -location_t input_location = UNKNOWN_LOCATION;
> +poisonable<location_t> input_location (UNKNOWN_LOCATION);
>
>  class line_maps *line_table;
>
> diff --git a/gcc/input.h b/gcc/input.h
> index f1ef5d76cfd..2b96ce8008e 100644
> --- a/gcc/input.h
> +++ b/gcc/input.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #ifndef GCC_INPUT_H
>  #define GCC_INPUT_H
>
> +#include "poison.h"
>  #include "line-map.h"
>
>  extern GTY(()) class line_maps *line_table;
> @@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
>  extern location_t expansion_point_location_if_in_system_header (location_t);
>  extern location_t expansion_point_location (location_t);
>
> -extern location_t input_location;
> +extern poisonable<location_t> input_location;
>
>  #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
>  #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
> diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
> index 3cfcd0b1a57..9ecb91cc56b 100644
> --- a/gcc/objc/objc-next-runtime-abi-02.c
> +++ b/gcc/objc/objc-next-runtime-abi-02.c
> @@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
>                                fold_convert (rcv_p, integer_zero_node), 1);
>
>  #ifdef OBJCPLUS
> -      ret_val = build_conditional_expr (input_location,
> +      ret_val = build_conditional_expr (location_t (input_location),
>                                         ifexp, ret_val, ftree,
>                                         tf_warning_or_error);
>  #else
> --
> 2.20.1
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 4/4] poison input_location and cfun in one spot
  2021-06-30  5:35 ` [PATCH 4/4] poison input_location and cfun in one spot Trevor Saunders
@ 2021-06-30  9:02   ` Richard Biener
  0 siblings, 0 replies; 25+ messages in thread
From: Richard Biener @ 2021-06-30  9:02 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>
> This simply confirms we can poison them in a small region.
>
> boostrapped and regtested on x86_64-linux-gnu, ok?

So this shows the approach doesn't really scale since it's necessarily
at most function-scope granularity rather than file-scope as possible
with the existing #pragma (maybe add the possibility to un-poison
identifiers or a push/pop mechanism).

> Trev
>
> gcc/ChangeLog:
>
>         * gimple-range.cc (disable_ranger): Prevent access to cfun and
>         input_location.
> ---
>  gcc/gimple-range.cc | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> index 1851339c528..d4a3a6e46be 100644
> --- a/gcc/gimple-range.cc
> +++ b/gcc/gimple-range.cc
> @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "config.h"
>  #include "system.h"
>  #include "coretypes.h"
> +#include "poison.h"
>  #include "backend.h"
>  #include "tree.h"
>  #include "gimple.h"
> @@ -509,6 +510,8 @@ enable_ranger (struct function *fun)
>  void
>  disable_ranger (struct function *fun)
>  {
> +  auto_poison<location_t> pil (input_location);
> +  auto_poison<function *> pcfun (cfun_poison);
>    delete fun->x_range_query;
>
>    fun->x_range_query = &global_ranges;
> --
> 2.20.1
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30  9:00   ` Richard Biener
@ 2021-06-30 12:33     ` Trevor Saunders
  2021-06-30 19:09       ` Richard Biener
  0 siblings, 1 reply; 25+ messages in thread
From: Trevor Saunders @ 2021-06-30 12:33 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

On Wed, Jun 30, 2021 at 11:00:37AM +0200, Richard Biener wrote:
> On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> >
> > This makes it possible to assert if input_location is used during the lifetime
> > of a scope.  This will allow us to find places that currently use it within a
> > function and its callees, or prevent adding uses within the lifetime of a
> > function after all existing uses are removed.
> >
> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> 
> I'm not sure about the general approach but I have comments about
> input_location.
> 
> IMHO a good first step would be to guard the input_location declaration with sth
> like
> 
> #ifndef GCC_NEED_INPUT_LOCATION
> extern location_t input_location;
> #endif

I think that's another reasonable step, my one concern is that it can be
useful to push the usage of input_location, or any other global from the
bottom of the stack to a caller that can provide a better argument
eventually, but first just use the global.  Doing this sort of
refactoring is harder if you need to add files with callers to the
whitelist, and kind of defeats the point of the whitelist.  Consider the
below commit, that is untested, but perhaps I should have included in
this series as somewhat related.

As for this approach being limited to functions that's somewhat true,
but since it effects all functions called while its on the stack, it
would mean once enough infrastructure is fixed, we could add one the
execute method of a pass and nothing in the pass could touch
input_location.  The limit also means that it doesn't get in the way of
the above sort of refactoring, but as it proceeds lower level functions
that now take explicit arguments can be called from contexts that ban
use of input_location.

Trev

From efd04d2df4163dd930f489d9fba1455bfb368114 Mon Sep 17 00:00:00 2001
From: Trevor Saunders <tbsaunde@tbsaunde.org>
Date: Sun, 27 Jun 2021 02:10:26 -0400
Subject: [PATCH] force decls to be allocated through build_decl to initialize
 them
To: gcc-patches@gcc.gnu.org

prior to this commit all calls to build_decl used input_location, even if
temporarily  until build_decl reset the location to something else that it was
told was the proper location.  To avoid using the global we need the caller to
pass in the location it wants, however that's not possible with make_node since
it makes other types of nodes.  So we force all callers who wish to make a decl
to go through build_decl which already takes a location argument.  To avoid
changing behavior this just explicitly passes in input_location to build_decl
for callers of make_node that create a decl, however it would seem in many of
these cases that the location of the decl being coppied might be a better
location.
---
 gcc/cfgexpand.c              |  8 +++---
 gcc/cp/cp-gimplify.c         |  5 ++--
 gcc/fortran/trans-decl.c     |  5 ++--
 gcc/fortran/trans-types.c    |  4 +--
 gcc/ipa-param-manipulation.c |  8 +++---
 gcc/objc/objc-act.c          | 16 +++++-------
 gcc/omp-simd-clone.c         |  4 +--
 gcc/stor-layout.c            |  2 +-
 gcc/tree-inline.c            | 13 +++++-----
 gcc/tree-into-ssa.c          |  4 +--
 gcc/tree-nested.c            | 24 ++++++++----------
 gcc/tree-ssa-ccp.c           |  4 +--
 gcc/tree-ssa-loop-ivopts.c   |  4 +--
 gcc/tree-ssa-phiopt.c        |  8 +++---
 gcc/tree-ssa-reassoc.c       |  4 +--
 gcc/tree-ssa.c               |  4 +--
 gcc/tree.c                   | 49 ++++++++++++++++++------------------
 gcc/tree.h                   |  9 ++++++-
 gcc/varasm.c                 | 12 ++++-----
 19 files changed, 93 insertions(+), 94 deletions(-)

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 3edd53c37dc..fea8c837c80 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4342,10 +4342,10 @@ avoid_deep_ter_for_debug (gimple *stmt, int depth)
 	  tree &vexpr = deep_ter_debug_map->get_or_insert (use);
 	  if (vexpr != NULL)
 	    continue;
-	  vexpr = make_node (DEBUG_EXPR_DECL);
+	  vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+			      TREE_TYPE (use));
 	  gimple *def_temp = gimple_build_debug_bind (vexpr, use, g);
 	  DECL_ARTIFICIAL (vexpr) = 1;
-	  TREE_TYPE (vexpr) = TREE_TYPE (use);
 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (use)));
 	  gimple_stmt_iterator gsi = gsi_for_stmt (g);
 	  gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
@@ -5899,14 +5899,14 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
 		       temporary.  */
 		    gimple *debugstmt;
 		    tree value = gimple_assign_rhs_to_tree (def);
-		    tree vexpr = make_node (DEBUG_EXPR_DECL);
 		    rtx val;
 		    machine_mode mode;
 
 		    set_curr_insn_location (gimple_location (def));
 
+		    tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
+					     nullptr, TREE_TYPE (value));
 		    DECL_ARTIFICIAL (vexpr) = 1;
-		    TREE_TYPE (vexpr) = TREE_TYPE (value);
 		    if (DECL_P (value))
 		      mode = DECL_MODE (value);
 		    else
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 00b7772fe0d..d537e547169 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1217,8 +1217,9 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 	      /* Omit from the GENERIC, the back-end can't handle it.  */;
 	    else
 	      {
-		tree using_directive = make_node (IMPORTED_DECL);
-		TREE_TYPE (using_directive) = void_type_node;
+		tree using_directive = build_decl (input_location,
+						   IMPORTED_DECL, nullptr,
+						   void_type_node);
 		DECL_CONTEXT (using_directive) = current_function_decl;
 
 		IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 479ba6fa6ce..b726c2f2bdc 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -5262,10 +5262,9 @@ generate_namelist_decl (gfc_symbol * sym)
       CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, nml->sym->backend_decl);
     }
 
-  decl = make_node (NAMELIST_DECL);
-  TREE_TYPE (decl) = void_type_node;
+  decl = build_decl (input_location, NAMELIST_DECL, get_identifier (sym->name),
+		     void_type_node);
   NAMELIST_DECL_ASSOCIATED_DECL (decl) = build_constructor (NULL_TREE, nml_decls);
-  DECL_NAME (decl) = get_identifier (sym->name);
   return decl;
 }
 
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 5582e404df9..8b4d5c99665 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3417,9 +3417,9 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
   if (!base_decl)
     {
-      base_decl = make_node (DEBUG_EXPR_DECL);
+      base_decl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+			      indirect ? build_pointer_type (ptype) : ptype);
       DECL_ARTIFICIAL (base_decl) = 1;
-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
       SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
     }
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
index f2d91476655..242fa4dee1d 100644
--- a/gcc/ipa-param-manipulation.c
+++ b/gcc/ipa-param-manipulation.c
@@ -834,9 +834,9 @@ ipa_param_adjustments::modify_call (gcall *stmt,
 	      }
 	  if (ddecl == NULL)
 	    {
-	      ddecl = make_node (DEBUG_EXPR_DECL);
+	      ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				  TREE_TYPE (origin));
 	      DECL_ARTIFICIAL (ddecl) = 1;
-	      TREE_TYPE (ddecl) = TREE_TYPE (origin);
 	      SET_DECL_MODE (ddecl, DECL_MODE (origin));
 
 	      vec_safe_push (*debug_args, origin);
@@ -1883,10 +1883,10 @@ ipa_param_body_adjustments::reset_debug_stmts ()
 	    gcc_assert (is_gimple_debug (stmt));
 	    if (vexpr == NULL && gsip != NULL)
 	      {
-		vexpr = make_node (DEBUG_EXPR_DECL);
+		vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				    TREE_TYPE (name));
 		def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
 		DECL_ARTIFICIAL (vexpr) = 1;
-		TREE_TYPE (vexpr) = TREE_TYPE (name);
 		SET_DECL_MODE (vexpr, DECL_MODE (decl));
 		gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
 	      }
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 8d106a4de26..259ce520143 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1295,12 +1295,11 @@ objc_add_property_declaration (location_t location, tree decl,
     }
 
   /* Create a PROPERTY_DECL node.  */
-  tree property_decl = make_node (PROPERTY_DECL);
+  tree property_decl = build_decl (DECL_SOURCE_LOCATION (decl), PROPERTY_DECL,
+				   nullptr, TREE_TYPE (decl));
 
   /* Copy the basic information from the original decl.  */
   tree p_type = TREE_TYPE (decl);
-  TREE_TYPE (property_decl) = p_type;
-  DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
   TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
 
   /* Add property-specific information.  */
@@ -1434,10 +1433,9 @@ maybe_make_artificial_property_decl (tree interface, tree implementation,
       /* Create an artificial property declaration with the
 	 information we collected on the type and getter/setter
 	 names.  */
-      property_decl = make_node (PROPERTY_DECL);
+      property_decl = build_decl (input_location, PROPERTY_DECL, nullptr,
+				  type);
 
-      TREE_TYPE (property_decl) = type;
-      DECL_SOURCE_LOCATION (property_decl) = input_location;
       TREE_DEPRECATED (property_decl) = 0;
       DECL_ARTIFICIAL (property_decl) = 1;
 
@@ -4889,9 +4887,8 @@ objc_build_keyword_decl (tree key_name, tree arg_type,
   /* If no type is specified, default to "id".  */
   arg_type = adjust_type_for_id_default (arg_type);
 
-  keyword_decl = make_node (KEYWORD_DECL);
+  keyword_decl = build_decl (input_location, KEYWORD_DECL, nullptr, arg_type);
 
-  TREE_TYPE (keyword_decl) = arg_type;
   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
   KEYWORD_KEY_NAME (keyword_decl) = key_name;
   DECL_ATTRIBUTES (keyword_decl) = attributes;
@@ -4975,8 +4972,7 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector,
      type of the method.  We may want to change this, and store the
      entire function type in there (eg, it may be used to simplify
      dealing with attributes below).  */
-  method_decl = make_node (code);
-  TREE_TYPE (method_decl) = ret_type;
+  method_decl = build_decl (input_location, code, nullptr, ret_type);
 
   /* If we have a keyword selector, create an identifier_node that
      represents the full selector name (`:' included)...  */
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index b772b7ff520..03189f4c50f 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -910,10 +910,10 @@ ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
       gimple *stmt;
       if (is_gimple_debug (info->stmt))
 	{
-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				   TREE_TYPE (repl));
 	  stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
 	  DECL_ARTIFICIAL (vexpr) = 1;
-	  TREE_TYPE (vexpr) = TREE_TYPE (repl);
 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (repl)));
 	  repl = vexpr;
 	}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 242452f2acf..7811fc6c302 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2024,7 +2024,7 @@ finalize_type_size (tree type)
 static tree
 start_bitfield_representative (tree field)
 {
-  tree repr = make_node (FIELD_DECL);
+  tree repr = build_decl (input_location, FIELD_DECL, nullptr, nullptr);
   DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field);
   /* Force the representative to begin at a BITS_PER_UNIT aligned
      boundary - C++ may use tail-padding of a base object to
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 9e041ca4d56..0204ce20282 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -193,7 +193,6 @@ remap_ssa_name (tree name, copy_body_data *id)
 	  && id->entry_bb == NULL
 	  && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
 	{
-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
 	  gimple *def_temp;
 	  gimple_stmt_iterator gsi;
 	  tree val = SSA_NAME_VAR (name);
@@ -210,9 +209,11 @@ remap_ssa_name (tree name, copy_body_data *id)
 	  n = id->decl_map->get (val);
 	  if (n && TREE_CODE (*n) == DEBUG_EXPR_DECL)
 	    return *n;
+
+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				   TREE_TYPE (name));
 	  def_temp = gimple_build_debug_source_bind (vexpr, val, NULL);
 	  DECL_ARTIFICIAL (vexpr) = 1;
-	  TREE_TYPE (vexpr) = TREE_TYPE (name);
 	  SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (name)));
 	  gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
 	  gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
@@ -6494,9 +6495,9 @@ tree_function_versioning (tree old_decl, tree new_decl,
 	      debug_args = decl_debug_args_insert (new_decl);
 	      len = vec_safe_length (*debug_args);
 	    }
-	  ddecl = make_node (DEBUG_EXPR_DECL);
+	  ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+			      TREE_TYPE (parm));
 	  DECL_ARTIFICIAL (ddecl) = 1;
-	  TREE_TYPE (ddecl) = TREE_TYPE (parm);
 	  SET_DECL_MODE (ddecl, DECL_MODE (parm));
 	  vec_safe_push (*debug_args, DECL_ORIGIN (parm));
 	  vec_safe_push (*debug_args, ddecl);
@@ -6525,10 +6526,10 @@ tree_function_versioning (tree old_decl, tree new_decl,
 		var = TREE_CHAIN (var);
 	      if (var == NULL_TREE)
 		break;
-	      vexpr = make_node (DEBUG_EXPR_DECL);
 	      tree parm = (**debug_args)[i];
+	      vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				  TREE_TYPE (parm));
 	      DECL_ARTIFICIAL (vexpr) = 1;
-	      TREE_TYPE (vexpr) = TREE_TYPE (parm);
 	      SET_DECL_MODE (vexpr, DECL_MODE (parm));
 	      def_temp = gimple_build_debug_bind (var, vexpr, NULL);
 	      gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 8045e34df26..f9933305957 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1284,10 +1284,10 @@ rewrite_debug_stmt_uses (gimple *stmt)
 	      if (def == NULL_TREE)
 		{
 		  gimple *def_temp;
-		  def = make_node (DEBUG_EXPR_DECL);
+		  def = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				    TREE_TYPE (var));
 		  def_temp = gimple_build_debug_source_bind (def, var, NULL);
 		  DECL_ARTIFICIAL (def) = 1;
-		  TREE_TYPE (def) = TREE_TYPE (var);
 		  SET_DECL_MODE (def, DECL_MODE (var));
 		  gsi =
 		 gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 9edd922a303..37e229477ec 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -394,8 +394,8 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
   if (!*slot)
     {
       tree type = get_frame_type (info);
-      tree field = make_node (FIELD_DECL);
-      DECL_NAME (field) = DECL_NAME (decl);
+      tree field = build_decl (input_location, FIELD_DECL, DECL_NAME (decl),
+			       nullptr);
 
       if (use_pointer_in_frame (decl))
 	{
@@ -510,9 +510,8 @@ get_chain_field (struct nesting_info *info)
     {
       tree type = build_pointer_type (get_frame_type (info->outer));
 
-      field = make_node (FIELD_DECL);
-      DECL_NAME (field) = get_identifier ("__chain");
-      TREE_TYPE (field) = type;
+      field = build_decl (input_location, FIELD_DECL,
+			  get_identifier ("__chain"), type);
       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
       DECL_NONADDRESSABLE_P (field) = 1;
 
@@ -694,9 +693,7 @@ lookup_element_for_decl (struct nesting_info *info, tree decl,
 static tree
 create_field_for_decl (struct nesting_info *info, tree decl, tree type)
 {
-  tree field = make_node (FIELD_DECL);
-  DECL_NAME (field) = DECL_NAME (decl);
-  TREE_TYPE (field) = type;
+  tree field = build_decl (input_location, FIELD_DECL, DECL_NAME (decl), type);
   TREE_ADDRESSABLE (field) = 1;
   insert_field_into_struct (get_frame_type (info), field);
   return field;
@@ -783,9 +780,8 @@ get_nl_goto_field (struct nesting_info *info)
       type = build_array_type
 	(type, build_index_type (size_int (size)));
 
-      field = make_node (FIELD_DECL);
-      DECL_NAME (field) = get_identifier ("__nl_goto_buf");
-      TREE_TYPE (field) = type;
+      field = build_decl (input_location, FIELD_DECL,
+			  get_identifier ("__nl_goto_buf"), type);
       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
       TREE_ADDRESSABLE (field) = 1;
 
@@ -3378,10 +3374,10 @@ finalize_nesting_tree_1 (struct nesting_info *root)
       /* Create a field in the FRAME record to hold the frame base address for
 	 this stack frame.  Since it will be used only by the debugger, put it
 	 at the end of the record in order not to shift all other offsets.  */
-      tree fb_decl = make_node (FIELD_DECL);
+      tree fb_decl = build_decl (input_location, FIELD_DECL,
+				 get_identifier ("FRAME_BASE.PARENT"),
+				 ptr_type_node);
 
-      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
-      TREE_TYPE (fb_decl) = ptr_type_node;
       TREE_ADDRESSABLE (fb_decl) = 1;
       DECL_CONTEXT (fb_decl) = root->frame_type;
       TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS (root->frame_type),
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 42585412325..dc6f412c02d 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3067,9 +3067,9 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
       tree temp = NULL_TREE;
       if (!throws || after || single_pred_p (e->dest))
 	{
-	  temp = make_node (DEBUG_EXPR_DECL);
+	  temp = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+			     TREE_TYPE (lhs));
 	  DECL_ARTIFICIAL (temp) = 1;
-	  TREE_TYPE (temp) = TREE_TYPE (lhs);
 	  SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
 	  tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
 	  g = gimple_build_debug_bind (temp, t, g);
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 12a8a49a307..953b3d0b2f1 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -7677,9 +7677,9 @@ remove_unused_ivs (struct ivopts_data *data, bitmap toremove)
 	      comp = unshare_expr (comp);
 	      if (count > 1)
 		{
-		  tree vexpr = make_node (DEBUG_EXPR_DECL);
+		  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
+					   nullptr, TREE_TYPE (comp));
 		  DECL_ARTIFICIAL (vexpr) = 1;
-		  TREE_TYPE (vexpr) = TREE_TYPE (comp);
 		  if (SSA_NAME_VAR (def))
 		    SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (def)));
 		  else
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 1777bff2f7c..25589716a11 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -2302,18 +2302,18 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
 	     all floating point numbers should be comparable.  */
 	  gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
 	  tree type = TREE_TYPE (phires);
-	  tree temp1 = make_node (DEBUG_EXPR_DECL);
+	  tree temp1 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				   type);
 	  DECL_ARTIFICIAL (temp1) = 1;
-	  TREE_TYPE (temp1) = type;
 	  SET_DECL_MODE (temp1, TYPE_MODE (type));
 	  tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
 	  t = build3 (COND_EXPR, type, t, build_one_cst (type),
 		      build_int_cst (type, -1));
 	  gimple *g = gimple_build_debug_bind (temp1, t, phi);
 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-	  tree temp2 = make_node (DEBUG_EXPR_DECL);
+	  tree temp2 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				   type);
 	  DECL_ARTIFICIAL (temp2) = 1;
-	  TREE_TYPE (temp2) = type;
 	  SET_DECL_MODE (temp2, TYPE_MODE (type));
 	  t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
 	  t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 2dd4435b981..48f6117a731 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1214,14 +1214,14 @@ make_new_ssa_for_def (gimple *stmt, enum tree_code opcode, tree op)
 	{
 	  if (new_debug_lhs == NULL_TREE)
 	    {
-	      new_debug_lhs = make_node (DEBUG_EXPR_DECL);
+	      new_debug_lhs = build_decl (input_location, DEBUG_EXPR_DECL,
+					  nullptr, TREE_TYPE (lhs));
 	      gdebug *def_temp
 		= gimple_build_debug_bind (new_debug_lhs,
 					   build2 (opcode, TREE_TYPE (lhs),
 						   new_lhs, op),
 					   stmt);
 	      DECL_ARTIFICIAL (new_debug_lhs) = 1;
-	      TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
 	      SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
 	      gimple_set_uid (def_temp, gimple_uid (stmt));
 	      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4cc400d3c2e..83caadb37c8 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -434,14 +434,14 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
       else
 	{
 	  gdebug *def_temp;
-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
+				   TREE_TYPE (value));
 
 	  def_temp = gimple_build_debug_bind (vexpr,
 					      unshare_expr (value),
 					      def_stmt);
 
 	  DECL_ARTIFICIAL (vexpr) = 1;
-	  TREE_TYPE (vexpr) = TREE_TYPE (value);
 	  if (DECL_P (value))
 	    SET_DECL_MODE (vexpr, DECL_MODE (value));
 	  else
diff --git a/gcc/tree.c b/gcc/tree.c
index 1aa6e557a04..a90097a51c6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1175,7 +1175,7 @@ allocate_decl_uid (void)
    Achoo!  I got a code in the node.  */
 
 tree
-make_node (enum tree_code code MEM_STAT_DECL)
+make_node (enum tree_code code, make_node_caller caller MEM_STAT_DECL)
 {
   tree t;
   enum tree_code_class type = TREE_CODE_CLASS (code);
@@ -1194,27 +1194,7 @@ make_node (enum tree_code code MEM_STAT_DECL)
       break;
 
     case tcc_declaration:
-      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
-	{
-	  if (code == FUNCTION_DECL)
-	    {
-	      SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
-	      SET_DECL_MODE (t, FUNCTION_MODE);
-	    }
-	  else
-	    SET_DECL_ALIGN (t, 1);
-	}
-      DECL_SOURCE_LOCATION (t) = input_location;
-      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
-	DECL_UID (t) = --next_debug_decl_uid;
-      else
-	{
-	  DECL_UID (t) = allocate_decl_uid ();
-	  SET_DECL_PT_UID (t, -1);
-	}
-      if (TREE_CODE (t) == LABEL_DECL)
-	LABEL_DECL_UID (t) = -1;
-
+      gcc_assert (caller == BUILD_DECL_MKNODE_CALLER);
       break;
 
     case tcc_type:
@@ -5257,10 +5237,29 @@ tree
 build_decl (location_t loc, enum tree_code code, tree name,
     		 tree type MEM_STAT_DECL)
 {
-  tree t;
-
-  t = make_node (code PASS_MEM_STAT);
+  tree t = make_node (code, BUILD_DECL_MKNODE_CALLER PASS_MEM_STAT);
   DECL_SOURCE_LOCATION (t) = loc;
+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+    {
+      if (code == FUNCTION_DECL)
+	{
+	  SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
+	  SET_DECL_MODE (t, FUNCTION_MODE);
+	}
+      else
+	SET_DECL_ALIGN (t, 1);
+    }
+
+  if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+    DECL_UID (t) = --next_debug_decl_uid;
+  else
+    {
+      DECL_UID (t) = allocate_decl_uid ();
+      SET_DECL_PT_UID (t, -1);
+    }
+
+  if (TREE_CODE (t) == LABEL_DECL)
+    LABEL_DECL_UID (t) = -1;
 
 /*  if (type == error_mark_node)
     type = integer_type_node; */
diff --git a/gcc/tree.h b/gcc/tree.h
index 8bdf16d8b4a..86dd32354f2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4357,11 +4357,18 @@ extern size_t tree_code_size (enum tree_code);
 /* Allocate and return a new UID from the DECL_UID namespace.  */
 extern int allocate_decl_uid (void);
 
+/* expected callers of make_node.  */
+enum make_node_caller
+{
+  UNKNOWN_MKNODE_CALLER,
+  BUILD_DECL_MKNODE_CALLER
+};
+
 /* Lowest level primitive for allocating a node.
    The TREE_CODE is the only argument.  Contents are initialized
    to zero except for a few of the common fields.  */
 
-extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
+extern tree make_node (enum tree_code, enum make_node_caller caller = UNKNOWN_MKNODE_CALLER CXX_MEM_STAT_INFO);
 
 /* Free tree node.  */
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 53cf6dea3f3..fa6799e48fb 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -8229,21 +8229,21 @@ output_file_directive (FILE *asm_file, const char *input_name)
 rtx
 make_debug_expr_from_rtl (const_rtx exp)
 {
-  tree ddecl = make_node (DEBUG_EXPR_DECL), type;
+  tree type;
   machine_mode mode = GET_MODE (exp);
   rtx dval;
 
-  DECL_ARTIFICIAL (ddecl) = 1;
   if (REG_P (exp) && REG_EXPR (exp))
     type = TREE_TYPE (REG_EXPR (exp));
   else if (MEM_P (exp) && MEM_EXPR (exp))
     type = TREE_TYPE (MEM_EXPR (exp));
   else
     type = NULL_TREE;
-  if (type && TYPE_MODE (type) == mode)
-    TREE_TYPE (ddecl) = type;
-  else
-    TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
+  if (!type || TYPE_MODE (type) != mode)
+    type = lang_hooks.types.type_for_mode (mode, 1);
+
+  tree ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr, type);
+  DECL_ARTIFICIAL (ddecl) = 1;
   SET_DECL_MODE (ddecl, mode);
   dval = gen_rtx_DEBUG_EXPR (mode);
   DEBUG_EXPR_TREE_DECL (dval) = ddecl;
-- 
2.20.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
  2021-06-30  9:00   ` Richard Biener
@ 2021-06-30 15:13   ` David Malcolm
  2021-06-30 19:34     ` Jason Merrill
  2021-07-01 10:16     ` Trevor Saunders
  2021-07-02 19:20   ` Martin Sebor
  2 siblings, 2 replies; 25+ messages in thread
From: David Malcolm @ 2021-06-30 15:13 UTC (permalink / raw)
  To: Trevor Saunders, gcc-patches

On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> This makes it possible to assert if input_location is used during the
> lifetime
> of a scope.  This will allow us to find places that currently use it
> within a
> function and its callees, or prevent adding uses within the lifetime
> of a
> function after all existing uses are removed.
> 
> bootstrapped and regtested on x86_64-linux-gnu, ok?
> 
> Trev

[...snip...]

> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index d58586f2526..3f68d1d79eb 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
>    auto_diagnostic_group d;
>    va_list ap;
>    va_start (ap, gmsgid);
> -  rich_location richloc (line_table, input_location);
> +  rich_location richloc (line_table, UNKNOWN_LOCATION);
>    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
>    va_end (ap);
>  

I actually make use of this in the analyzer: the analyzer sets
input_location to stmt->location when analyzing a given stmt - that
way, if the analyzer ICEs, the ICE is shown at the code construct that
crashed the analyzer.

This behavior is useful to me, and would be lost with the proposed
patch.

Is there a better way of doing what I'm doing?

Is the long-term goal of the patch kit to reduce our reliance on global
variables?  Are we ultimately still going to need a variable for "where
to show the ICE if gcc crashes"?  (perhaps stashing it in the
diagnostic_context???)

Hope this is constructive
Dave


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30 12:33     ` Trevor Saunders
@ 2021-06-30 19:09       ` Richard Biener
  2021-07-01 10:23         ` Trevor Saunders
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Biener @ 2021-06-30 19:09 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On June 30, 2021 2:33:30 PM GMT+02:00, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>On Wed, Jun 30, 2021 at 11:00:37AM +0200, Richard Biener wrote:
>> On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders
><tbsaunde@tbsaunde.org> wrote:
>> >
>> > This makes it possible to assert if input_location is used during
>the lifetime
>> > of a scope.  This will allow us to find places that currently use
>it within a
>> > function and its callees, or prevent adding uses within the
>lifetime of a
>> > function after all existing uses are removed.
>> >
>> > bootstrapped and regtested on x86_64-linux-gnu, ok?
>> 
>> I'm not sure about the general approach but I have comments about
>> input_location.
>> 
>> IMHO a good first step would be to guard the input_location
>declaration with sth
>> like
>> 
>> #ifndef GCC_NEED_INPUT_LOCATION
>> extern location_t input_location;
>> #endif
>
>I think that's another reasonable step, my one concern is that it can
>be
>useful to push the usage of input_location, or any other global from
>the
>bottom of the stack to a caller that can provide a better argument
>eventually, but first just use the global.  Doing this sort of
>refactoring is harder if you need to add files with callers to the
>whitelist, and kind of defeats the point of the whitelist.  Consider
>the
>below commit, that is untested, but perhaps I should have included in
>this series as somewhat related.
>
>As for this approach being limited to functions that's somewhat true,
>but since it effects all functions called while its on the stack, it
>would mean once enough infrastructure is fixed, we could add one the
>execute method of a pass and nothing in the pass could touch
>input_location.  The limit also means that it doesn't get in the way of
>the above sort of refactoring, but as it proceeds lower level functions
>that now take explicit arguments can be called from contexts that ban
>use of input_location.
>
>Trev
>
From efd04d2df4163dd930f489d9fba1455bfb368114 Mon Sep 17 00:00:00 2001
>From: Trevor Saunders <tbsaunde@tbsaunde.org>
>Date: Sun, 27 Jun 2021 02:10:26 -0400
>Subject: [PATCH] force decls to be allocated through build_decl to
>initialize
> them
>To: gcc-patches@gcc.gnu.org
>
>prior to this commit all calls to build_decl used input_location, even
>if
>temporarily  until build_decl reset the location to something else that
>it was
>told was the proper location.  To avoid using the global we need the
>caller to
>pass in the location it wants, however that's not possible with
>make_node since
>it makes other types of nodes.  So we force all callers who wish to
>make a decl
>to go through build_decl which already takes a location argument.  To
>avoid
>changing behavior this just explicitly passes in input_location to
>build_decl
>for callers of make_node that create a decl, however it would seem in
>many of
>these cases that the location of the decl being coppied might be a
>better
>location.

If make_node really uses input_location that's what should change (to UNONOWN_LOCATION).  But yes, it might change behavior to the worse... 

Richard. 

>---
> gcc/cfgexpand.c              |  8 +++---
> gcc/cp/cp-gimplify.c         |  5 ++--
> gcc/fortran/trans-decl.c     |  5 ++--
> gcc/fortran/trans-types.c    |  4 +--
> gcc/ipa-param-manipulation.c |  8 +++---
> gcc/objc/objc-act.c          | 16 +++++-------
> gcc/omp-simd-clone.c         |  4 +--
> gcc/stor-layout.c            |  2 +-
> gcc/tree-inline.c            | 13 +++++-----
> gcc/tree-into-ssa.c          |  4 +--
> gcc/tree-nested.c            | 24 ++++++++----------
> gcc/tree-ssa-ccp.c           |  4 +--
> gcc/tree-ssa-loop-ivopts.c   |  4 +--
> gcc/tree-ssa-phiopt.c        |  8 +++---
> gcc/tree-ssa-reassoc.c       |  4 +--
> gcc/tree-ssa.c               |  4 +--
> gcc/tree.c                   | 49 ++++++++++++++++++------------------
> gcc/tree.h                   |  9 ++++++-
> gcc/varasm.c                 | 12 ++++-----
> 19 files changed, 93 insertions(+), 94 deletions(-)
>
>diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
>index 3edd53c37dc..fea8c837c80 100644
>--- a/gcc/cfgexpand.c
>+++ b/gcc/cfgexpand.c
>@@ -4342,10 +4342,10 @@ avoid_deep_ter_for_debug (gimple *stmt, int
>depth)
> 	  tree &vexpr = deep_ter_debug_map->get_or_insert (use);
> 	  if (vexpr != NULL)
> 	    continue;
>-	  vexpr = make_node (DEBUG_EXPR_DECL);
>+	  vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+			      TREE_TYPE (use));
> 	  gimple *def_temp = gimple_build_debug_bind (vexpr, use, g);
> 	  DECL_ARTIFICIAL (vexpr) = 1;
>-	  TREE_TYPE (vexpr) = TREE_TYPE (use);
> 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (use)));
> 	  gimple_stmt_iterator gsi = gsi_for_stmt (g);
> 	  gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
>@@ -5899,14 +5899,14 @@ expand_gimple_basic_block (basic_block bb, bool
>disable_tail_calls)
> 		       temporary.  */
> 		    gimple *debugstmt;
> 		    tree value = gimple_assign_rhs_to_tree (def);
>-		    tree vexpr = make_node (DEBUG_EXPR_DECL);
> 		    rtx val;
> 		    machine_mode mode;
> 
> 		    set_curr_insn_location (gimple_location (def));
> 
>+		    tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
>+					     nullptr, TREE_TYPE (value));
> 		    DECL_ARTIFICIAL (vexpr) = 1;
>-		    TREE_TYPE (vexpr) = TREE_TYPE (value);
> 		    if (DECL_P (value))
> 		      mode = DECL_MODE (value);
> 		    else
>diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
>index 00b7772fe0d..d537e547169 100644
>--- a/gcc/cp/cp-gimplify.c
>+++ b/gcc/cp/cp-gimplify.c
>@@ -1217,8 +1217,9 @@ cp_genericize_r (tree *stmt_p, int
>*walk_subtrees, void *data)
> 	      /* Omit from the GENERIC, the back-end can't handle it.  */;
> 	    else
> 	      {
>-		tree using_directive = make_node (IMPORTED_DECL);
>-		TREE_TYPE (using_directive) = void_type_node;
>+		tree using_directive = build_decl (input_location,
>+						   IMPORTED_DECL, nullptr,
>+						   void_type_node);
> 		DECL_CONTEXT (using_directive) = current_function_decl;
> 
> 		IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
>diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
>index 479ba6fa6ce..b726c2f2bdc 100644
>--- a/gcc/fortran/trans-decl.c
>+++ b/gcc/fortran/trans-decl.c
>@@ -5262,10 +5262,9 @@ generate_namelist_decl (gfc_symbol * sym)
> CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, nml->sym->backend_decl);
>     }
> 
>-  decl = make_node (NAMELIST_DECL);
>-  TREE_TYPE (decl) = void_type_node;
>+  decl = build_decl (input_location, NAMELIST_DECL, get_identifier
>(sym->name),
>+		     void_type_node);
>NAMELIST_DECL_ASSOCIATED_DECL (decl) = build_constructor (NULL_TREE,
>nml_decls);
>-  DECL_NAME (decl) = get_identifier (sym->name);
>   return decl;
> }
> 
>diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
>index 5582e404df9..8b4d5c99665 100644
>--- a/gcc/fortran/trans-types.c
>+++ b/gcc/fortran/trans-types.c
>@@ -3417,9 +3417,9 @@ gfc_get_array_descr_info (const_tree type, struct
>array_descr_info *info)
>   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
>   if (!base_decl)
>     {
>-      base_decl = make_node (DEBUG_EXPR_DECL);
>+      base_decl = build_decl (input_location, DEBUG_EXPR_DECL,
>nullptr,
>+			      indirect ? build_pointer_type (ptype) : ptype);
>       DECL_ARTIFICIAL (base_decl) = 1;
>-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) :
>ptype;
>       SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
>       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
>     }
>diff --git a/gcc/ipa-param-manipulation.c
>b/gcc/ipa-param-manipulation.c
>index f2d91476655..242fa4dee1d 100644
>--- a/gcc/ipa-param-manipulation.c
>+++ b/gcc/ipa-param-manipulation.c
>@@ -834,9 +834,9 @@ ipa_param_adjustments::modify_call (gcall *stmt,
> 	      }
> 	  if (ddecl == NULL)
> 	    {
>-	      ddecl = make_node (DEBUG_EXPR_DECL);
>+	      ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				  TREE_TYPE (origin));
> 	      DECL_ARTIFICIAL (ddecl) = 1;
>-	      TREE_TYPE (ddecl) = TREE_TYPE (origin);
> 	      SET_DECL_MODE (ddecl, DECL_MODE (origin));
> 
> 	      vec_safe_push (*debug_args, origin);
>@@ -1883,10 +1883,10 @@ ipa_param_body_adjustments::reset_debug_stmts
>()
> 	    gcc_assert (is_gimple_debug (stmt));
> 	    if (vexpr == NULL && gsip != NULL)
> 	      {
>-		vexpr = make_node (DEBUG_EXPR_DECL);
>+		vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				    TREE_TYPE (name));
> 		def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
> 		DECL_ARTIFICIAL (vexpr) = 1;
>-		TREE_TYPE (vexpr) = TREE_TYPE (name);
> 		SET_DECL_MODE (vexpr, DECL_MODE (decl));
> 		gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
> 	      }
>diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
>index 8d106a4de26..259ce520143 100644
>--- a/gcc/objc/objc-act.c
>+++ b/gcc/objc/objc-act.c
>@@ -1295,12 +1295,11 @@ objc_add_property_declaration (location_t
>location, tree decl,
>     }
> 
>   /* Create a PROPERTY_DECL node.  */
>-  tree property_decl = make_node (PROPERTY_DECL);
>+  tree property_decl = build_decl (DECL_SOURCE_LOCATION (decl),
>PROPERTY_DECL,
>+				   nullptr, TREE_TYPE (decl));
> 
>   /* Copy the basic information from the original decl.  */
>   tree p_type = TREE_TYPE (decl);
>-  TREE_TYPE (property_decl) = p_type;
>-  DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
>   TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
> 
>   /* Add property-specific information.  */
>@@ -1434,10 +1433,9 @@ maybe_make_artificial_property_decl (tree
>interface, tree implementation,
>       /* Create an artificial property declaration with the
> 	 information we collected on the type and getter/setter
> 	 names.  */
>-      property_decl = make_node (PROPERTY_DECL);
>+      property_decl = build_decl (input_location, PROPERTY_DECL,
>nullptr,
>+				  type);
> 
>-      TREE_TYPE (property_decl) = type;
>-      DECL_SOURCE_LOCATION (property_decl) = input_location;
>       TREE_DEPRECATED (property_decl) = 0;
>       DECL_ARTIFICIAL (property_decl) = 1;
> 
>@@ -4889,9 +4887,8 @@ objc_build_keyword_decl (tree key_name, tree
>arg_type,
>   /* If no type is specified, default to "id".  */
>   arg_type = adjust_type_for_id_default (arg_type);
> 
>-  keyword_decl = make_node (KEYWORD_DECL);
>+  keyword_decl = build_decl (input_location, KEYWORD_DECL, nullptr,
>arg_type);
> 
>-  TREE_TYPE (keyword_decl) = arg_type;
>   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
>   KEYWORD_KEY_NAME (keyword_decl) = key_name;
>   DECL_ATTRIBUTES (keyword_decl) = attributes;
>@@ -4975,8 +4972,7 @@ build_method_decl (enum tree_code code, tree
>ret_type, tree selector,
>      type of the method.  We may want to change this, and store the
>      entire function type in there (eg, it may be used to simplify
>      dealing with attributes below).  */
>-  method_decl = make_node (code);
>-  TREE_TYPE (method_decl) = ret_type;
>+  method_decl = build_decl (input_location, code, nullptr, ret_type);
> 
>   /* If we have a keyword selector, create an identifier_node that
>      represents the full selector name (`:' included)...  */
>diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
>index b772b7ff520..03189f4c50f 100644
>--- a/gcc/omp-simd-clone.c
>+++ b/gcc/omp-simd-clone.c
>@@ -910,10 +910,10 @@ ipa_simd_modify_stmt_ops (tree *tp, int
>*walk_subtrees, void *data)
>       gimple *stmt;
>       if (is_gimple_debug (info->stmt))
> 	{
>-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
>+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				   TREE_TYPE (repl));
> 	  stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
> 	  DECL_ARTIFICIAL (vexpr) = 1;
>-	  TREE_TYPE (vexpr) = TREE_TYPE (repl);
> 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (repl)));
> 	  repl = vexpr;
> 	}
>diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
>index 242452f2acf..7811fc6c302 100644
>--- a/gcc/stor-layout.c
>+++ b/gcc/stor-layout.c
>@@ -2024,7 +2024,7 @@ finalize_type_size (tree type)
> static tree
> start_bitfield_representative (tree field)
> {
>-  tree repr = make_node (FIELD_DECL);
>+  tree repr = build_decl (input_location, FIELD_DECL, nullptr,
>nullptr);
>   DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field);
>   /* Force the representative to begin at a BITS_PER_UNIT aligned
>      boundary - C++ may use tail-padding of a base object to
>diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
>index 9e041ca4d56..0204ce20282 100644
>--- a/gcc/tree-inline.c
>+++ b/gcc/tree-inline.c
>@@ -193,7 +193,6 @@ remap_ssa_name (tree name, copy_body_data *id)
> 	  && id->entry_bb == NULL
> 	  && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
> 	{
>-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
> 	  gimple *def_temp;
> 	  gimple_stmt_iterator gsi;
> 	  tree val = SSA_NAME_VAR (name);
>@@ -210,9 +209,11 @@ remap_ssa_name (tree name, copy_body_data *id)
> 	  n = id->decl_map->get (val);
> 	  if (n && TREE_CODE (*n) == DEBUG_EXPR_DECL)
> 	    return *n;
>+
>+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				   TREE_TYPE (name));
> 	  def_temp = gimple_build_debug_source_bind (vexpr, val, NULL);
> 	  DECL_ARTIFICIAL (vexpr) = 1;
>-	  TREE_TYPE (vexpr) = TREE_TYPE (name);
> 	  SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (name)));
>	  gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN
>(cfun)));
> 	  gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
>@@ -6494,9 +6495,9 @@ tree_function_versioning (tree old_decl, tree
>new_decl,
> 	      debug_args = decl_debug_args_insert (new_decl);
> 	      len = vec_safe_length (*debug_args);
> 	    }
>-	  ddecl = make_node (DEBUG_EXPR_DECL);
>+	  ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+			      TREE_TYPE (parm));
> 	  DECL_ARTIFICIAL (ddecl) = 1;
>-	  TREE_TYPE (ddecl) = TREE_TYPE (parm);
> 	  SET_DECL_MODE (ddecl, DECL_MODE (parm));
> 	  vec_safe_push (*debug_args, DECL_ORIGIN (parm));
> 	  vec_safe_push (*debug_args, ddecl);
>@@ -6525,10 +6526,10 @@ tree_function_versioning (tree old_decl, tree
>new_decl,
> 		var = TREE_CHAIN (var);
> 	      if (var == NULL_TREE)
> 		break;
>-	      vexpr = make_node (DEBUG_EXPR_DECL);
> 	      tree parm = (**debug_args)[i];
>+	      vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				  TREE_TYPE (parm));
> 	      DECL_ARTIFICIAL (vexpr) = 1;
>-	      TREE_TYPE (vexpr) = TREE_TYPE (parm);
> 	      SET_DECL_MODE (vexpr, DECL_MODE (parm));
> 	      def_temp = gimple_build_debug_bind (var, vexpr, NULL);
> 	      gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT);
>diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
>index 8045e34df26..f9933305957 100644
>--- a/gcc/tree-into-ssa.c
>+++ b/gcc/tree-into-ssa.c
>@@ -1284,10 +1284,10 @@ rewrite_debug_stmt_uses (gimple *stmt)
> 	      if (def == NULL_TREE)
> 		{
> 		  gimple *def_temp;
>-		  def = make_node (DEBUG_EXPR_DECL);
>+		  def = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				    TREE_TYPE (var));
> 		  def_temp = gimple_build_debug_source_bind (def, var, NULL);
> 		  DECL_ARTIFICIAL (def) = 1;
>-		  TREE_TYPE (def) = TREE_TYPE (var);
> 		  SET_DECL_MODE (def, DECL_MODE (var));
> 		  gsi =
> 		 gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
>diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
>index 9edd922a303..37e229477ec 100644
>--- a/gcc/tree-nested.c
>+++ b/gcc/tree-nested.c
>@@ -394,8 +394,8 @@ lookup_field_for_decl (struct nesting_info *info,
>tree decl,
>   if (!*slot)
>     {
>       tree type = get_frame_type (info);
>-      tree field = make_node (FIELD_DECL);
>-      DECL_NAME (field) = DECL_NAME (decl);
>+      tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
>(decl),
>+			       nullptr);
> 
>       if (use_pointer_in_frame (decl))
> 	{
>@@ -510,9 +510,8 @@ get_chain_field (struct nesting_info *info)
>     {
>       tree type = build_pointer_type (get_frame_type (info->outer));
> 
>-      field = make_node (FIELD_DECL);
>-      DECL_NAME (field) = get_identifier ("__chain");
>-      TREE_TYPE (field) = type;
>+      field = build_decl (input_location, FIELD_DECL,
>+			  get_identifier ("__chain"), type);
>       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
>       DECL_NONADDRESSABLE_P (field) = 1;
> 
>@@ -694,9 +693,7 @@ lookup_element_for_decl (struct nesting_info *info,
>tree decl,
> static tree
>create_field_for_decl (struct nesting_info *info, tree decl, tree type)
> {
>-  tree field = make_node (FIELD_DECL);
>-  DECL_NAME (field) = DECL_NAME (decl);
>-  TREE_TYPE (field) = type;
>+  tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
>(decl), type);
>   TREE_ADDRESSABLE (field) = 1;
>   insert_field_into_struct (get_frame_type (info), field);
>   return field;
>@@ -783,9 +780,8 @@ get_nl_goto_field (struct nesting_info *info)
>       type = build_array_type
> 	(type, build_index_type (size_int (size)));
> 
>-      field = make_node (FIELD_DECL);
>-      DECL_NAME (field) = get_identifier ("__nl_goto_buf");
>-      TREE_TYPE (field) = type;
>+      field = build_decl (input_location, FIELD_DECL,
>+			  get_identifier ("__nl_goto_buf"), type);
>       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
>       TREE_ADDRESSABLE (field) = 1;
> 
>@@ -3378,10 +3374,10 @@ finalize_nesting_tree_1 (struct nesting_info
>*root)
>/* Create a field in the FRAME record to hold the frame base address
>for
>	 this stack frame.  Since it will be used only by the debugger, put it
>	 at the end of the record in order not to shift all other offsets.  */
>-      tree fb_decl = make_node (FIELD_DECL);
>+      tree fb_decl = build_decl (input_location, FIELD_DECL,
>+				 get_identifier ("FRAME_BASE.PARENT"),
>+				 ptr_type_node);
> 
>-      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
>-      TREE_TYPE (fb_decl) = ptr_type_node;
>       TREE_ADDRESSABLE (fb_decl) = 1;
>       DECL_CONTEXT (fb_decl) = root->frame_type;
>TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS
>(root->frame_type),
>diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
>index 42585412325..dc6f412c02d 100644
>--- a/gcc/tree-ssa-ccp.c
>+++ b/gcc/tree-ssa-ccp.c
>@@ -3067,9 +3067,9 @@ optimize_atomic_bit_test_and
>(gimple_stmt_iterator *gsip,
>       tree temp = NULL_TREE;
>       if (!throws || after || single_pred_p (e->dest))
> 	{
>-	  temp = make_node (DEBUG_EXPR_DECL);
>+	  temp = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+			     TREE_TYPE (lhs));
> 	  DECL_ARTIFICIAL (temp) = 1;
>-	  TREE_TYPE (temp) = TREE_TYPE (lhs);
> 	  SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
> 	  tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
> 	  g = gimple_build_debug_bind (temp, t, g);
>diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
>index 12a8a49a307..953b3d0b2f1 100644
>--- a/gcc/tree-ssa-loop-ivopts.c
>+++ b/gcc/tree-ssa-loop-ivopts.c
>@@ -7677,9 +7677,9 @@ remove_unused_ivs (struct ivopts_data *data,
>bitmap toremove)
> 	      comp = unshare_expr (comp);
> 	      if (count > 1)
> 		{
>-		  tree vexpr = make_node (DEBUG_EXPR_DECL);
>+		  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
>+					   nullptr, TREE_TYPE (comp));
> 		  DECL_ARTIFICIAL (vexpr) = 1;
>-		  TREE_TYPE (vexpr) = TREE_TYPE (comp);
> 		  if (SSA_NAME_VAR (def))
> 		    SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (def)));
> 		  else
>diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
>index 1777bff2f7c..25589716a11 100644
>--- a/gcc/tree-ssa-phiopt.c
>+++ b/gcc/tree-ssa-phiopt.c
>@@ -2302,18 +2302,18 @@ spaceship_replacement (basic_block cond_bb,
>basic_block middle_bb,
> 	     all floating point numbers should be comparable.  */
> 	  gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
> 	  tree type = TREE_TYPE (phires);
>-	  tree temp1 = make_node (DEBUG_EXPR_DECL);
>+	  tree temp1 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				   type);
> 	  DECL_ARTIFICIAL (temp1) = 1;
>-	  TREE_TYPE (temp1) = type;
> 	  SET_DECL_MODE (temp1, TYPE_MODE (type));
> 	  tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
> 	  t = build3 (COND_EXPR, type, t, build_one_cst (type),
> 		      build_int_cst (type, -1));
> 	  gimple *g = gimple_build_debug_bind (temp1, t, phi);
> 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
>-	  tree temp2 = make_node (DEBUG_EXPR_DECL);
>+	  tree temp2 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				   type);
> 	  DECL_ARTIFICIAL (temp2) = 1;
>-	  TREE_TYPE (temp2) = type;
> 	  SET_DECL_MODE (temp2, TYPE_MODE (type));
> 	  t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
> 	  t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
>diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
>index 2dd4435b981..48f6117a731 100644
>--- a/gcc/tree-ssa-reassoc.c
>+++ b/gcc/tree-ssa-reassoc.c
>@@ -1214,14 +1214,14 @@ make_new_ssa_for_def (gimple *stmt, enum
>tree_code opcode, tree op)
> 	{
> 	  if (new_debug_lhs == NULL_TREE)
> 	    {
>-	      new_debug_lhs = make_node (DEBUG_EXPR_DECL);
>+	      new_debug_lhs = build_decl (input_location, DEBUG_EXPR_DECL,
>+					  nullptr, TREE_TYPE (lhs));
> 	      gdebug *def_temp
> 		= gimple_build_debug_bind (new_debug_lhs,
> 					   build2 (opcode, TREE_TYPE (lhs),
> 						   new_lhs, op),
> 					   stmt);
> 	      DECL_ARTIFICIAL (new_debug_lhs) = 1;
>-	      TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
> 	      SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
> 	      gimple_set_uid (def_temp, gimple_uid (stmt));
> 	      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
>diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
>index 4cc400d3c2e..83caadb37c8 100644
>--- a/gcc/tree-ssa.c
>+++ b/gcc/tree-ssa.c
>@@ -434,14 +434,14 @@ insert_debug_temp_for_var_def
>(gimple_stmt_iterator *gsi, tree var)
>       else
> 	{
> 	  gdebug *def_temp;
>-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
>+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>+				   TREE_TYPE (value));
> 
> 	  def_temp = gimple_build_debug_bind (vexpr,
> 					      unshare_expr (value),
> 					      def_stmt);
> 
> 	  DECL_ARTIFICIAL (vexpr) = 1;
>-	  TREE_TYPE (vexpr) = TREE_TYPE (value);
> 	  if (DECL_P (value))
> 	    SET_DECL_MODE (vexpr, DECL_MODE (value));
> 	  else
>diff --git a/gcc/tree.c b/gcc/tree.c
>index 1aa6e557a04..a90097a51c6 100644
>--- a/gcc/tree.c
>+++ b/gcc/tree.c
>@@ -1175,7 +1175,7 @@ allocate_decl_uid (void)
>    Achoo!  I got a code in the node.  */
> 
> tree
>-make_node (enum tree_code code MEM_STAT_DECL)
>+make_node (enum tree_code code, make_node_caller caller MEM_STAT_DECL)
> {
>   tree t;
>   enum tree_code_class type = TREE_CODE_CLASS (code);
>@@ -1194,27 +1194,7 @@ make_node (enum tree_code code MEM_STAT_DECL)
>       break;
> 
>     case tcc_declaration:
>-      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
>-	{
>-	  if (code == FUNCTION_DECL)
>-	    {
>-	      SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
>-	      SET_DECL_MODE (t, FUNCTION_MODE);
>-	    }
>-	  else
>-	    SET_DECL_ALIGN (t, 1);
>-	}
>-      DECL_SOURCE_LOCATION (t) = input_location;
>-      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
>-	DECL_UID (t) = --next_debug_decl_uid;
>-      else
>-	{
>-	  DECL_UID (t) = allocate_decl_uid ();
>-	  SET_DECL_PT_UID (t, -1);
>-	}
>-      if (TREE_CODE (t) == LABEL_DECL)
>-	LABEL_DECL_UID (t) = -1;
>-
>+      gcc_assert (caller == BUILD_DECL_MKNODE_CALLER);
>       break;
> 
>     case tcc_type:
>@@ -5257,10 +5237,29 @@ tree
> build_decl (location_t loc, enum tree_code code, tree name,
>     		 tree type MEM_STAT_DECL)
> {
>-  tree t;
>-
>-  t = make_node (code PASS_MEM_STAT);
>+  tree t = make_node (code, BUILD_DECL_MKNODE_CALLER PASS_MEM_STAT);
>   DECL_SOURCE_LOCATION (t) = loc;
>+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
>+    {
>+      if (code == FUNCTION_DECL)
>+	{
>+	  SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
>+	  SET_DECL_MODE (t, FUNCTION_MODE);
>+	}
>+      else
>+	SET_DECL_ALIGN (t, 1);
>+    }
>+
>+  if (TREE_CODE (t) == DEBUG_EXPR_DECL)
>+    DECL_UID (t) = --next_debug_decl_uid;
>+  else
>+    {
>+      DECL_UID (t) = allocate_decl_uid ();
>+      SET_DECL_PT_UID (t, -1);
>+    }
>+
>+  if (TREE_CODE (t) == LABEL_DECL)
>+    LABEL_DECL_UID (t) = -1;
> 
> /*  if (type == error_mark_node)
>     type = integer_type_node; */
>diff --git a/gcc/tree.h b/gcc/tree.h
>index 8bdf16d8b4a..86dd32354f2 100644
>--- a/gcc/tree.h
>+++ b/gcc/tree.h
>@@ -4357,11 +4357,18 @@ extern size_t tree_code_size (enum tree_code);
> /* Allocate and return a new UID from the DECL_UID namespace.  */
> extern int allocate_decl_uid (void);
> 
>+/* expected callers of make_node.  */
>+enum make_node_caller
>+{
>+  UNKNOWN_MKNODE_CALLER,
>+  BUILD_DECL_MKNODE_CALLER
>+};
>+
> /* Lowest level primitive for allocating a node.
>    The TREE_CODE is the only argument.  Contents are initialized
>    to zero except for a few of the common fields.  */
> 
>-extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
>+extern tree make_node (enum tree_code, enum make_node_caller caller =
>UNKNOWN_MKNODE_CALLER CXX_MEM_STAT_INFO);
> 
> /* Free tree node.  */
> 
>diff --git a/gcc/varasm.c b/gcc/varasm.c
>index 53cf6dea3f3..fa6799e48fb 100644
>--- a/gcc/varasm.c
>+++ b/gcc/varasm.c
>@@ -8229,21 +8229,21 @@ output_file_directive (FILE *asm_file, const
>char *input_name)
> rtx
> make_debug_expr_from_rtl (const_rtx exp)
> {
>-  tree ddecl = make_node (DEBUG_EXPR_DECL), type;
>+  tree type;
>   machine_mode mode = GET_MODE (exp);
>   rtx dval;
> 
>-  DECL_ARTIFICIAL (ddecl) = 1;
>   if (REG_P (exp) && REG_EXPR (exp))
>     type = TREE_TYPE (REG_EXPR (exp));
>   else if (MEM_P (exp) && MEM_EXPR (exp))
>     type = TREE_TYPE (MEM_EXPR (exp));
>   else
>     type = NULL_TREE;
>-  if (type && TYPE_MODE (type) == mode)
>-    TREE_TYPE (ddecl) = type;
>-  else
>-    TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
>+  if (!type || TYPE_MODE (type) != mode)
>+    type = lang_hooks.types.type_for_mode (mode, 1);
>+
>+  tree ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
>type);
>+  DECL_ARTIFICIAL (ddecl) = 1;
>   SET_DECL_MODE (ddecl, mode);
>   dval = gen_rtx_DEBUG_EXPR (mode);
>   DEBUG_EXPR_TREE_DECL (dval) = ddecl;


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30 15:13   ` David Malcolm
@ 2021-06-30 19:34     ` Jason Merrill
  2021-07-01 10:16     ` Trevor Saunders
  1 sibling, 0 replies; 25+ messages in thread
From: Jason Merrill @ 2021-06-30 19:34 UTC (permalink / raw)
  To: David Malcolm; +Cc: Trevor Saunders, gcc-patches List

On Wed, Jun 30, 2021 at 11:14 AM David Malcolm via Gcc-patches <
gcc-patches@gcc.gnu.org> wrote:

> On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > This makes it possible to assert if input_location is used during the
> > lifetime
> > of a scope.  This will allow us to find places that currently use it
> > within a
> > function and its callees, or prevent adding uses within the lifetime
> > of a
> > function after all existing uses are removed.
> >
> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> >
> > Trev
>
> [...snip...]
>
> > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > index d58586f2526..3f68d1d79eb 100644
> > --- a/gcc/diagnostic.c
> > +++ b/gcc/diagnostic.c
> > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> >    auto_diagnostic_group d;
> >    va_list ap;
> >    va_start (ap, gmsgid);
> > -  rich_location richloc (line_table, input_location);
> > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> >    va_end (ap);
> >
>
> I actually make use of this in the analyzer: the analyzer sets
> input_location to stmt->location when analyzing a given stmt - that
> way, if the analyzer ICEs, the ICE is shown at the code construct that
> crashed the analyzer.
>

C++ template instantiation and constexpr evaluation work similarly.

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30 15:13   ` David Malcolm
  2021-06-30 19:34     ` Jason Merrill
@ 2021-07-01 10:16     ` Trevor Saunders
  2021-07-01 12:53       ` Richard Biener
  2021-07-02 15:46       ` Jason Merrill
  1 sibling, 2 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-07-01 10:16 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > This makes it possible to assert if input_location is used during the
> > lifetime
> > of a scope.  This will allow us to find places that currently use it
> > within a
> > function and its callees, or prevent adding uses within the lifetime
> > of a
> > function after all existing uses are removed.
> > 
> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > 
> > Trev
> 
> [...snip...]
> 
> > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > index d58586f2526..3f68d1d79eb 100644
> > --- a/gcc/diagnostic.c
> > +++ b/gcc/diagnostic.c
> > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> >    auto_diagnostic_group d;
> >    va_list ap;
> >    va_start (ap, gmsgid);
> > -  rich_location richloc (line_table, input_location);
> > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> >    va_end (ap);
> >  
> 
> I actually make use of this in the analyzer: the analyzer sets
> input_location to stmt->location when analyzing a given stmt - that
> way, if the analyzer ICEs, the ICE is shown at the code construct that
> crashed the analyzer.
> 
> This behavior is useful to me, and would be lost with the proposed
> patch.

I made this change because otherwise if the compiler ICE's while access
to input_location is blocked we end up infinitely recursing complaining
we can't access it while trying to say where the last error was.  I was
nervous about the change before, and now I agree we need something
else.

> Is there a better way of doing what I'm doing?
> 
> Is the long-term goal of the patch kit to reduce our reliance on global
> variables?  Are we ultimately still going to need a variable for "where
> to show the ICE if gcc crashes"?  (perhaps stashing it in the
> diagnostic_context???)

Yes, the goal is ultimately removal of global state, however I'm not
really ure what the better approach to your problem is, after all even
moving it to the diagnostic context is sort of a global state, and sort
of dupplicates input_location.  That said it is somewhat more
constrained, so if it removes usage of input_location perhaps its
worthwhile?

Sorry I'm not yet sure what to propose here.

Trev

> 
> Hope this is constructive
> Dave
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30 19:09       ` Richard Biener
@ 2021-07-01 10:23         ` Trevor Saunders
  2021-07-01 12:48           ` Richard Biener
  0 siblings, 1 reply; 25+ messages in thread
From: Trevor Saunders @ 2021-07-01 10:23 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

On Wed, Jun 30, 2021 at 09:09:33PM +0200, Richard Biener wrote:
> On June 30, 2021 2:33:30 PM GMT+02:00, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> >On Wed, Jun 30, 2021 at 11:00:37AM +0200, Richard Biener wrote:
> >> On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders
> ><tbsaunde@tbsaunde.org> wrote:
> >> >
> >> > This makes it possible to assert if input_location is used during
> >the lifetime
> >> > of a scope.  This will allow us to find places that currently use
> >it within a
> >> > function and its callees, or prevent adding uses within the
> >lifetime of a
> >> > function after all existing uses are removed.
> >> >
> >> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> >> 
> >> I'm not sure about the general approach but I have comments about
> >> input_location.
> >> 
> >> IMHO a good first step would be to guard the input_location
> >declaration with sth
> >> like
> >> 
> >> #ifndef GCC_NEED_INPUT_LOCATION
> >> extern location_t input_location;
> >> #endif
> >
> >I think that's another reasonable step, my one concern is that it can
> >be
> >useful to push the usage of input_location, or any other global from
> >the
> >bottom of the stack to a caller that can provide a better argument
> >eventually, but first just use the global.  Doing this sort of
> >refactoring is harder if you need to add files with callers to the
> >whitelist, and kind of defeats the point of the whitelist.  Consider
> >the
> >below commit, that is untested, but perhaps I should have included in
> >this series as somewhat related.
> >
> >As for this approach being limited to functions that's somewhat true,
> >but since it effects all functions called while its on the stack, it
> >would mean once enough infrastructure is fixed, we could add one the
> >execute method of a pass and nothing in the pass could touch
> >input_location.  The limit also means that it doesn't get in the way of
> >the above sort of refactoring, but as it proceeds lower level functions
> >that now take explicit arguments can be called from contexts that ban
> >use of input_location.
> >
> >Trev
> >
> >From efd04d2df4163dd930f489d9fba1455bfb368114 Mon Sep 17 00:00:00 2001
> >From: Trevor Saunders <tbsaunde@tbsaunde.org>
> >Date: Sun, 27 Jun 2021 02:10:26 -0400
> >Subject: [PATCH] force decls to be allocated through build_decl to
> >initialize
> > them
> >To: gcc-patches@gcc.gnu.org
> >
> >prior to this commit all calls to build_decl used input_location, even
> >if
> >temporarily  until build_decl reset the location to something else that
> >it was
> >told was the proper location.  To avoid using the global we need the
> >caller to
> >pass in the location it wants, however that's not possible with
> >make_node since
> >it makes other types of nodes.  So we force all callers who wish to
> >make a decl
> >to go through build_decl which already takes a location argument.  To
> >avoid
> >changing behavior this just explicitly passes in input_location to
> >build_decl
> >for callers of make_node that create a decl, however it would seem in
> >many of
> >these cases that the location of the decl being coppied might be a
> >better
> >location.
> 
> If make_node really uses input_location that's what should change (to UNONOWN_LOCATION).  But yes, it might change behavior to the worse... 

make_node really does, when making a decl.  My idea was to force using
build_decl rather than make_node when making a decl, that way make_node
could stop doing anything special for decls including setting the
location, implicitly leaving it as UNKNOWN_LOCATION since it clears the
object when allocating it.  Then I used input_location as an argument to
build_decl wherever the location currently isn't set to something else,
so as not to make things worse.  That way callers that know the right
location do not need to touch input_location, and it pushes the problem
to the places where we need to work on finding a better location, and
might be able to do so rather than deep in make_node.  Does that seem
reasonable as an incremental step to using input_location less, even
without trying to block its use?

Thanks

Trev

> 
> Richard. 
> 
> >---
> > gcc/cfgexpand.c              |  8 +++---
> > gcc/cp/cp-gimplify.c         |  5 ++--
> > gcc/fortran/trans-decl.c     |  5 ++--
> > gcc/fortran/trans-types.c    |  4 +--
> > gcc/ipa-param-manipulation.c |  8 +++---
> > gcc/objc/objc-act.c          | 16 +++++-------
> > gcc/omp-simd-clone.c         |  4 +--
> > gcc/stor-layout.c            |  2 +-
> > gcc/tree-inline.c            | 13 +++++-----
> > gcc/tree-into-ssa.c          |  4 +--
> > gcc/tree-nested.c            | 24 ++++++++----------
> > gcc/tree-ssa-ccp.c           |  4 +--
> > gcc/tree-ssa-loop-ivopts.c   |  4 +--
> > gcc/tree-ssa-phiopt.c        |  8 +++---
> > gcc/tree-ssa-reassoc.c       |  4 +--
> > gcc/tree-ssa.c               |  4 +--
> > gcc/tree.c                   | 49 ++++++++++++++++++------------------
> > gcc/tree.h                   |  9 ++++++-
> > gcc/varasm.c                 | 12 ++++-----
> > 19 files changed, 93 insertions(+), 94 deletions(-)
> >
> >diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> >index 3edd53c37dc..fea8c837c80 100644
> >--- a/gcc/cfgexpand.c
> >+++ b/gcc/cfgexpand.c
> >@@ -4342,10 +4342,10 @@ avoid_deep_ter_for_debug (gimple *stmt, int
> >depth)
> > 	  tree &vexpr = deep_ter_debug_map->get_or_insert (use);
> > 	  if (vexpr != NULL)
> > 	    continue;
> >-	  vexpr = make_node (DEBUG_EXPR_DECL);
> >+	  vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+			      TREE_TYPE (use));
> > 	  gimple *def_temp = gimple_build_debug_bind (vexpr, use, g);
> > 	  DECL_ARTIFICIAL (vexpr) = 1;
> >-	  TREE_TYPE (vexpr) = TREE_TYPE (use);
> > 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (use)));
> > 	  gimple_stmt_iterator gsi = gsi_for_stmt (g);
> > 	  gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
> >@@ -5899,14 +5899,14 @@ expand_gimple_basic_block (basic_block bb, bool
> >disable_tail_calls)
> > 		       temporary.  */
> > 		    gimple *debugstmt;
> > 		    tree value = gimple_assign_rhs_to_tree (def);
> >-		    tree vexpr = make_node (DEBUG_EXPR_DECL);
> > 		    rtx val;
> > 		    machine_mode mode;
> > 
> > 		    set_curr_insn_location (gimple_location (def));
> > 
> >+		    tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
> >+					     nullptr, TREE_TYPE (value));
> > 		    DECL_ARTIFICIAL (vexpr) = 1;
> >-		    TREE_TYPE (vexpr) = TREE_TYPE (value);
> > 		    if (DECL_P (value))
> > 		      mode = DECL_MODE (value);
> > 		    else
> >diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> >index 00b7772fe0d..d537e547169 100644
> >--- a/gcc/cp/cp-gimplify.c
> >+++ b/gcc/cp/cp-gimplify.c
> >@@ -1217,8 +1217,9 @@ cp_genericize_r (tree *stmt_p, int
> >*walk_subtrees, void *data)
> > 	      /* Omit from the GENERIC, the back-end can't handle it.  */;
> > 	    else
> > 	      {
> >-		tree using_directive = make_node (IMPORTED_DECL);
> >-		TREE_TYPE (using_directive) = void_type_node;
> >+		tree using_directive = build_decl (input_location,
> >+						   IMPORTED_DECL, nullptr,
> >+						   void_type_node);
> > 		DECL_CONTEXT (using_directive) = current_function_decl;
> > 
> > 		IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
> >diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> >index 479ba6fa6ce..b726c2f2bdc 100644
> >--- a/gcc/fortran/trans-decl.c
> >+++ b/gcc/fortran/trans-decl.c
> >@@ -5262,10 +5262,9 @@ generate_namelist_decl (gfc_symbol * sym)
> > CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, nml->sym->backend_decl);
> >     }
> > 
> >-  decl = make_node (NAMELIST_DECL);
> >-  TREE_TYPE (decl) = void_type_node;
> >+  decl = build_decl (input_location, NAMELIST_DECL, get_identifier
> >(sym->name),
> >+		     void_type_node);
> >NAMELIST_DECL_ASSOCIATED_DECL (decl) = build_constructor (NULL_TREE,
> >nml_decls);
> >-  DECL_NAME (decl) = get_identifier (sym->name);
> >   return decl;
> > }
> > 
> >diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
> >index 5582e404df9..8b4d5c99665 100644
> >--- a/gcc/fortran/trans-types.c
> >+++ b/gcc/fortran/trans-types.c
> >@@ -3417,9 +3417,9 @@ gfc_get_array_descr_info (const_tree type, struct
> >array_descr_info *info)
> >   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
> >   if (!base_decl)
> >     {
> >-      base_decl = make_node (DEBUG_EXPR_DECL);
> >+      base_decl = build_decl (input_location, DEBUG_EXPR_DECL,
> >nullptr,
> >+			      indirect ? build_pointer_type (ptype) : ptype);
> >       DECL_ARTIFICIAL (base_decl) = 1;
> >-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) :
> >ptype;
> >       SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
> >       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
> >     }
> >diff --git a/gcc/ipa-param-manipulation.c
> >b/gcc/ipa-param-manipulation.c
> >index f2d91476655..242fa4dee1d 100644
> >--- a/gcc/ipa-param-manipulation.c
> >+++ b/gcc/ipa-param-manipulation.c
> >@@ -834,9 +834,9 @@ ipa_param_adjustments::modify_call (gcall *stmt,
> > 	      }
> > 	  if (ddecl == NULL)
> > 	    {
> >-	      ddecl = make_node (DEBUG_EXPR_DECL);
> >+	      ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				  TREE_TYPE (origin));
> > 	      DECL_ARTIFICIAL (ddecl) = 1;
> >-	      TREE_TYPE (ddecl) = TREE_TYPE (origin);
> > 	      SET_DECL_MODE (ddecl, DECL_MODE (origin));
> > 
> > 	      vec_safe_push (*debug_args, origin);
> >@@ -1883,10 +1883,10 @@ ipa_param_body_adjustments::reset_debug_stmts
> >()
> > 	    gcc_assert (is_gimple_debug (stmt));
> > 	    if (vexpr == NULL && gsip != NULL)
> > 	      {
> >-		vexpr = make_node (DEBUG_EXPR_DECL);
> >+		vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				    TREE_TYPE (name));
> > 		def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
> > 		DECL_ARTIFICIAL (vexpr) = 1;
> >-		TREE_TYPE (vexpr) = TREE_TYPE (name);
> > 		SET_DECL_MODE (vexpr, DECL_MODE (decl));
> > 		gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
> > 	      }
> >diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
> >index 8d106a4de26..259ce520143 100644
> >--- a/gcc/objc/objc-act.c
> >+++ b/gcc/objc/objc-act.c
> >@@ -1295,12 +1295,11 @@ objc_add_property_declaration (location_t
> >location, tree decl,
> >     }
> > 
> >   /* Create a PROPERTY_DECL node.  */
> >-  tree property_decl = make_node (PROPERTY_DECL);
> >+  tree property_decl = build_decl (DECL_SOURCE_LOCATION (decl),
> >PROPERTY_DECL,
> >+				   nullptr, TREE_TYPE (decl));
> > 
> >   /* Copy the basic information from the original decl.  */
> >   tree p_type = TREE_TYPE (decl);
> >-  TREE_TYPE (property_decl) = p_type;
> >-  DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
> >   TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
> > 
> >   /* Add property-specific information.  */
> >@@ -1434,10 +1433,9 @@ maybe_make_artificial_property_decl (tree
> >interface, tree implementation,
> >       /* Create an artificial property declaration with the
> > 	 information we collected on the type and getter/setter
> > 	 names.  */
> >-      property_decl = make_node (PROPERTY_DECL);
> >+      property_decl = build_decl (input_location, PROPERTY_DECL,
> >nullptr,
> >+				  type);
> > 
> >-      TREE_TYPE (property_decl) = type;
> >-      DECL_SOURCE_LOCATION (property_decl) = input_location;
> >       TREE_DEPRECATED (property_decl) = 0;
> >       DECL_ARTIFICIAL (property_decl) = 1;
> > 
> >@@ -4889,9 +4887,8 @@ objc_build_keyword_decl (tree key_name, tree
> >arg_type,
> >   /* If no type is specified, default to "id".  */
> >   arg_type = adjust_type_for_id_default (arg_type);
> > 
> >-  keyword_decl = make_node (KEYWORD_DECL);
> >+  keyword_decl = build_decl (input_location, KEYWORD_DECL, nullptr,
> >arg_type);
> > 
> >-  TREE_TYPE (keyword_decl) = arg_type;
> >   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
> >   KEYWORD_KEY_NAME (keyword_decl) = key_name;
> >   DECL_ATTRIBUTES (keyword_decl) = attributes;
> >@@ -4975,8 +4972,7 @@ build_method_decl (enum tree_code code, tree
> >ret_type, tree selector,
> >      type of the method.  We may want to change this, and store the
> >      entire function type in there (eg, it may be used to simplify
> >      dealing with attributes below).  */
> >-  method_decl = make_node (code);
> >-  TREE_TYPE (method_decl) = ret_type;
> >+  method_decl = build_decl (input_location, code, nullptr, ret_type);
> > 
> >   /* If we have a keyword selector, create an identifier_node that
> >      represents the full selector name (`:' included)...  */
> >diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
> >index b772b7ff520..03189f4c50f 100644
> >--- a/gcc/omp-simd-clone.c
> >+++ b/gcc/omp-simd-clone.c
> >@@ -910,10 +910,10 @@ ipa_simd_modify_stmt_ops (tree *tp, int
> >*walk_subtrees, void *data)
> >       gimple *stmt;
> >       if (is_gimple_debug (info->stmt))
> > 	{
> >-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
> >+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				   TREE_TYPE (repl));
> > 	  stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
> > 	  DECL_ARTIFICIAL (vexpr) = 1;
> >-	  TREE_TYPE (vexpr) = TREE_TYPE (repl);
> > 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (repl)));
> > 	  repl = vexpr;
> > 	}
> >diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
> >index 242452f2acf..7811fc6c302 100644
> >--- a/gcc/stor-layout.c
> >+++ b/gcc/stor-layout.c
> >@@ -2024,7 +2024,7 @@ finalize_type_size (tree type)
> > static tree
> > start_bitfield_representative (tree field)
> > {
> >-  tree repr = make_node (FIELD_DECL);
> >+  tree repr = build_decl (input_location, FIELD_DECL, nullptr,
> >nullptr);
> >   DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field);
> >   /* Force the representative to begin at a BITS_PER_UNIT aligned
> >      boundary - C++ may use tail-padding of a base object to
> >diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> >index 9e041ca4d56..0204ce20282 100644
> >--- a/gcc/tree-inline.c
> >+++ b/gcc/tree-inline.c
> >@@ -193,7 +193,6 @@ remap_ssa_name (tree name, copy_body_data *id)
> > 	  && id->entry_bb == NULL
> > 	  && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
> > 	{
> >-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
> > 	  gimple *def_temp;
> > 	  gimple_stmt_iterator gsi;
> > 	  tree val = SSA_NAME_VAR (name);
> >@@ -210,9 +209,11 @@ remap_ssa_name (tree name, copy_body_data *id)
> > 	  n = id->decl_map->get (val);
> > 	  if (n && TREE_CODE (*n) == DEBUG_EXPR_DECL)
> > 	    return *n;
> >+
> >+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				   TREE_TYPE (name));
> > 	  def_temp = gimple_build_debug_source_bind (vexpr, val, NULL);
> > 	  DECL_ARTIFICIAL (vexpr) = 1;
> >-	  TREE_TYPE (vexpr) = TREE_TYPE (name);
> > 	  SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (name)));
> >	  gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN
> >(cfun)));
> > 	  gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
> >@@ -6494,9 +6495,9 @@ tree_function_versioning (tree old_decl, tree
> >new_decl,
> > 	      debug_args = decl_debug_args_insert (new_decl);
> > 	      len = vec_safe_length (*debug_args);
> > 	    }
> >-	  ddecl = make_node (DEBUG_EXPR_DECL);
> >+	  ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+			      TREE_TYPE (parm));
> > 	  DECL_ARTIFICIAL (ddecl) = 1;
> >-	  TREE_TYPE (ddecl) = TREE_TYPE (parm);
> > 	  SET_DECL_MODE (ddecl, DECL_MODE (parm));
> > 	  vec_safe_push (*debug_args, DECL_ORIGIN (parm));
> > 	  vec_safe_push (*debug_args, ddecl);
> >@@ -6525,10 +6526,10 @@ tree_function_versioning (tree old_decl, tree
> >new_decl,
> > 		var = TREE_CHAIN (var);
> > 	      if (var == NULL_TREE)
> > 		break;
> >-	      vexpr = make_node (DEBUG_EXPR_DECL);
> > 	      tree parm = (**debug_args)[i];
> >+	      vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				  TREE_TYPE (parm));
> > 	      DECL_ARTIFICIAL (vexpr) = 1;
> >-	      TREE_TYPE (vexpr) = TREE_TYPE (parm);
> > 	      SET_DECL_MODE (vexpr, DECL_MODE (parm));
> > 	      def_temp = gimple_build_debug_bind (var, vexpr, NULL);
> > 	      gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT);
> >diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
> >index 8045e34df26..f9933305957 100644
> >--- a/gcc/tree-into-ssa.c
> >+++ b/gcc/tree-into-ssa.c
> >@@ -1284,10 +1284,10 @@ rewrite_debug_stmt_uses (gimple *stmt)
> > 	      if (def == NULL_TREE)
> > 		{
> > 		  gimple *def_temp;
> >-		  def = make_node (DEBUG_EXPR_DECL);
> >+		  def = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				    TREE_TYPE (var));
> > 		  def_temp = gimple_build_debug_source_bind (def, var, NULL);
> > 		  DECL_ARTIFICIAL (def) = 1;
> >-		  TREE_TYPE (def) = TREE_TYPE (var);
> > 		  SET_DECL_MODE (def, DECL_MODE (var));
> > 		  gsi =
> > 		 gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
> >diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> >index 9edd922a303..37e229477ec 100644
> >--- a/gcc/tree-nested.c
> >+++ b/gcc/tree-nested.c
> >@@ -394,8 +394,8 @@ lookup_field_for_decl (struct nesting_info *info,
> >tree decl,
> >   if (!*slot)
> >     {
> >       tree type = get_frame_type (info);
> >-      tree field = make_node (FIELD_DECL);
> >-      DECL_NAME (field) = DECL_NAME (decl);
> >+      tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
> >(decl),
> >+			       nullptr);
> > 
> >       if (use_pointer_in_frame (decl))
> > 	{
> >@@ -510,9 +510,8 @@ get_chain_field (struct nesting_info *info)
> >     {
> >       tree type = build_pointer_type (get_frame_type (info->outer));
> > 
> >-      field = make_node (FIELD_DECL);
> >-      DECL_NAME (field) = get_identifier ("__chain");
> >-      TREE_TYPE (field) = type;
> >+      field = build_decl (input_location, FIELD_DECL,
> >+			  get_identifier ("__chain"), type);
> >       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
> >       DECL_NONADDRESSABLE_P (field) = 1;
> > 
> >@@ -694,9 +693,7 @@ lookup_element_for_decl (struct nesting_info *info,
> >tree decl,
> > static tree
> >create_field_for_decl (struct nesting_info *info, tree decl, tree type)
> > {
> >-  tree field = make_node (FIELD_DECL);
> >-  DECL_NAME (field) = DECL_NAME (decl);
> >-  TREE_TYPE (field) = type;
> >+  tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
> >(decl), type);
> >   TREE_ADDRESSABLE (field) = 1;
> >   insert_field_into_struct (get_frame_type (info), field);
> >   return field;
> >@@ -783,9 +780,8 @@ get_nl_goto_field (struct nesting_info *info)
> >       type = build_array_type
> > 	(type, build_index_type (size_int (size)));
> > 
> >-      field = make_node (FIELD_DECL);
> >-      DECL_NAME (field) = get_identifier ("__nl_goto_buf");
> >-      TREE_TYPE (field) = type;
> >+      field = build_decl (input_location, FIELD_DECL,
> >+			  get_identifier ("__nl_goto_buf"), type);
> >       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
> >       TREE_ADDRESSABLE (field) = 1;
> > 
> >@@ -3378,10 +3374,10 @@ finalize_nesting_tree_1 (struct nesting_info
> >*root)
> >/* Create a field in the FRAME record to hold the frame base address
> >for
> >	 this stack frame.  Since it will be used only by the debugger, put it
> >	 at the end of the record in order not to shift all other offsets.  */
> >-      tree fb_decl = make_node (FIELD_DECL);
> >+      tree fb_decl = build_decl (input_location, FIELD_DECL,
> >+				 get_identifier ("FRAME_BASE.PARENT"),
> >+				 ptr_type_node);
> > 
> >-      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
> >-      TREE_TYPE (fb_decl) = ptr_type_node;
> >       TREE_ADDRESSABLE (fb_decl) = 1;
> >       DECL_CONTEXT (fb_decl) = root->frame_type;
> >TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS
> >(root->frame_type),
> >diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
> >index 42585412325..dc6f412c02d 100644
> >--- a/gcc/tree-ssa-ccp.c
> >+++ b/gcc/tree-ssa-ccp.c
> >@@ -3067,9 +3067,9 @@ optimize_atomic_bit_test_and
> >(gimple_stmt_iterator *gsip,
> >       tree temp = NULL_TREE;
> >       if (!throws || after || single_pred_p (e->dest))
> > 	{
> >-	  temp = make_node (DEBUG_EXPR_DECL);
> >+	  temp = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+			     TREE_TYPE (lhs));
> > 	  DECL_ARTIFICIAL (temp) = 1;
> >-	  TREE_TYPE (temp) = TREE_TYPE (lhs);
> > 	  SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
> > 	  tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
> > 	  g = gimple_build_debug_bind (temp, t, g);
> >diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
> >index 12a8a49a307..953b3d0b2f1 100644
> >--- a/gcc/tree-ssa-loop-ivopts.c
> >+++ b/gcc/tree-ssa-loop-ivopts.c
> >@@ -7677,9 +7677,9 @@ remove_unused_ivs (struct ivopts_data *data,
> >bitmap toremove)
> > 	      comp = unshare_expr (comp);
> > 	      if (count > 1)
> > 		{
> >-		  tree vexpr = make_node (DEBUG_EXPR_DECL);
> >+		  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
> >+					   nullptr, TREE_TYPE (comp));
> > 		  DECL_ARTIFICIAL (vexpr) = 1;
> >-		  TREE_TYPE (vexpr) = TREE_TYPE (comp);
> > 		  if (SSA_NAME_VAR (def))
> > 		    SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (def)));
> > 		  else
> >diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> >index 1777bff2f7c..25589716a11 100644
> >--- a/gcc/tree-ssa-phiopt.c
> >+++ b/gcc/tree-ssa-phiopt.c
> >@@ -2302,18 +2302,18 @@ spaceship_replacement (basic_block cond_bb,
> >basic_block middle_bb,
> > 	     all floating point numbers should be comparable.  */
> > 	  gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
> > 	  tree type = TREE_TYPE (phires);
> >-	  tree temp1 = make_node (DEBUG_EXPR_DECL);
> >+	  tree temp1 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				   type);
> > 	  DECL_ARTIFICIAL (temp1) = 1;
> >-	  TREE_TYPE (temp1) = type;
> > 	  SET_DECL_MODE (temp1, TYPE_MODE (type));
> > 	  tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
> > 	  t = build3 (COND_EXPR, type, t, build_one_cst (type),
> > 		      build_int_cst (type, -1));
> > 	  gimple *g = gimple_build_debug_bind (temp1, t, phi);
> > 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
> >-	  tree temp2 = make_node (DEBUG_EXPR_DECL);
> >+	  tree temp2 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				   type);
> > 	  DECL_ARTIFICIAL (temp2) = 1;
> >-	  TREE_TYPE (temp2) = type;
> > 	  SET_DECL_MODE (temp2, TYPE_MODE (type));
> > 	  t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
> > 	  t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
> >diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
> >index 2dd4435b981..48f6117a731 100644
> >--- a/gcc/tree-ssa-reassoc.c
> >+++ b/gcc/tree-ssa-reassoc.c
> >@@ -1214,14 +1214,14 @@ make_new_ssa_for_def (gimple *stmt, enum
> >tree_code opcode, tree op)
> > 	{
> > 	  if (new_debug_lhs == NULL_TREE)
> > 	    {
> >-	      new_debug_lhs = make_node (DEBUG_EXPR_DECL);
> >+	      new_debug_lhs = build_decl (input_location, DEBUG_EXPR_DECL,
> >+					  nullptr, TREE_TYPE (lhs));
> > 	      gdebug *def_temp
> > 		= gimple_build_debug_bind (new_debug_lhs,
> > 					   build2 (opcode, TREE_TYPE (lhs),
> > 						   new_lhs, op),
> > 					   stmt);
> > 	      DECL_ARTIFICIAL (new_debug_lhs) = 1;
> >-	      TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
> > 	      SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
> > 	      gimple_set_uid (def_temp, gimple_uid (stmt));
> > 	      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> >diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> >index 4cc400d3c2e..83caadb37c8 100644
> >--- a/gcc/tree-ssa.c
> >+++ b/gcc/tree-ssa.c
> >@@ -434,14 +434,14 @@ insert_debug_temp_for_var_def
> >(gimple_stmt_iterator *gsi, tree var)
> >       else
> > 	{
> > 	  gdebug *def_temp;
> >-	  tree vexpr = make_node (DEBUG_EXPR_DECL);
> >+	  tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >+				   TREE_TYPE (value));
> > 
> > 	  def_temp = gimple_build_debug_bind (vexpr,
> > 					      unshare_expr (value),
> > 					      def_stmt);
> > 
> > 	  DECL_ARTIFICIAL (vexpr) = 1;
> >-	  TREE_TYPE (vexpr) = TREE_TYPE (value);
> > 	  if (DECL_P (value))
> > 	    SET_DECL_MODE (vexpr, DECL_MODE (value));
> > 	  else
> >diff --git a/gcc/tree.c b/gcc/tree.c
> >index 1aa6e557a04..a90097a51c6 100644
> >--- a/gcc/tree.c
> >+++ b/gcc/tree.c
> >@@ -1175,7 +1175,7 @@ allocate_decl_uid (void)
> >    Achoo!  I got a code in the node.  */
> > 
> > tree
> >-make_node (enum tree_code code MEM_STAT_DECL)
> >+make_node (enum tree_code code, make_node_caller caller MEM_STAT_DECL)
> > {
> >   tree t;
> >   enum tree_code_class type = TREE_CODE_CLASS (code);
> >@@ -1194,27 +1194,7 @@ make_node (enum tree_code code MEM_STAT_DECL)
> >       break;
> > 
> >     case tcc_declaration:
> >-      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> >-	{
> >-	  if (code == FUNCTION_DECL)
> >-	    {
> >-	      SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
> >-	      SET_DECL_MODE (t, FUNCTION_MODE);
> >-	    }
> >-	  else
> >-	    SET_DECL_ALIGN (t, 1);
> >-	}
> >-      DECL_SOURCE_LOCATION (t) = input_location;
> >-      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> >-	DECL_UID (t) = --next_debug_decl_uid;
> >-      else
> >-	{
> >-	  DECL_UID (t) = allocate_decl_uid ();
> >-	  SET_DECL_PT_UID (t, -1);
> >-	}
> >-      if (TREE_CODE (t) == LABEL_DECL)
> >-	LABEL_DECL_UID (t) = -1;
> >-
> >+      gcc_assert (caller == BUILD_DECL_MKNODE_CALLER);
> >       break;
> > 
> >     case tcc_type:
> >@@ -5257,10 +5237,29 @@ tree
> > build_decl (location_t loc, enum tree_code code, tree name,
> >     		 tree type MEM_STAT_DECL)
> > {
> >-  tree t;
> >-
> >-  t = make_node (code PASS_MEM_STAT);
> >+  tree t = make_node (code, BUILD_DECL_MKNODE_CALLER PASS_MEM_STAT);
> >   DECL_SOURCE_LOCATION (t) = loc;
> >+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> >+    {
> >+      if (code == FUNCTION_DECL)
> >+	{
> >+	  SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
> >+	  SET_DECL_MODE (t, FUNCTION_MODE);
> >+	}
> >+      else
> >+	SET_DECL_ALIGN (t, 1);
> >+    }
> >+
> >+  if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> >+    DECL_UID (t) = --next_debug_decl_uid;
> >+  else
> >+    {
> >+      DECL_UID (t) = allocate_decl_uid ();
> >+      SET_DECL_PT_UID (t, -1);
> >+    }
> >+
> >+  if (TREE_CODE (t) == LABEL_DECL)
> >+    LABEL_DECL_UID (t) = -1;
> > 
> > /*  if (type == error_mark_node)
> >     type = integer_type_node; */
> >diff --git a/gcc/tree.h b/gcc/tree.h
> >index 8bdf16d8b4a..86dd32354f2 100644
> >--- a/gcc/tree.h
> >+++ b/gcc/tree.h
> >@@ -4357,11 +4357,18 @@ extern size_t tree_code_size (enum tree_code);
> > /* Allocate and return a new UID from the DECL_UID namespace.  */
> > extern int allocate_decl_uid (void);
> > 
> >+/* expected callers of make_node.  */
> >+enum make_node_caller
> >+{
> >+  UNKNOWN_MKNODE_CALLER,
> >+  BUILD_DECL_MKNODE_CALLER
> >+};
> >+
> > /* Lowest level primitive for allocating a node.
> >    The TREE_CODE is the only argument.  Contents are initialized
> >    to zero except for a few of the common fields.  */
> > 
> >-extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
> >+extern tree make_node (enum tree_code, enum make_node_caller caller =
> >UNKNOWN_MKNODE_CALLER CXX_MEM_STAT_INFO);
> > 
> > /* Free tree node.  */
> > 
> >diff --git a/gcc/varasm.c b/gcc/varasm.c
> >index 53cf6dea3f3..fa6799e48fb 100644
> >--- a/gcc/varasm.c
> >+++ b/gcc/varasm.c
> >@@ -8229,21 +8229,21 @@ output_file_directive (FILE *asm_file, const
> >char *input_name)
> > rtx
> > make_debug_expr_from_rtl (const_rtx exp)
> > {
> >-  tree ddecl = make_node (DEBUG_EXPR_DECL), type;
> >+  tree type;
> >   machine_mode mode = GET_MODE (exp);
> >   rtx dval;
> > 
> >-  DECL_ARTIFICIAL (ddecl) = 1;
> >   if (REG_P (exp) && REG_EXPR (exp))
> >     type = TREE_TYPE (REG_EXPR (exp));
> >   else if (MEM_P (exp) && MEM_EXPR (exp))
> >     type = TREE_TYPE (MEM_EXPR (exp));
> >   else
> >     type = NULL_TREE;
> >-  if (type && TYPE_MODE (type) == mode)
> >-    TREE_TYPE (ddecl) = type;
> >-  else
> >-    TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
> >+  if (!type || TYPE_MODE (type) != mode)
> >+    type = lang_hooks.types.type_for_mode (mode, 1);
> >+
> >+  tree ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> >type);
> >+  DECL_ARTIFICIAL (ddecl) = 1;
> >   SET_DECL_MODE (ddecl, mode);
> >   dval = gen_rtx_DEBUG_EXPR (mode);
> >   DEBUG_EXPR_TREE_DECL (dval) = ddecl;
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 10:23         ` Trevor Saunders
@ 2021-07-01 12:48           ` Richard Biener
  0 siblings, 0 replies; 25+ messages in thread
From: Richard Biener @ 2021-07-01 12:48 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On Thu, Jul 1, 2021 at 12:24 PM Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>
> On Wed, Jun 30, 2021 at 09:09:33PM +0200, Richard Biener wrote:
> > On June 30, 2021 2:33:30 PM GMT+02:00, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> > >On Wed, Jun 30, 2021 at 11:00:37AM +0200, Richard Biener wrote:
> > >> On Wed, Jun 30, 2021 at 7:37 AM Trevor Saunders
> > ><tbsaunde@tbsaunde.org> wrote:
> > >> >
> > >> > This makes it possible to assert if input_location is used during
> > >the lifetime
> > >> > of a scope.  This will allow us to find places that currently use
> > >it within a
> > >> > function and its callees, or prevent adding uses within the
> > >lifetime of a
> > >> > function after all existing uses are removed.
> > >> >
> > >> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > >>
> > >> I'm not sure about the general approach but I have comments about
> > >> input_location.
> > >>
> > >> IMHO a good first step would be to guard the input_location
> > >declaration with sth
> > >> like
> > >>
> > >> #ifndef GCC_NEED_INPUT_LOCATION
> > >> extern location_t input_location;
> > >> #endif
> > >
> > >I think that's another reasonable step, my one concern is that it can
> > >be
> > >useful to push the usage of input_location, or any other global from
> > >the
> > >bottom of the stack to a caller that can provide a better argument
> > >eventually, but first just use the global.  Doing this sort of
> > >refactoring is harder if you need to add files with callers to the
> > >whitelist, and kind of defeats the point of the whitelist.  Consider
> > >the
> > >below commit, that is untested, but perhaps I should have included in
> > >this series as somewhat related.
> > >
> > >As for this approach being limited to functions that's somewhat true,
> > >but since it effects all functions called while its on the stack, it
> > >would mean once enough infrastructure is fixed, we could add one the
> > >execute method of a pass and nothing in the pass could touch
> > >input_location.  The limit also means that it doesn't get in the way of
> > >the above sort of refactoring, but as it proceeds lower level functions
> > >that now take explicit arguments can be called from contexts that ban
> > >use of input_location.
> > >
> > >Trev
> > >
> > >From efd04d2df4163dd930f489d9fba1455bfb368114 Mon Sep 17 00:00:00 2001
> > >From: Trevor Saunders <tbsaunde@tbsaunde.org>
> > >Date: Sun, 27 Jun 2021 02:10:26 -0400
> > >Subject: [PATCH] force decls to be allocated through build_decl to
> > >initialize
> > > them
> > >To: gcc-patches@gcc.gnu.org
> > >
> > >prior to this commit all calls to build_decl used input_location, even
> > >if
> > >temporarily  until build_decl reset the location to something else that
> > >it was
> > >told was the proper location.  To avoid using the global we need the
> > >caller to
> > >pass in the location it wants, however that's not possible with
> > >make_node since
> > >it makes other types of nodes.  So we force all callers who wish to
> > >make a decl
> > >to go through build_decl which already takes a location argument.  To
> > >avoid
> > >changing behavior this just explicitly passes in input_location to
> > >build_decl
> > >for callers of make_node that create a decl, however it would seem in
> > >many of
> > >these cases that the location of the decl being coppied might be a
> > >better
> > >location.
> >
> > If make_node really uses input_location that's what should change (to UNONOWN_LOCATION).  But yes, it might change behavior to the worse...
>
> make_node really does, when making a decl.  My idea was to force using
> build_decl rather than make_node when making a decl, that way make_node
> could stop doing anything special for decls including setting the
> location, implicitly leaving it as UNKNOWN_LOCATION since it clears the
> object when allocating it.  Then I used input_location as an argument to
> build_decl wherever the location currently isn't set to something else,
> so as not to make things worse.  That way callers that know the right
> location do not need to touch input_location, and it pushes the problem
> to the places where we need to work on finding a better location, and
> might be able to do so rather than deep in make_node.  Does that seem
> reasonable as an incremental step to using input_location less, even
> without trying to block its use?

I guess so - I was just worried that make_node is used for a reason
in some places (when we build a VAR/PARM/RESULT_DECL that
avoids calling layout_decl for example).  Note build_decl still invokes
make_node (and thus refers to input_location ...), but yes, if you
catch all decl cases to go through build_decl then you can be confident
in changing make_node ...

Richard.

>
> Thanks
>
> Trev
>
> >
> > Richard.
> >
> > >---
> > > gcc/cfgexpand.c              |  8 +++---
> > > gcc/cp/cp-gimplify.c         |  5 ++--
> > > gcc/fortran/trans-decl.c     |  5 ++--
> > > gcc/fortran/trans-types.c    |  4 +--
> > > gcc/ipa-param-manipulation.c |  8 +++---
> > > gcc/objc/objc-act.c          | 16 +++++-------
> > > gcc/omp-simd-clone.c         |  4 +--
> > > gcc/stor-layout.c            |  2 +-
> > > gcc/tree-inline.c            | 13 +++++-----
> > > gcc/tree-into-ssa.c          |  4 +--
> > > gcc/tree-nested.c            | 24 ++++++++----------
> > > gcc/tree-ssa-ccp.c           |  4 +--
> > > gcc/tree-ssa-loop-ivopts.c   |  4 +--
> > > gcc/tree-ssa-phiopt.c        |  8 +++---
> > > gcc/tree-ssa-reassoc.c       |  4 +--
> > > gcc/tree-ssa.c               |  4 +--
> > > gcc/tree.c                   | 49 ++++++++++++++++++------------------
> > > gcc/tree.h                   |  9 ++++++-
> > > gcc/varasm.c                 | 12 ++++-----
> > > 19 files changed, 93 insertions(+), 94 deletions(-)
> > >
> > >diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> > >index 3edd53c37dc..fea8c837c80 100644
> > >--- a/gcc/cfgexpand.c
> > >+++ b/gcc/cfgexpand.c
> > >@@ -4342,10 +4342,10 @@ avoid_deep_ter_for_debug (gimple *stmt, int
> > >depth)
> > >       tree &vexpr = deep_ter_debug_map->get_or_insert (use);
> > >       if (vexpr != NULL)
> > >         continue;
> > >-      vexpr = make_node (DEBUG_EXPR_DECL);
> > >+      vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                          TREE_TYPE (use));
> > >       gimple *def_temp = gimple_build_debug_bind (vexpr, use, g);
> > >       DECL_ARTIFICIAL (vexpr) = 1;
> > >-      TREE_TYPE (vexpr) = TREE_TYPE (use);
> > >       SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (use)));
> > >       gimple_stmt_iterator gsi = gsi_for_stmt (g);
> > >       gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
> > >@@ -5899,14 +5899,14 @@ expand_gimple_basic_block (basic_block bb, bool
> > >disable_tail_calls)
> > >                    temporary.  */
> > >                 gimple *debugstmt;
> > >                 tree value = gimple_assign_rhs_to_tree (def);
> > >-                tree vexpr = make_node (DEBUG_EXPR_DECL);
> > >                 rtx val;
> > >                 machine_mode mode;
> > >
> > >                 set_curr_insn_location (gimple_location (def));
> > >
> > >+                tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
> > >+                                         nullptr, TREE_TYPE (value));
> > >                 DECL_ARTIFICIAL (vexpr) = 1;
> > >-                TREE_TYPE (vexpr) = TREE_TYPE (value);
> > >                 if (DECL_P (value))
> > >                   mode = DECL_MODE (value);
> > >                 else
> > >diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> > >index 00b7772fe0d..d537e547169 100644
> > >--- a/gcc/cp/cp-gimplify.c
> > >+++ b/gcc/cp/cp-gimplify.c
> > >@@ -1217,8 +1217,9 @@ cp_genericize_r (tree *stmt_p, int
> > >*walk_subtrees, void *data)
> > >           /* Omit from the GENERIC, the back-end can't handle it.  */;
> > >         else
> > >           {
> > >-            tree using_directive = make_node (IMPORTED_DECL);
> > >-            TREE_TYPE (using_directive) = void_type_node;
> > >+            tree using_directive = build_decl (input_location,
> > >+                                               IMPORTED_DECL, nullptr,
> > >+                                               void_type_node);
> > >             DECL_CONTEXT (using_directive) = current_function_decl;
> > >
> > >             IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
> > >diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> > >index 479ba6fa6ce..b726c2f2bdc 100644
> > >--- a/gcc/fortran/trans-decl.c
> > >+++ b/gcc/fortran/trans-decl.c
> > >@@ -5262,10 +5262,9 @@ generate_namelist_decl (gfc_symbol * sym)
> > > CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, nml->sym->backend_decl);
> > >     }
> > >
> > >-  decl = make_node (NAMELIST_DECL);
> > >-  TREE_TYPE (decl) = void_type_node;
> > >+  decl = build_decl (input_location, NAMELIST_DECL, get_identifier
> > >(sym->name),
> > >+                 void_type_node);
> > >NAMELIST_DECL_ASSOCIATED_DECL (decl) = build_constructor (NULL_TREE,
> > >nml_decls);
> > >-  DECL_NAME (decl) = get_identifier (sym->name);
> > >   return decl;
> > > }
> > >
> > >diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
> > >index 5582e404df9..8b4d5c99665 100644
> > >--- a/gcc/fortran/trans-types.c
> > >+++ b/gcc/fortran/trans-types.c
> > >@@ -3417,9 +3417,9 @@ gfc_get_array_descr_info (const_tree type, struct
> > >array_descr_info *info)
> > >   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
> > >   if (!base_decl)
> > >     {
> > >-      base_decl = make_node (DEBUG_EXPR_DECL);
> > >+      base_decl = build_decl (input_location, DEBUG_EXPR_DECL,
> > >nullptr,
> > >+                          indirect ? build_pointer_type (ptype) : ptype);
> > >       DECL_ARTIFICIAL (base_decl) = 1;
> > >-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) :
> > >ptype;
> > >       SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
> > >       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
> > >     }
> > >diff --git a/gcc/ipa-param-manipulation.c
> > >b/gcc/ipa-param-manipulation.c
> > >index f2d91476655..242fa4dee1d 100644
> > >--- a/gcc/ipa-param-manipulation.c
> > >+++ b/gcc/ipa-param-manipulation.c
> > >@@ -834,9 +834,9 @@ ipa_param_adjustments::modify_call (gcall *stmt,
> > >           }
> > >       if (ddecl == NULL)
> > >         {
> > >-          ddecl = make_node (DEBUG_EXPR_DECL);
> > >+          ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                              TREE_TYPE (origin));
> > >           DECL_ARTIFICIAL (ddecl) = 1;
> > >-          TREE_TYPE (ddecl) = TREE_TYPE (origin);
> > >           SET_DECL_MODE (ddecl, DECL_MODE (origin));
> > >
> > >           vec_safe_push (*debug_args, origin);
> > >@@ -1883,10 +1883,10 @@ ipa_param_body_adjustments::reset_debug_stmts
> > >()
> > >         gcc_assert (is_gimple_debug (stmt));
> > >         if (vexpr == NULL && gsip != NULL)
> > >           {
> > >-            vexpr = make_node (DEBUG_EXPR_DECL);
> > >+            vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                                TREE_TYPE (name));
> > >             def_temp = gimple_build_debug_source_bind (vexpr, decl, NULL);
> > >             DECL_ARTIFICIAL (vexpr) = 1;
> > >-            TREE_TYPE (vexpr) = TREE_TYPE (name);
> > >             SET_DECL_MODE (vexpr, DECL_MODE (decl));
> > >             gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
> > >           }
> > >diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
> > >index 8d106a4de26..259ce520143 100644
> > >--- a/gcc/objc/objc-act.c
> > >+++ b/gcc/objc/objc-act.c
> > >@@ -1295,12 +1295,11 @@ objc_add_property_declaration (location_t
> > >location, tree decl,
> > >     }
> > >
> > >   /* Create a PROPERTY_DECL node.  */
> > >-  tree property_decl = make_node (PROPERTY_DECL);
> > >+  tree property_decl = build_decl (DECL_SOURCE_LOCATION (decl),
> > >PROPERTY_DECL,
> > >+                               nullptr, TREE_TYPE (decl));
> > >
> > >   /* Copy the basic information from the original decl.  */
> > >   tree p_type = TREE_TYPE (decl);
> > >-  TREE_TYPE (property_decl) = p_type;
> > >-  DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
> > >   TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
> > >
> > >   /* Add property-specific information.  */
> > >@@ -1434,10 +1433,9 @@ maybe_make_artificial_property_decl (tree
> > >interface, tree implementation,
> > >       /* Create an artificial property declaration with the
> > >      information we collected on the type and getter/setter
> > >      names.  */
> > >-      property_decl = make_node (PROPERTY_DECL);
> > >+      property_decl = build_decl (input_location, PROPERTY_DECL,
> > >nullptr,
> > >+                              type);
> > >
> > >-      TREE_TYPE (property_decl) = type;
> > >-      DECL_SOURCE_LOCATION (property_decl) = input_location;
> > >       TREE_DEPRECATED (property_decl) = 0;
> > >       DECL_ARTIFICIAL (property_decl) = 1;
> > >
> > >@@ -4889,9 +4887,8 @@ objc_build_keyword_decl (tree key_name, tree
> > >arg_type,
> > >   /* If no type is specified, default to "id".  */
> > >   arg_type = adjust_type_for_id_default (arg_type);
> > >
> > >-  keyword_decl = make_node (KEYWORD_DECL);
> > >+  keyword_decl = build_decl (input_location, KEYWORD_DECL, nullptr,
> > >arg_type);
> > >
> > >-  TREE_TYPE (keyword_decl) = arg_type;
> > >   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
> > >   KEYWORD_KEY_NAME (keyword_decl) = key_name;
> > >   DECL_ATTRIBUTES (keyword_decl) = attributes;
> > >@@ -4975,8 +4972,7 @@ build_method_decl (enum tree_code code, tree
> > >ret_type, tree selector,
> > >      type of the method.  We may want to change this, and store the
> > >      entire function type in there (eg, it may be used to simplify
> > >      dealing with attributes below).  */
> > >-  method_decl = make_node (code);
> > >-  TREE_TYPE (method_decl) = ret_type;
> > >+  method_decl = build_decl (input_location, code, nullptr, ret_type);
> > >
> > >   /* If we have a keyword selector, create an identifier_node that
> > >      represents the full selector name (`:' included)...  */
> > >diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
> > >index b772b7ff520..03189f4c50f 100644
> > >--- a/gcc/omp-simd-clone.c
> > >+++ b/gcc/omp-simd-clone.c
> > >@@ -910,10 +910,10 @@ ipa_simd_modify_stmt_ops (tree *tp, int
> > >*walk_subtrees, void *data)
> > >       gimple *stmt;
> > >       if (is_gimple_debug (info->stmt))
> > >     {
> > >-      tree vexpr = make_node (DEBUG_EXPR_DECL);
> > >+      tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                               TREE_TYPE (repl));
> > >       stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
> > >       DECL_ARTIFICIAL (vexpr) = 1;
> > >-      TREE_TYPE (vexpr) = TREE_TYPE (repl);
> > >       SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (repl)));
> > >       repl = vexpr;
> > >     }
> > >diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
> > >index 242452f2acf..7811fc6c302 100644
> > >--- a/gcc/stor-layout.c
> > >+++ b/gcc/stor-layout.c
> > >@@ -2024,7 +2024,7 @@ finalize_type_size (tree type)
> > > static tree
> > > start_bitfield_representative (tree field)
> > > {
> > >-  tree repr = make_node (FIELD_DECL);
> > >+  tree repr = build_decl (input_location, FIELD_DECL, nullptr,
> > >nullptr);
> > >   DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field);
> > >   /* Force the representative to begin at a BITS_PER_UNIT aligned
> > >      boundary - C++ may use tail-padding of a base object to
> > >diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> > >index 9e041ca4d56..0204ce20282 100644
> > >--- a/gcc/tree-inline.c
> > >+++ b/gcc/tree-inline.c
> > >@@ -193,7 +193,6 @@ remap_ssa_name (tree name, copy_body_data *id)
> > >       && id->entry_bb == NULL
> > >       && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (cfun)))
> > >     {
> > >-      tree vexpr = make_node (DEBUG_EXPR_DECL);
> > >       gimple *def_temp;
> > >       gimple_stmt_iterator gsi;
> > >       tree val = SSA_NAME_VAR (name);
> > >@@ -210,9 +209,11 @@ remap_ssa_name (tree name, copy_body_data *id)
> > >       n = id->decl_map->get (val);
> > >       if (n && TREE_CODE (*n) == DEBUG_EXPR_DECL)
> > >         return *n;
> > >+
> > >+      tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                               TREE_TYPE (name));
> > >       def_temp = gimple_build_debug_source_bind (vexpr, val, NULL);
> > >       DECL_ARTIFICIAL (vexpr) = 1;
> > >-      TREE_TYPE (vexpr) = TREE_TYPE (name);
> > >       SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (name)));
> > >       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN
> > >(cfun)));
> > >       gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
> > >@@ -6494,9 +6495,9 @@ tree_function_versioning (tree old_decl, tree
> > >new_decl,
> > >           debug_args = decl_debug_args_insert (new_decl);
> > >           len = vec_safe_length (*debug_args);
> > >         }
> > >-      ddecl = make_node (DEBUG_EXPR_DECL);
> > >+      ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                          TREE_TYPE (parm));
> > >       DECL_ARTIFICIAL (ddecl) = 1;
> > >-      TREE_TYPE (ddecl) = TREE_TYPE (parm);
> > >       SET_DECL_MODE (ddecl, DECL_MODE (parm));
> > >       vec_safe_push (*debug_args, DECL_ORIGIN (parm));
> > >       vec_safe_push (*debug_args, ddecl);
> > >@@ -6525,10 +6526,10 @@ tree_function_versioning (tree old_decl, tree
> > >new_decl,
> > >             var = TREE_CHAIN (var);
> > >           if (var == NULL_TREE)
> > >             break;
> > >-          vexpr = make_node (DEBUG_EXPR_DECL);
> > >           tree parm = (**debug_args)[i];
> > >+          vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                              TREE_TYPE (parm));
> > >           DECL_ARTIFICIAL (vexpr) = 1;
> > >-          TREE_TYPE (vexpr) = TREE_TYPE (parm);
> > >           SET_DECL_MODE (vexpr, DECL_MODE (parm));
> > >           def_temp = gimple_build_debug_bind (var, vexpr, NULL);
> > >           gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT);
> > >diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
> > >index 8045e34df26..f9933305957 100644
> > >--- a/gcc/tree-into-ssa.c
> > >+++ b/gcc/tree-into-ssa.c
> > >@@ -1284,10 +1284,10 @@ rewrite_debug_stmt_uses (gimple *stmt)
> > >           if (def == NULL_TREE)
> > >             {
> > >               gimple *def_temp;
> > >-              def = make_node (DEBUG_EXPR_DECL);
> > >+              def = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                                TREE_TYPE (var));
> > >               def_temp = gimple_build_debug_source_bind (def, var, NULL);
> > >               DECL_ARTIFICIAL (def) = 1;
> > >-              TREE_TYPE (def) = TREE_TYPE (var);
> > >               SET_DECL_MODE (def, DECL_MODE (var));
> > >               gsi =
> > >              gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
> > >diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> > >index 9edd922a303..37e229477ec 100644
> > >--- a/gcc/tree-nested.c
> > >+++ b/gcc/tree-nested.c
> > >@@ -394,8 +394,8 @@ lookup_field_for_decl (struct nesting_info *info,
> > >tree decl,
> > >   if (!*slot)
> > >     {
> > >       tree type = get_frame_type (info);
> > >-      tree field = make_node (FIELD_DECL);
> > >-      DECL_NAME (field) = DECL_NAME (decl);
> > >+      tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
> > >(decl),
> > >+                           nullptr);
> > >
> > >       if (use_pointer_in_frame (decl))
> > >     {
> > >@@ -510,9 +510,8 @@ get_chain_field (struct nesting_info *info)
> > >     {
> > >       tree type = build_pointer_type (get_frame_type (info->outer));
> > >
> > >-      field = make_node (FIELD_DECL);
> > >-      DECL_NAME (field) = get_identifier ("__chain");
> > >-      TREE_TYPE (field) = type;
> > >+      field = build_decl (input_location, FIELD_DECL,
> > >+                      get_identifier ("__chain"), type);
> > >       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
> > >       DECL_NONADDRESSABLE_P (field) = 1;
> > >
> > >@@ -694,9 +693,7 @@ lookup_element_for_decl (struct nesting_info *info,
> > >tree decl,
> > > static tree
> > >create_field_for_decl (struct nesting_info *info, tree decl, tree type)
> > > {
> > >-  tree field = make_node (FIELD_DECL);
> > >-  DECL_NAME (field) = DECL_NAME (decl);
> > >-  TREE_TYPE (field) = type;
> > >+  tree field = build_decl (input_location, FIELD_DECL, DECL_NAME
> > >(decl), type);
> > >   TREE_ADDRESSABLE (field) = 1;
> > >   insert_field_into_struct (get_frame_type (info), field);
> > >   return field;
> > >@@ -783,9 +780,8 @@ get_nl_goto_field (struct nesting_info *info)
> > >       type = build_array_type
> > >     (type, build_index_type (size_int (size)));
> > >
> > >-      field = make_node (FIELD_DECL);
> > >-      DECL_NAME (field) = get_identifier ("__nl_goto_buf");
> > >-      TREE_TYPE (field) = type;
> > >+      field = build_decl (input_location, FIELD_DECL,
> > >+                      get_identifier ("__nl_goto_buf"), type);
> > >       SET_DECL_ALIGN (field, TYPE_ALIGN (type));
> > >       TREE_ADDRESSABLE (field) = 1;
> > >
> > >@@ -3378,10 +3374,10 @@ finalize_nesting_tree_1 (struct nesting_info
> > >*root)
> > >/* Create a field in the FRAME record to hold the frame base address
> > >for
> > >      this stack frame.  Since it will be used only by the debugger, put it
> > >      at the end of the record in order not to shift all other offsets.  */
> > >-      tree fb_decl = make_node (FIELD_DECL);
> > >+      tree fb_decl = build_decl (input_location, FIELD_DECL,
> > >+                             get_identifier ("FRAME_BASE.PARENT"),
> > >+                             ptr_type_node);
> > >
> > >-      DECL_NAME (fb_decl) = get_identifier ("FRAME_BASE.PARENT");
> > >-      TREE_TYPE (fb_decl) = ptr_type_node;
> > >       TREE_ADDRESSABLE (fb_decl) = 1;
> > >       DECL_CONTEXT (fb_decl) = root->frame_type;
> > >TYPE_FIELDS (root->frame_type) = chainon (TYPE_FIELDS
> > >(root->frame_type),
> > >diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
> > >index 42585412325..dc6f412c02d 100644
> > >--- a/gcc/tree-ssa-ccp.c
> > >+++ b/gcc/tree-ssa-ccp.c
> > >@@ -3067,9 +3067,9 @@ optimize_atomic_bit_test_and
> > >(gimple_stmt_iterator *gsip,
> > >       tree temp = NULL_TREE;
> > >       if (!throws || after || single_pred_p (e->dest))
> > >     {
> > >-      temp = make_node (DEBUG_EXPR_DECL);
> > >+      temp = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                         TREE_TYPE (lhs));
> > >       DECL_ARTIFICIAL (temp) = 1;
> > >-      TREE_TYPE (temp) = TREE_TYPE (lhs);
> > >       SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
> > >       tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
> > >       g = gimple_build_debug_bind (temp, t, g);
> > >diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
> > >index 12a8a49a307..953b3d0b2f1 100644
> > >--- a/gcc/tree-ssa-loop-ivopts.c
> > >+++ b/gcc/tree-ssa-loop-ivopts.c
> > >@@ -7677,9 +7677,9 @@ remove_unused_ivs (struct ivopts_data *data,
> > >bitmap toremove)
> > >           comp = unshare_expr (comp);
> > >           if (count > 1)
> > >             {
> > >-              tree vexpr = make_node (DEBUG_EXPR_DECL);
> > >+              tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL,
> > >+                                       nullptr, TREE_TYPE (comp));
> > >               DECL_ARTIFICIAL (vexpr) = 1;
> > >-              TREE_TYPE (vexpr) = TREE_TYPE (comp);
> > >               if (SSA_NAME_VAR (def))
> > >                 SET_DECL_MODE (vexpr, DECL_MODE (SSA_NAME_VAR (def)));
> > >               else
> > >diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> > >index 1777bff2f7c..25589716a11 100644
> > >--- a/gcc/tree-ssa-phiopt.c
> > >+++ b/gcc/tree-ssa-phiopt.c
> > >@@ -2302,18 +2302,18 @@ spaceship_replacement (basic_block cond_bb,
> > >basic_block middle_bb,
> > >          all floating point numbers should be comparable.  */
> > >       gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
> > >       tree type = TREE_TYPE (phires);
> > >-      tree temp1 = make_node (DEBUG_EXPR_DECL);
> > >+      tree temp1 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                               type);
> > >       DECL_ARTIFICIAL (temp1) = 1;
> > >-      TREE_TYPE (temp1) = type;
> > >       SET_DECL_MODE (temp1, TYPE_MODE (type));
> > >       tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
> > >       t = build3 (COND_EXPR, type, t, build_one_cst (type),
> > >                   build_int_cst (type, -1));
> > >       gimple *g = gimple_build_debug_bind (temp1, t, phi);
> > >       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
> > >-      tree temp2 = make_node (DEBUG_EXPR_DECL);
> > >+      tree temp2 = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                               type);
> > >       DECL_ARTIFICIAL (temp2) = 1;
> > >-      TREE_TYPE (temp2) = type;
> > >       SET_DECL_MODE (temp2, TYPE_MODE (type));
> > >       t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
> > >       t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
> > >diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
> > >index 2dd4435b981..48f6117a731 100644
> > >--- a/gcc/tree-ssa-reassoc.c
> > >+++ b/gcc/tree-ssa-reassoc.c
> > >@@ -1214,14 +1214,14 @@ make_new_ssa_for_def (gimple *stmt, enum
> > >tree_code opcode, tree op)
> > >     {
> > >       if (new_debug_lhs == NULL_TREE)
> > >         {
> > >-          new_debug_lhs = make_node (DEBUG_EXPR_DECL);
> > >+          new_debug_lhs = build_decl (input_location, DEBUG_EXPR_DECL,
> > >+                                      nullptr, TREE_TYPE (lhs));
> > >           gdebug *def_temp
> > >             = gimple_build_debug_bind (new_debug_lhs,
> > >                                        build2 (opcode, TREE_TYPE (lhs),
> > >                                                new_lhs, op),
> > >                                        stmt);
> > >           DECL_ARTIFICIAL (new_debug_lhs) = 1;
> > >-          TREE_TYPE (new_debug_lhs) = TREE_TYPE (lhs);
> > >           SET_DECL_MODE (new_debug_lhs, TYPE_MODE (TREE_TYPE (lhs)));
> > >           gimple_set_uid (def_temp, gimple_uid (stmt));
> > >           gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> > >diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> > >index 4cc400d3c2e..83caadb37c8 100644
> > >--- a/gcc/tree-ssa.c
> > >+++ b/gcc/tree-ssa.c
> > >@@ -434,14 +434,14 @@ insert_debug_temp_for_var_def
> > >(gimple_stmt_iterator *gsi, tree var)
> > >       else
> > >     {
> > >       gdebug *def_temp;
> > >-      tree vexpr = make_node (DEBUG_EXPR_DECL);
> > >+      tree vexpr = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >+                               TREE_TYPE (value));
> > >
> > >       def_temp = gimple_build_debug_bind (vexpr,
> > >                                           unshare_expr (value),
> > >                                           def_stmt);
> > >
> > >       DECL_ARTIFICIAL (vexpr) = 1;
> > >-      TREE_TYPE (vexpr) = TREE_TYPE (value);
> > >       if (DECL_P (value))
> > >         SET_DECL_MODE (vexpr, DECL_MODE (value));
> > >       else
> > >diff --git a/gcc/tree.c b/gcc/tree.c
> > >index 1aa6e557a04..a90097a51c6 100644
> > >--- a/gcc/tree.c
> > >+++ b/gcc/tree.c
> > >@@ -1175,7 +1175,7 @@ allocate_decl_uid (void)
> > >    Achoo!  I got a code in the node.  */
> > >
> > > tree
> > >-make_node (enum tree_code code MEM_STAT_DECL)
> > >+make_node (enum tree_code code, make_node_caller caller MEM_STAT_DECL)
> > > {
> > >   tree t;
> > >   enum tree_code_class type = TREE_CODE_CLASS (code);
> > >@@ -1194,27 +1194,7 @@ make_node (enum tree_code code MEM_STAT_DECL)
> > >       break;
> > >
> > >     case tcc_declaration:
> > >-      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > >-    {
> > >-      if (code == FUNCTION_DECL)
> > >-        {
> > >-          SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
> > >-          SET_DECL_MODE (t, FUNCTION_MODE);
> > >-        }
> > >-      else
> > >-        SET_DECL_ALIGN (t, 1);
> > >-    }
> > >-      DECL_SOURCE_LOCATION (t) = input_location;
> > >-      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> > >-    DECL_UID (t) = --next_debug_decl_uid;
> > >-      else
> > >-    {
> > >-      DECL_UID (t) = allocate_decl_uid ();
> > >-      SET_DECL_PT_UID (t, -1);
> > >-    }
> > >-      if (TREE_CODE (t) == LABEL_DECL)
> > >-    LABEL_DECL_UID (t) = -1;
> > >-
> > >+      gcc_assert (caller == BUILD_DECL_MKNODE_CALLER);
> > >       break;
> > >
> > >     case tcc_type:
> > >@@ -5257,10 +5237,29 @@ tree
> > > build_decl (location_t loc, enum tree_code code, tree name,
> > >                      tree type MEM_STAT_DECL)
> > > {
> > >-  tree t;
> > >-
> > >-  t = make_node (code PASS_MEM_STAT);
> > >+  tree t = make_node (code, BUILD_DECL_MKNODE_CALLER PASS_MEM_STAT);
> > >   DECL_SOURCE_LOCATION (t) = loc;
> > >+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > >+    {
> > >+      if (code == FUNCTION_DECL)
> > >+    {
> > >+      SET_DECL_ALIGN (t, FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY));
> > >+      SET_DECL_MODE (t, FUNCTION_MODE);
> > >+    }
> > >+      else
> > >+    SET_DECL_ALIGN (t, 1);
> > >+    }
> > >+
> > >+  if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> > >+    DECL_UID (t) = --next_debug_decl_uid;
> > >+  else
> > >+    {
> > >+      DECL_UID (t) = allocate_decl_uid ();
> > >+      SET_DECL_PT_UID (t, -1);
> > >+    }
> > >+
> > >+  if (TREE_CODE (t) == LABEL_DECL)
> > >+    LABEL_DECL_UID (t) = -1;
> > >
> > > /*  if (type == error_mark_node)
> > >     type = integer_type_node; */
> > >diff --git a/gcc/tree.h b/gcc/tree.h
> > >index 8bdf16d8b4a..86dd32354f2 100644
> > >--- a/gcc/tree.h
> > >+++ b/gcc/tree.h
> > >@@ -4357,11 +4357,18 @@ extern size_t tree_code_size (enum tree_code);
> > > /* Allocate and return a new UID from the DECL_UID namespace.  */
> > > extern int allocate_decl_uid (void);
> > >
> > >+/* expected callers of make_node.  */
> > >+enum make_node_caller
> > >+{
> > >+  UNKNOWN_MKNODE_CALLER,
> > >+  BUILD_DECL_MKNODE_CALLER
> > >+};
> > >+
> > > /* Lowest level primitive for allocating a node.
> > >    The TREE_CODE is the only argument.  Contents are initialized
> > >    to zero except for a few of the common fields.  */
> > >
> > >-extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
> > >+extern tree make_node (enum tree_code, enum make_node_caller caller =
> > >UNKNOWN_MKNODE_CALLER CXX_MEM_STAT_INFO);
> > >
> > > /* Free tree node.  */
> > >
> > >diff --git a/gcc/varasm.c b/gcc/varasm.c
> > >index 53cf6dea3f3..fa6799e48fb 100644
> > >--- a/gcc/varasm.c
> > >+++ b/gcc/varasm.c
> > >@@ -8229,21 +8229,21 @@ output_file_directive (FILE *asm_file, const
> > >char *input_name)
> > > rtx
> > > make_debug_expr_from_rtl (const_rtx exp)
> > > {
> > >-  tree ddecl = make_node (DEBUG_EXPR_DECL), type;
> > >+  tree type;
> > >   machine_mode mode = GET_MODE (exp);
> > >   rtx dval;
> > >
> > >-  DECL_ARTIFICIAL (ddecl) = 1;
> > >   if (REG_P (exp) && REG_EXPR (exp))
> > >     type = TREE_TYPE (REG_EXPR (exp));
> > >   else if (MEM_P (exp) && MEM_EXPR (exp))
> > >     type = TREE_TYPE (MEM_EXPR (exp));
> > >   else
> > >     type = NULL_TREE;
> > >-  if (type && TYPE_MODE (type) == mode)
> > >-    TREE_TYPE (ddecl) = type;
> > >-  else
> > >-    TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
> > >+  if (!type || TYPE_MODE (type) != mode)
> > >+    type = lang_hooks.types.type_for_mode (mode, 1);
> > >+
> > >+  tree ddecl = build_decl (input_location, DEBUG_EXPR_DECL, nullptr,
> > >type);
> > >+  DECL_ARTIFICIAL (ddecl) = 1;
> > >   SET_DECL_MODE (ddecl, mode);
> > >   dval = gen_rtx_DEBUG_EXPR (mode);
> > >   DEBUG_EXPR_TREE_DECL (dval) = ddecl;
> >

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 10:16     ` Trevor Saunders
@ 2021-07-01 12:53       ` Richard Biener
  2021-07-01 15:40         ` David Malcolm
  2021-07-02 15:46       ` Jason Merrill
  1 sibling, 1 reply; 25+ messages in thread
From: Richard Biener @ 2021-07-01 12:53 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: David Malcolm, GCC Patches

On Thu, Jul 1, 2021 at 12:16 PM Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
>
> On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> > On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > > This makes it possible to assert if input_location is used during the
> > > lifetime
> > > of a scope.  This will allow us to find places that currently use it
> > > within a
> > > function and its callees, or prevent adding uses within the lifetime
> > > of a
> > > function after all existing uses are removed.
> > >
> > > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > >
> > > Trev
> >
> > [...snip...]
> >
> > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > index d58586f2526..3f68d1d79eb 100644
> > > --- a/gcc/diagnostic.c
> > > +++ b/gcc/diagnostic.c
> > > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> > >    auto_diagnostic_group d;
> > >    va_list ap;
> > >    va_start (ap, gmsgid);
> > > -  rich_location richloc (line_table, input_location);
> > > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> > >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> > >    va_end (ap);
> > >
> >
> > I actually make use of this in the analyzer: the analyzer sets
> > input_location to stmt->location when analyzing a given stmt - that
> > way, if the analyzer ICEs, the ICE is shown at the code construct that
> > crashed the analyzer.
> >
> > This behavior is useful to me, and would be lost with the proposed
> > patch.
>
> I made this change because otherwise if the compiler ICE's while access
> to input_location is blocked we end up infinitely recursing complaining
> we can't access it while trying to say where the last error was.  I was
> nervous about the change before, and now I agree we need something
> else.
>
> > Is there a better way of doing what I'm doing?
> >
> > Is the long-term goal of the patch kit to reduce our reliance on global
> > variables?  Are we ultimately still going to need a variable for "where
> > to show the ICE if gcc crashes"?  (perhaps stashing it in the
> > diagnostic_context???)
>
> Yes, the goal is ultimately removal of global state, however I'm not
> really ure what the better approach to your problem is, after all even
> moving it to the diagnostic context is sort of a global state, and sort
> of dupplicates input_location.  That said it is somewhat more
> constrained, so if it removes usage of input_location perhaps its
> worthwhile?

Reduction of global state is of course good - but in particular input_location
should be something only used during parsing because it's a quite
broken concept otherwise.  And fiddling with it tends to be quite fragile...
for example see g:7d6f7e92c3b737736a2d8ff97a71af9f230c2f88
for the "fun" you can have with "stale" values in input_location ...
IMHO users should have their own "copy", for example the gimplifier
instead of mucking with and using input_location could use a
similar state in its gimplify_ctx.

Richard.

> Sorry I'm not yet sure what to propose here.
>
> Trev
>
> >
> > Hope this is constructive
> > Dave
> >

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 12:53       ` Richard Biener
@ 2021-07-01 15:40         ` David Malcolm
  2021-07-01 16:04           ` David Malcolm
  2021-07-02  0:44           ` [PATCH 2/4] allow poisoning input_location in ranges it should not be used Trevor Saunders
  0 siblings, 2 replies; 25+ messages in thread
From: David Malcolm @ 2021-07-01 15:40 UTC (permalink / raw)
  To: Richard Biener, Trevor Saunders; +Cc: GCC Patches

On Thu, 2021-07-01 at 14:53 +0200, Richard Biener wrote:
> On Thu, Jul 1, 2021 at 12:16 PM Trevor Saunders <
> tbsaunde@tbsaunde.org> wrote:
> > 
> > On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> > > On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > > > This makes it possible to assert if input_location is used
> > > > during the
> > > > lifetime
> > > > of a scope.  This will allow us to find places that currently
> > > > use it
> > > > within a
> > > > function and its callees, or prevent adding uses within the
> > > > lifetime
> > > > of a
> > > > function after all existing uses are removed.
> > > > 
> > > > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > > > 
> > > > Trev
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > > index d58586f2526..3f68d1d79eb 100644
> > > > --- a/gcc/diagnostic.c
> > > > +++ b/gcc/diagnostic.c
> > > > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> > > >    auto_diagnostic_group d;
> > > >    va_list ap;
> > > >    va_start (ap, gmsgid);
> > > > -  rich_location richloc (line_table, input_location);
> > > > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> > > >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> > > >    va_end (ap);
> > > > 
> > > 
> > > I actually make use of this in the analyzer: the analyzer sets
> > > input_location to stmt->location when analyzing a given stmt -
> > > that
> > > way, if the analyzer ICEs, the ICE is shown at the code construct
> > > that
> > > crashed the analyzer.
> > > 
> > > This behavior is useful to me, and would be lost with the
> > > proposed
> > > patch.
> > 
> > I made this change because otherwise if the compiler ICE's while
> > access
> > to input_location is blocked we end up infinitely recursing
> > complaining
> > we can't access it while trying to say where the last error was.  I
> > was
> > nervous about the change before, and now I agree we need something
> > else.
> > 
> > > Is there a better way of doing what I'm doing?
> > > 
> > > Is the long-term goal of the patch kit to reduce our reliance on
> > > global
> > > variables?  Are we ultimately still going to need a variable for
> > > "where
> > > to show the ICE if gcc crashes"?  (perhaps stashing it in the
> > > diagnostic_context???)
> > 
> > Yes, the goal is ultimately removal of global state, however I'm
> > not
> > really ure what the better approach to your problem is, after all
> > even
> > moving it to the diagnostic context is sort of a global state, and
> > sort
> > of dupplicates input_location.  That said it is somewhat more
> > constrained, so if it removes usage of input_location perhaps its
> > worthwhile?
> 
> Reduction of global state is of course good - but in particular
> input_location
> should be something only used during parsing because it's a quite
> broken concept otherwise.  And fiddling with it tends to be quite
> fragile...
> for example see g:7d6f7e92c3b737736a2d8ff97a71af9f230c2f88
> for the "fun" you can have with "stale" values in input_location ...

Yeah.  Another example, from the analyzer, is
g:2fbea4190e76a59c4880727cf84706fe083c00ae (PR 93349)


> IMHO users should have their own "copy", for example the gimplifier
> instead of mucking with and using input_location could use a
> similar state in its gimplify_ctx.

Some ideas (not necessarily good ones):

(a) the diagnostic_context could have an ice_location field, and use
that in internal_error (and maybe an RAII class for setting/clearing
it).

(b) move input_location to diagnostic_context, and add:
       #define input_location (global_dc->x_input_location)
or:
       #define input_location (global_dc->x_default_location)
which add an indirection everywhere.  I don't love these ideas, in that
we already overuse the preprocessor IMHO.

Trevor: BTW, if you're looking for global state to eliminate, it might
be nice to move the globals in input.c for caching source lines
(fcache_tab etc) into a new source_cache class, and have the
diagnostic_context own it via a new "source_cache *" field.

Dave


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 15:40         ` David Malcolm
@ 2021-07-01 16:04           ` David Malcolm
  2021-07-01 21:51             ` [committed] input.c: move file caching globals to a new file_cache class David Malcolm
  2021-07-02  0:44           ` [PATCH 2/4] allow poisoning input_location in ranges it should not be used Trevor Saunders
  1 sibling, 1 reply; 25+ messages in thread
From: David Malcolm @ 2021-07-01 16:04 UTC (permalink / raw)
  To: Richard Biener, Trevor Saunders; +Cc: GCC Patches

On Thu, 2021-07-01 at 11:40 -0400, David Malcolm wrote:
> On Thu, 2021-07-01 at 14:53 +0200, Richard Biener wrote:
> > On Thu, Jul 1, 2021 at 12:16 PM Trevor Saunders <
> > tbsaunde@tbsaunde.org> wrote:
> > > 
> > > On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> > > > On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > > > > This makes it possible to assert if input_location is used
> > > > > during the
> > > > > lifetime
> > > > > of a scope.  This will allow us to find places that currently
> > > > > use it
> > > > > within a
> > > > > function and its callees, or prevent adding uses within the
> > > > > lifetime
> > > > > of a
> > > > > function after all existing uses are removed.
> > > > > 
> > > > > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > > > > 
> > > > > Trev
> > > > 
> > > > [...snip...]
> > > > 
> > > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > > > index d58586f2526..3f68d1d79eb 100644
> > > > > --- a/gcc/diagnostic.c
> > > > > +++ b/gcc/diagnostic.c
> > > > > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid,
> > > > > ...)
> > > > >    auto_diagnostic_group d;
> > > > >    va_list ap;
> > > > >    va_start (ap, gmsgid);
> > > > > -  rich_location richloc (line_table, input_location);
> > > > > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> > > > >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> > > > >    va_end (ap);
> > > > > 
> > > > 
> > > > I actually make use of this in the analyzer: the analyzer sets
> > > > input_location to stmt->location when analyzing a given stmt -
> > > > that
> > > > way, if the analyzer ICEs, the ICE is shown at the code
> > > > construct
> > > > that
> > > > crashed the analyzer.
> > > > 
> > > > This behavior is useful to me, and would be lost with the
> > > > proposed
> > > > patch.
> > > 
> > > I made this change because otherwise if the compiler ICE's while
> > > access
> > > to input_location is blocked we end up infinitely recursing
> > > complaining
> > > we can't access it while trying to say where the last error was. 
> > > I
> > > was
> > > nervous about the change before, and now I agree we need
> > > something
> > > else.
> > > 
> > > > Is there a better way of doing what I'm doing?
> > > > 
> > > > Is the long-term goal of the patch kit to reduce our reliance
> > > > on
> > > > global
> > > > variables?  Are we ultimately still going to need a variable
> > > > for
> > > > "where
> > > > to show the ICE if gcc crashes"?  (perhaps stashing it in the
> > > > diagnostic_context???)
> > > 
> > > Yes, the goal is ultimately removal of global state, however I'm
> > > not
> > > really ure what the better approach to your problem is, after all
> > > even
> > > moving it to the diagnostic context is sort of a global state,
> > > and
> > > sort
> > > of dupplicates input_location.  That said it is somewhat more
> > > constrained, so if it removes usage of input_location perhaps its
> > > worthwhile?
> > 
> > Reduction of global state is of course good - but in particular
> > input_location
> > should be something only used during parsing because it's a quite
> > broken concept otherwise.  And fiddling with it tends to be quite
> > fragile...
> > for example see g:7d6f7e92c3b737736a2d8ff97a71af9f230c2f88
> > for the "fun" you can have with "stale" values in input_location
> > ...
> 
> Yeah.  Another example, from the analyzer, is
> g:2fbea4190e76a59c4880727cf84706fe083c00ae (PR 93349)
> 
> 
> > IMHO users should have their own "copy", for example the gimplifier
> > instead of mucking with and using input_location could use a
> > similar state in its gimplify_ctx.
> 
> Some ideas (not necessarily good ones):
> 
> (a) the diagnostic_context could have an ice_location field, and use
> that in internal_error (and maybe an RAII class for setting/clearing
> it).
> 
> (b) move input_location to diagnostic_context, and add:
>        #define input_location (global_dc->x_input_location)
> or:
>        #define input_location (global_dc->x_default_location)
> which add an indirection everywhere.  I don't love these ideas, in
> that
> we already overuse the preprocessor IMHO.
> 
> Trevor: BTW, if you're looking for global state to eliminate, it
> might
> be nice to move the globals in input.c for caching source lines
> (fcache_tab etc) into a new source_cache class, and have the
> diagnostic_context own it via a new "source_cache *" field.

Actually, I just found an old working copy on my drive that does most
of this; I'll try cleaning it up for gcc 12 and see if I can get it to
bootstrap.

Dave


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [committed] input.c: move file caching globals to a new file_cache class
  2021-07-01 16:04           ` David Malcolm
@ 2021-07-01 21:51             ` David Malcolm
  2021-07-11 16:58               ` Lewis Hyatt
  0 siblings, 1 reply; 25+ messages in thread
From: David Malcolm @ 2021-07-01 21:51 UTC (permalink / raw)
  To: gcc-patches

This moves some global state from input.c to a new file_cache class,
of which an instance is owned by global_dc.  Various state is also
made private.

No functional change intended.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as b544c348e13ad33d55f0d954370ab1fb0f2bf683.

gcc/ChangeLog:
	* diagnostic.h (diagnostic_context::m_file_cache): New field.
	* input.c (class fcache): Rename to...
	(class file_cache_slot): ...this, making most members private and
	prefixing fields with "m_".
	(file_cache_slot::get_file_path): New accessor.
	(file_cache_slot::get_use_count): New accessor.
	(file_cache_slot::missing_trailing_newline_p): New accessor.
	(file_cache_slot::inc_use_count): New.
	(fcache_buffer_size): Move to...
	(file_cache_slot::buffer_size): ...here.
	(fcache_line_record_size): Move to...
	(file_cache_slot::line_record_size): ...here.
	(fcache_tab): Delete, in favor of global_dc->m_file_cache.
	(fcache_tab_size): Move to file_cache::num_file_slots.
	(diagnostic_file_cache_init): Update for move of fcache_tab
	to global_dc->m_file_cache.
	(diagnostic_file_cache_fini): Likewise.
	(lookup_file_in_cache_tab): Convert to...
	(file_cache::lookup_file): ...this.
	(diagnostics_file_cache_forcibly_evict_file): Update for move of
	fcache_tab to global_dc->m_file_cache, moving most of
	implementation to...
	(file_cache::forcibly_evict_file): ...this new function and...
	(file_cache_slot::evict): ...this new function.
	(evicted_cache_tab_entry): Convert to...
	(file_cache::evicted_cache_tab_entry): ...this.
	(add_file_to_cache_tab): Convert to...
	(file_cache::add_file): ...this, moving bulk of implementation
	to...
	(file_cache_slot::create): ..this new function.
	(file_cache::file_cache): New.
	(file_cache::~file_cache): New.
	(lookup_or_add_file_to_cache_tab): Convert to...
	(file_cache::lookup_or_add_file): ..this new function.
	(fcache::fcache): Rename to...
	(file_cache_slot::file_cache_slot): ...this, adding "m_" prefixes
	to fields.
	(fcache::~fcache): Rename to...
	(file_cache_slot::~file_cache_slot): ...this, adding "m_" prefixes
	to fields.
	(needs_read): Convert to...
	(file_cache_slot::needs_read_p): ...this.
	(needs_grow): Convert to...
	(file_cache_slot::needs_grow_p): ...this.
	(maybe_grow): Convert to...
	(file_cache_slot::maybe_grow): ...this.
	(read_data): Convert to...
	(file_cache_slot::read_data): ...this.
	(maybe_read_data): Convert to...
	(file_cache_slot::maybe_read_data): ...this.
	(get_next_line): Convert to...
	(file_cache_slot::get_next_line): ...this.
	(goto_next_line): Convert to...
	(file_cache_slot::goto_next_line): ...this.
	(read_line_num): Convert to...
	(file_cache_slot::read_line_num): ...this.
	(location_get_source_line): Update for moving of globals to
	global_dc->m_file_cache.
	(location_missing_trailing_newline): Likewise.
	* input.h (class file_cache_slot): New forward decl.
	(class file_cache): New.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic.h |   3 +
 gcc/input.c      | 459 +++++++++++++++++++++++++++--------------------
 gcc/input.h      |  33 ++++
 3 files changed, 301 insertions(+), 194 deletions(-)

diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 1b9d6b1f64d..086bc4f903f 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -136,6 +136,9 @@ struct diagnostic_context
   /* Where most of the diagnostic formatting work is done.  */
   pretty_printer *printer;
 
+  /* Cache of source code.  */
+  file_cache *m_file_cache;
+
   /* The number of times we have issued diagnostics.  */
   int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
 
diff --git a/gcc/input.c b/gcc/input.c
index 9e39e7df83c..de20d983d2c 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -32,9 +32,29 @@ along with GCC; see the file COPYING3.  If not see
 
 /* This is a cache used by get_next_line to store the content of a
    file to be searched for file lines.  */
-class fcache
+class file_cache_slot
 {
 public:
+  file_cache_slot ();
+  ~file_cache_slot ();
+
+  bool read_line_num (size_t line_num,
+		      char ** line, ssize_t *line_len);
+
+  /* Accessors.  */
+  const char *get_file_path () const { return m_file_path; }
+  unsigned get_use_count () const { return m_use_count; }
+  bool missing_trailing_newline_p () const
+  {
+    return m_missing_trailing_newline;
+  }
+
+  void inc_use_count () { m_use_count++; }
+
+  void create (const char *file_path, FILE *fp, unsigned highest_use_count);
+  void evict ();
+
+ private:
   /* These are information used to store a line boundary.  */
   class line_info
   {
@@ -61,36 +81,48 @@ public:
     {}
   };
 
+  bool needs_read_p () const;
+  bool needs_grow_p () const;
+  void maybe_grow ();
+  bool read_data ();
+  bool maybe_read_data ();
+  bool get_next_line (char **line, ssize_t *line_len);
+  bool read_next_line (char ** line, ssize_t *line_len);
+  bool goto_next_line ();
+
+  static const size_t buffer_size = 4 * 1024;
+  static const size_t line_record_size = 100;
+
   /* The number of time this file has been accessed.  This is used
      to designate which file cache to evict from the cache
      array.  */
-  unsigned use_count;
+  unsigned m_use_count;
 
   /* The file_path is the key for identifying a particular file in
      the cache.
      For libcpp-using code, the underlying buffer for this field is
      owned by the corresponding _cpp_file within the cpp_reader.  */
-  const char *file_path;
+  const char *m_file_path;
 
-  FILE *fp;
+  FILE *m_fp;
 
   /* This points to the content of the file that we've read so
      far.  */
-  char *data;
+  char *m_data;
 
   /*  The size of the DATA array above.*/
-  size_t size;
+  size_t m_size;
 
   /* The number of bytes read from the underlying file so far.  This
      must be less (or equal) than SIZE above.  */
-  size_t nb_read;
+  size_t m_nb_read;
 
   /* The index of the beginning of the current line.  */
-  size_t line_start_idx;
+  size_t m_line_start_idx;
 
   /* The number of the previous line read.  This starts at 1.  Zero
      means we've read no line so far.  */
-  size_t line_num;
+  size_t m_line_num;
 
   /* This is the total number of lines of the current file.  At the
      moment, we try to get this information from the line map
@@ -100,24 +132,21 @@ public:
      the number of lines before compilation really starts.  For e.g,
      the C front-end, it can happen that we start emitting diagnostics
      before the line map has seen the end of the file.  */
-  size_t total_lines;
+  size_t m_total_lines;
 
   /* Could this file be missing a trailing newline on its final line?
      Initially true (to cope with empty files), set to true/false
      as each line is read.  */
-  bool missing_trailing_newline;
+  bool m_missing_trailing_newline;
 
   /* This is a record of the beginning and end of the lines we've seen
      while reading the file.  This is useful to avoid walking the data
      from the beginning when we are asked to read a line that is
      before LINE_START_IDX above.  Note that the maximum size of this
-     record is fcache_line_record_size, so that the memory consumption
+     record is line_record_size, so that the memory consumption
      doesn't explode.  We thus scale total_lines down to
-     fcache_line_record_size.  */
-  vec<line_info, va_heap> line_record;
-
-  fcache ();
-  ~fcache ();
+     line_record_size.  */
+  vec<line_info, va_heap> m_line_record;
 };
 
 /* Current position in real source file.  */
@@ -133,11 +162,6 @@ class line_maps *line_table;
 
 class line_maps *saved_line_table;
 
-static fcache *fcache_tab;
-static const size_t fcache_tab_size = 16;
-static const size_t fcache_buffer_size = 4 * 1024;
-static const size_t fcache_line_record_size = 100;
-
 /* Expand the source location LOC into a human readable location.  If
    LOC resolves to a builtin location, the file name of the readable
    location is set to the string "<built-in>". If EXPANSION_POINT_P is
@@ -233,8 +257,9 @@ expand_location_1 (location_t loc,
 static void
 diagnostic_file_cache_init (void)
 {
-  if (fcache_tab == NULL)
-    fcache_tab = new fcache[fcache_tab_size];
+  gcc_assert (global_dc);
+  if (global_dc->m_file_cache == NULL)
+    global_dc->m_file_cache = new file_cache ();
 }
 
 /* Free the resources used by the set of cache used for files accessed
@@ -243,10 +268,10 @@ diagnostic_file_cache_init (void)
 void
 diagnostic_file_cache_fini (void)
 {
-  if (fcache_tab)
+  if (global_dc->m_file_cache)
     {
-      delete [] (fcache_tab);
-      fcache_tab = NULL;
+      delete global_dc->m_file_cache;
+      global_dc->m_file_cache = NULL;
     }
 }
 
@@ -273,28 +298,25 @@ total_lines_num (const char *file_path)
    caret diagnostic.  Return the found cached file, or NULL if no
    cached file was found.  */
 
-static fcache*
-lookup_file_in_cache_tab (const char *file_path)
+file_cache_slot *
+file_cache::lookup_file (const char *file_path)
 {
-  if (file_path == NULL)
-    return NULL;
-
-  diagnostic_file_cache_init ();
+  gcc_assert (file_path);
 
   /* This will contain the found cached file.  */
-  fcache *r = NULL;
-  for (unsigned i = 0; i < fcache_tab_size; ++i)
+  file_cache_slot *r = NULL;
+  for (unsigned i = 0; i < num_file_slots; ++i)
     {
-      fcache *c = &fcache_tab[i];
-      if (c->file_path && !strcmp (c->file_path, file_path))
+      file_cache_slot *c = &m_file_slots[i];
+      if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
 	{
-	  ++c->use_count;
+	  c->inc_use_count ();
 	  r = c;
 	}
     }
 
   if (r)
-    ++r->use_count;
+    r->inc_use_count ();
 
   return r;
 }
@@ -308,22 +330,39 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path)
 {
   gcc_assert (file_path);
 
-  fcache *r = lookup_file_in_cache_tab (file_path);
+  if (!global_dc->m_file_cache)
+    return;
+
+  global_dc->m_file_cache->forcibly_evict_file (file_path);
+}
+
+void
+file_cache::forcibly_evict_file (const char *file_path)
+{
+  gcc_assert (file_path);
+
+  file_cache_slot *r = lookup_file (file_path);
   if (!r)
     /* Not found.  */
     return;
 
-  r->file_path = NULL;
-  if (r->fp)
-    fclose (r->fp);
-  r->fp = NULL;
-  r->nb_read = 0;
-  r->line_start_idx = 0;
-  r->line_num = 0;
-  r->line_record.truncate (0);
-  r->use_count = 0;
-  r->total_lines = 0;
-  r->missing_trailing_newline = true;
+  r->evict ();
+}
+
+void
+file_cache_slot::evict ()
+{
+  m_file_path = NULL;
+  if (m_fp)
+    fclose (m_fp);
+  m_fp = NULL;
+  m_nb_read = 0;
+  m_line_start_idx = 0;
+  m_line_num = 0;
+  m_line_record.truncate (0);
+  m_use_count = 0;
+  m_total_lines = 0;
+  m_missing_trailing_newline = true;
 }
 
 /* Return the file cache that has been less used, recently, or the
@@ -331,26 +370,26 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path)
    *HIGHEST_USE_COUNT is set to the highest use count of the entries
    in the cache table.  */
 
-static fcache*
-evicted_cache_tab_entry (unsigned *highest_use_count)
+file_cache_slot*
+file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
 {
   diagnostic_file_cache_init ();
 
-  fcache *to_evict = &fcache_tab[0];
-  unsigned huc = to_evict->use_count;
-  for (unsigned i = 1; i < fcache_tab_size; ++i)
+  file_cache_slot *to_evict = &m_file_slots[0];
+  unsigned huc = to_evict->get_use_count ();
+  for (unsigned i = 1; i < num_file_slots; ++i)
     {
-      fcache *c = &fcache_tab[i];
-      bool c_is_empty = (c->file_path == NULL);
+      file_cache_slot *c = &m_file_slots[i];
+      bool c_is_empty = (c->get_file_path () == NULL);
 
-      if (c->use_count < to_evict->use_count
-	  || (to_evict->file_path && c_is_empty))
+      if (c->get_use_count () < to_evict->get_use_count ()
+	  || (to_evict->get_file_path () && c_is_empty))
 	/* We evict C because it's either an entry with a lower use
 	   count or one that is empty.  */
 	to_evict = c;
 
-      if (huc < c->use_count)
-	huc = c->use_count;
+      if (huc < c->get_use_count ())
+	huc = c->get_use_count ();
 
       if (c_is_empty)
 	/* We've reached the end of the cache; subsequent elements are
@@ -368,10 +407,10 @@ evicted_cache_tab_entry (unsigned *highest_use_count)
    accessed by caret diagnostic.  This cache is added to an array of
    cache and can be retrieved by lookup_file_in_cache_tab.  This
    function returns the created cache.  Note that only the last
-   fcache_tab_size files are cached.  */
+   num_file_slots files are cached.  */
 
-static fcache*
-add_file_to_cache_tab (const char *file_path)
+file_cache_slot*
+file_cache::add_file (const char *file_path)
 {
 
   FILE *fp = fopen (file_path, "r");
@@ -379,22 +418,45 @@ add_file_to_cache_tab (const char *file_path)
     return NULL;
 
   unsigned highest_use_count = 0;
-  fcache *r = evicted_cache_tab_entry (&highest_use_count);
-  r->file_path = file_path;
-  if (r->fp)
-    fclose (r->fp);
-  r->fp = fp;
-  r->nb_read = 0;
-  r->line_start_idx = 0;
-  r->line_num = 0;
-  r->line_record.truncate (0);
+  file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count);
+  r->create (file_path, fp, highest_use_count);
+  return r;
+}
+
+/* Populate this slot for use on FILE_PATH and FP, dropping any
+   existing cached content within it.  */
+
+void
+file_cache_slot::create (const char *file_path, FILE *fp,
+			 unsigned highest_use_count)
+{
+  m_file_path = file_path;
+  if (m_fp)
+    fclose (m_fp);
+  m_fp = fp;
+  m_nb_read = 0;
+  m_line_start_idx = 0;
+  m_line_num = 0;
+  m_line_record.truncate (0);
   /* Ensure that this cache entry doesn't get evicted next time
      add_file_to_cache_tab is called.  */
-  r->use_count = ++highest_use_count;
-  r->total_lines = total_lines_num (file_path);
-  r->missing_trailing_newline = true;
+  m_use_count = ++highest_use_count;
+  m_total_lines = total_lines_num (file_path);
+  m_missing_trailing_newline = true;
+}
 
-  return r;
+/* file_cache's ctor.  */
+
+file_cache::file_cache ()
+: m_file_slots (new file_cache_slot[num_file_slots])
+{
+}
+
+/* file_cache's dtor.  */
+
+file_cache::~file_cache ()
+{
+  delete[] m_file_slots;
 }
 
 /* Lookup the cache used for the content of a given file accessed by
@@ -402,41 +464,41 @@ add_file_to_cache_tab (const char *file_path)
    for this file, add it to the array of cached file and return
    it.  */
 
-static fcache*
-lookup_or_add_file_to_cache_tab (const char *file_path)
+file_cache_slot*
+file_cache::lookup_or_add_file (const char *file_path)
 {
-  fcache *r = lookup_file_in_cache_tab (file_path);
+  file_cache_slot *r = lookup_file (file_path);
   if (r == NULL)
-    r = add_file_to_cache_tab (file_path);
+    r = add_file (file_path);
   return r;
 }
 
 /* Default constructor for a cache of file used by caret
    diagnostic.  */
 
-fcache::fcache ()
-: use_count (0), file_path (NULL), fp (NULL), data (0),
-  size (0), nb_read (0), line_start_idx (0), line_num (0),
-  total_lines (0), missing_trailing_newline (true)
+file_cache_slot::file_cache_slot ()
+: m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0),
+  m_size (0), m_nb_read (0), m_line_start_idx (0), m_line_num (0),
+  m_total_lines (0), m_missing_trailing_newline (true)
 {
-  line_record.create (0);
+  m_line_record.create (0);
 }
 
 /* Destructor for a cache of file used by caret diagnostic.  */
 
-fcache::~fcache ()
+file_cache_slot::~file_cache_slot ()
 {
-  if (fp)
+  if (m_fp)
     {
-      fclose (fp);
-      fp = NULL;
+      fclose (m_fp);
+      m_fp = NULL;
     }
-  if (data)
+  if (m_data)
     {
-      XDELETEVEC (data);
-      data = 0;
+      XDELETEVEC (m_data);
+      m_data = 0;
     }
-  line_record.release ();
+  m_line_record.release ();
 }
 
 /* Returns TRUE iff the cache would need to be filled with data coming
@@ -444,55 +506,55 @@ fcache::~fcache ()
    current line is empty.  Note that if the cache is full, it would
    need to be extended and filled again.  */
 
-static bool
-needs_read (fcache *c)
+bool
+file_cache_slot::needs_read_p () const
 {
-  return (c->nb_read == 0
-	  || c->nb_read == c->size
-	  || (c->line_start_idx >= c->nb_read - 1));
+  return (m_nb_read == 0
+	  || m_nb_read == m_size
+	  || (m_line_start_idx >= m_nb_read - 1));
 }
 
 /*  Return TRUE iff the cache is full and thus needs to be
     extended.  */
 
-static bool
-needs_grow (fcache *c)
+bool
+file_cache_slot::needs_grow_p () const
 {
-  return c->nb_read == c->size;
+  return m_nb_read == m_size;
 }
 
 /* Grow the cache if it needs to be extended.  */
 
-static void
-maybe_grow (fcache *c)
+void
+file_cache_slot::maybe_grow ()
 {
-  if (!needs_grow (c))
+  if (!needs_grow_p ())
     return;
 
-  size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
-  c->data = XRESIZEVEC (char, c->data, size);
-  c->size = size;
+  size_t size = m_size == 0 ? buffer_size : m_size * 2;
+  m_data = XRESIZEVEC (char, m_data, size);
+  m_size = size;
 }
 
 /*  Read more data into the cache.  Extends the cache if need be.
     Returns TRUE iff new data could be read.  */
 
-static bool
-read_data (fcache *c)
+bool
+file_cache_slot::read_data ()
 {
-  if (feof (c->fp) || ferror (c->fp))
+  if (feof (m_fp) || ferror (m_fp))
     return false;
 
-  maybe_grow (c);
+  maybe_grow ();
 
-  char * from = c->data + c->nb_read;
-  size_t to_read = c->size - c->nb_read;
-  size_t nb_read = fread (from, 1, to_read, c->fp);
+  char * from = m_data + m_nb_read;
+  size_t to_read = m_size - m_nb_read;
+  size_t nb_read = fread (from, 1, to_read, m_fp);
 
-  if (ferror (c->fp))
+  if (ferror (m_fp))
     return false;
 
-  c->nb_read += nb_read;
+  m_nb_read += nb_read;
   return !!nb_read;
 }
 
@@ -500,12 +562,12 @@ read_data (fcache *c)
    coming from the file FP.  Return TRUE iff the cache was filled with
    mode data.  */
 
-static bool
-maybe_read_data (fcache *c)
+bool
+file_cache_slot::maybe_read_data ()
 {
-  if (!needs_read (c))
+  if (!needs_read_p ())
     return false;
-  return read_data (c);
+  return read_data ();
 }
 
 /* Read a new line from file FP, using C as a cache for the data
@@ -518,18 +580,18 @@ maybe_read_data (fcache *c)
    otherwise.  Note that subsequent calls to get_next_line might
    make the content of *LINE invalid.  */
 
-static bool
-get_next_line (fcache *c, char **line, ssize_t *line_len)
+bool
+file_cache_slot::get_next_line (char **line, ssize_t *line_len)
 {
   /* Fill the cache with data to process.  */
-  maybe_read_data (c);
+  maybe_read_data ();
 
-  size_t remaining_size = c->nb_read - c->line_start_idx;
+  size_t remaining_size = m_nb_read - m_line_start_idx;
   if (remaining_size == 0)
     /* There is no more data to process.  */
     return false;
 
-  char *line_start = c->data + c->line_start_idx;
+  char *line_start = m_data + m_line_start_idx;
 
   char *next_line_start = NULL;
   size_t len = 0;
@@ -539,10 +601,10 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
       /* We haven't found the end-of-line delimiter in the cache.
 	 Fill the cache with more data from the file and look for the
 	 '\n'.  */
-      while (maybe_read_data (c))
+      while (maybe_read_data ())
 	{
-	  line_start = c->data + c->line_start_idx;
-	  remaining_size = c->nb_read - c->line_start_idx;
+	  line_start = m_data + m_line_start_idx;
+	  remaining_size = m_nb_read - m_line_start_idx;
 	  line_end = (char *) memchr (line_start, '\n', remaining_size);
 	  if (line_end != NULL)
 	    {
@@ -558,19 +620,19 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
 	     of when the line ends up with a '\n' and line_end points to
 	     that terminal '\n'.  That consistency is useful below in
 	     the len calculation.  */
-	  line_end = c->data + c->nb_read ;
-	  c->missing_trailing_newline = true;
+	  line_end = m_data + m_nb_read ;
+	  m_missing_trailing_newline = true;
 	}
       else
-	c->missing_trailing_newline = false;
+	m_missing_trailing_newline = false;
     }
   else
     {
       next_line_start = line_end + 1;
-      c->missing_trailing_newline = false;
+      m_missing_trailing_newline = false;
     }
 
-  if (ferror (c->fp))
+  if (ferror (m_fp))
     return false;
 
   /* At this point, we've found the end of the of line.  It either
@@ -580,54 +642,56 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
 
   len = line_end - line_start;
 
-  if (c->line_start_idx < c->nb_read)
+  if (m_line_start_idx < m_nb_read)
     *line = line_start;
 
-  ++c->line_num;
+  ++m_line_num;
 
   /* Before we update our line record, make sure the hint about the
      total number of lines of the file is correct.  If it's not, then
      we give up recording line boundaries from now on.  */
   bool update_line_record = true;
-  if (c->line_num > c->total_lines)
+  if (m_line_num > m_total_lines)
     update_line_record = false;
 
     /* Now update our line record so that re-reading lines from the
-     before c->line_start_idx is faster.  */
+     before m_line_start_idx is faster.  */
   if (update_line_record
-      && c->line_record.length () < fcache_line_record_size)
+      && m_line_record.length () < line_record_size)
     {
       /* If the file lines fits in the line record, we just record all
 	 its lines ...*/
-      if (c->total_lines <= fcache_line_record_size
-	  && c->line_num > c->line_record.length ())
-	c->line_record.safe_push (fcache::line_info (c->line_num,
-						 c->line_start_idx,
-						 line_end - c->data));
-      else if (c->total_lines > fcache_line_record_size)
+      if (m_total_lines <= line_record_size
+	  && m_line_num > m_line_record.length ())
+	m_line_record.safe_push
+	  (file_cache_slot::line_info (m_line_num,
+				       m_line_start_idx,
+				       line_end - m_data));
+      else if (m_total_lines > line_record_size)
 	{
 	  /* ... otherwise, we just scale total_lines down to
-	     (fcache_line_record_size lines.  */
-	  size_t n = (c->line_num * fcache_line_record_size) / c->total_lines;
-	  if (c->line_record.length () == 0
-	      || n >= c->line_record.length ())
-	    c->line_record.safe_push (fcache::line_info (c->line_num,
-						     c->line_start_idx,
-						     line_end - c->data));
+	     (line_record_size lines.  */
+	  size_t n = (m_line_num * line_record_size) / m_total_lines;
+	  if (m_line_record.length () == 0
+	      || n >= m_line_record.length ())
+	    m_line_record.safe_push
+	      (file_cache_slot::line_info (m_line_num,
+					   m_line_start_idx,
+					   line_end - m_data));
 	}
     }
 
-  /* Update c->line_start_idx so that it points to the next line to be
+  /* Update m_line_start_idx so that it points to the next line to be
      read.  */
   if (next_line_start)
-    c->line_start_idx = next_line_start - c->data;
+    m_line_start_idx = next_line_start - m_data;
   else
     /* We didn't find any terminal '\n'.  Let's consider that the end
        of line is the end of the data in the cache.  The next
        invocation of get_next_line will either read more data from the
        underlying file or return false early because we've reached the
        end of the file.  */
-    c->line_start_idx = c->nb_read;
+    m_line_start_idx = m_nb_read;
 
   *line_len = len;
 
@@ -640,13 +704,13 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
    copying from the cache involved.  Return TRUE upon successful
    completion.  */
 
-static bool
-goto_next_line (fcache *cache)
+bool
+file_cache_slot::goto_next_line ()
 {
   char *l;
   ssize_t len;
 
-  return get_next_line (cache, &l, &len);
+  return get_next_line (&l, &len);
 }
 
 /* Read an arbitrary line number LINE_NUM from the file cached in C.
@@ -656,54 +720,54 @@ goto_next_line (fcache *cache)
    *LINE is only valid until the next call of read_line_num.
    This function returns bool if a line was read.  */
 
-static bool
-read_line_num (fcache *c, size_t line_num,
-	       char **line, ssize_t *line_len)
+bool
+file_cache_slot::read_line_num (size_t line_num,
+		       char ** line, ssize_t *line_len)
 {
   gcc_assert (line_num > 0);
 
-  if (line_num <= c->line_num)
+  if (line_num <= m_line_num)
     {
-      /* We've been asked to read lines that are before c->line_num.
+      /* We've been asked to read lines that are before m_line_num.
 	 So lets use our line record (if it's not empty) to try to
 	 avoid re-reading the file from the beginning again.  */
 
-      if (c->line_record.is_empty ())
+      if (m_line_record.is_empty ())
 	{
-	  c->line_start_idx = 0;
-	  c->line_num = 0;
+	  m_line_start_idx = 0;
+	  m_line_num = 0;
 	}
       else
 	{
-	  fcache::line_info *i = NULL;
-	  if (c->total_lines <= fcache_line_record_size)
+	  file_cache_slot::line_info *i = NULL;
+	  if (m_total_lines <= line_record_size)
 	    {
 	      /* In languages where the input file is not totally
-		 preprocessed up front, the c->total_lines hint
+		 preprocessed up front, the m_total_lines hint
 		 can be smaller than the number of lines of the
 		 file.  In that case, only the first
-		 c->total_lines have been recorded.
+		 m_total_lines have been recorded.
 
-		 Otherwise, the first c->total_lines we've read have
+		 Otherwise, the first m_total_lines we've read have
 		 their start/end recorded here.  */
-	      i = (line_num <= c->total_lines)
-		? &c->line_record[line_num - 1]
-		: &c->line_record[c->total_lines - 1];
+	      i = (line_num <= m_total_lines)
+		? &m_line_record[line_num - 1]
+		: &m_line_record[m_total_lines - 1];
 	      gcc_assert (i->line_num <= line_num);
 	    }
 	  else
 	    {
 	      /*  So the file had more lines than our line record
 		  size.  Thus the number of lines we've recorded has
-		  been scaled down to fcache_line_reacord_size.  Let's
+		  been scaled down to line_record_size.  Let's
 		  pick the start/end of the recorded line that is
 		  closest to line_num.  */
-	      size_t n = (line_num <= c->total_lines)
-		? line_num * fcache_line_record_size / c->total_lines
-		: c ->line_record.length () - 1;
-	      if (n < c->line_record.length ())
+	      size_t n = (line_num <= m_total_lines)
+		? line_num * line_record_size / m_total_lines
+		: m_line_record.length () - 1;
+	      if (n < m_line_record.length ())
 		{
-		  i = &c->line_record[n];
+		  i = &m_line_record[n];
 		  gcc_assert (i->line_num <= line_num);
 		}
 	    }
@@ -711,33 +775,33 @@ read_line_num (fcache *c, size_t line_num,
 	  if (i && i->line_num == line_num)
 	    {
 	      /* We have the start/end of the line.  */
-	      *line = c->data + i->start_pos;
+	      *line = m_data + i->start_pos;
 	      *line_len = i->end_pos - i->start_pos;
 	      return true;
 	    }
 
 	  if (i)
 	    {
-	      c->line_start_idx = i->start_pos;
-	      c->line_num = i->line_num - 1;
+	      m_line_start_idx = i->start_pos;
+	      m_line_num = i->line_num - 1;
 	    }
 	  else
 	    {
-	      c->line_start_idx = 0;
-	      c->line_num = 0;
+	      m_line_start_idx = 0;
+	      m_line_num = 0;
 	    }
 	}
     }
 
-  /*  Let's walk from line c->line_num up to line_num - 1, without
+  /*  Let's walk from line m_line_num up to line_num - 1, without
       copying any line.  */
-  while (c->line_num < line_num - 1)
-    if (!goto_next_line (c))
+  while (m_line_num < line_num - 1)
+    if (!goto_next_line ())
       return false;
 
   /* The line we want is the next one.  Let's read and copy it back to
      the caller.  */
-  return get_next_line (c, line, line_len);
+  return get_next_line (line, line_len);
 }
 
 /* Return the physical source line that corresponds to FILE_PATH/LINE.
@@ -756,11 +820,16 @@ location_get_source_line (const char *file_path, int line)
   if (line == 0)
     return char_span (NULL, 0);
 
-  fcache *c = lookup_or_add_file_to_cache_tab (file_path);
+  if (file_path == NULL)
+    return char_span (NULL, 0);
+
+  diagnostic_file_cache_init ();
+
+  file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
   if (c == NULL)
     return char_span (NULL, 0);
 
-  bool read = read_line_num (c, line, &buffer, &len);
+  bool read = c->read_line_num (line, &buffer, &len);
   if (!read)
     return char_span (NULL, 0);
 
@@ -774,11 +843,13 @@ location_get_source_line (const char *file_path, int line)
 bool
 location_missing_trailing_newline (const char *file_path)
 {
-  fcache *c = lookup_or_add_file_to_cache_tab (file_path);
+  diagnostic_file_cache_init ();
+
+  file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
   if (c == NULL)
     return false;
 
-  return c->missing_trailing_newline;
+  return c->missing_trailing_newline_p ();
 }
 
 /* Test if the location originates from the spelling location of a
diff --git a/gcc/input.h b/gcc/input.h
index f1ef5d76cfd..bbcec84c521 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -88,6 +88,39 @@ class char_span
 extern char_span location_get_source_line (const char *file_path, int line);
 
 extern bool location_missing_trailing_newline (const char *file_path);
+
+/* Forward decl of slot within file_cache, so that the definition doesn't
+   need to be in this header.  */
+class file_cache_slot;
+
+/* A cache of source files for use when emitting diagnostics
+   (and in a few places in the C/C++ frontends).
+
+   Results are only valid until the next call to the cache, as
+   slots can be evicted.
+
+   Filenames are stored by pointer, and so must outlive the cache
+   instance.  */
+
+class file_cache
+{
+ public:
+  file_cache ();
+  ~file_cache ();
+
+  file_cache_slot *lookup_or_add_file (const char *file_path);
+  void forcibly_evict_file (const char *file_path);
+
+ private:
+  file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
+  file_cache_slot *add_file (const char *file_path);
+  file_cache_slot *lookup_file (const char *file_path);
+
+ private:
+  static const size_t num_file_slots = 16;
+  file_cache_slot *m_file_slots;
+};
+
 extern expanded_location
 expand_location_to_spelling_point (location_t,
 				   enum location_aspect aspect
-- 
2.26.3


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 15:40         ` David Malcolm
  2021-07-01 16:04           ` David Malcolm
@ 2021-07-02  0:44           ` Trevor Saunders
  1 sibling, 0 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-07-02  0:44 UTC (permalink / raw)
  To: David Malcolm; +Cc: Richard Biener, GCC Patches

On Thu, Jul 01, 2021 at 11:40:55AM -0400, David Malcolm via Gcc-patches wrote:
> On Thu, 2021-07-01 at 14:53 +0200, Richard Biener wrote:
> > On Thu, Jul 1, 2021 at 12:16 PM Trevor Saunders <
> > tbsaunde@tbsaunde.org> wrote:
> > > 
> > > On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> > > > On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > > > > This makes it possible to assert if input_location is used
> > > > > during the
> > > > > lifetime
> > > > > of a scope.  This will allow us to find places that currently
> > > > > use it
> > > > > within a
> > > > > function and its callees, or prevent adding uses within the
> > > > > lifetime
> > > > > of a
> > > > > function after all existing uses are removed.
> > > > > 
> > > > > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > > > > 
> > > > > Trev
> > > > 
> > > > [...snip...]
> > > > 
> > > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > > > index d58586f2526..3f68d1d79eb 100644
> > > > > --- a/gcc/diagnostic.c
> > > > > +++ b/gcc/diagnostic.c
> > > > > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> > > > >    auto_diagnostic_group d;
> > > > >    va_list ap;
> > > > >    va_start (ap, gmsgid);
> > > > > -  rich_location richloc (line_table, input_location);
> > > > > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> > > > >    diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> > > > >    va_end (ap);
> > > > > 
> > > > 
> > > > I actually make use of this in the analyzer: the analyzer sets
> > > > input_location to stmt->location when analyzing a given stmt -
> > > > that
> > > > way, if the analyzer ICEs, the ICE is shown at the code construct
> > > > that
> > > > crashed the analyzer.
> > > > 
> > > > This behavior is useful to me, and would be lost with the
> > > > proposed
> > > > patch.
> > > 
> > > I made this change because otherwise if the compiler ICE's while
> > > access
> > > to input_location is blocked we end up infinitely recursing
> > > complaining
> > > we can't access it while trying to say where the last error was.  I
> > > was
> > > nervous about the change before, and now I agree we need something
> > > else.
> > > 
> > > > Is there a better way of doing what I'm doing?
> > > > 
> > > > Is the long-term goal of the patch kit to reduce our reliance on
> > > > global
> > > > variables?  Are we ultimately still going to need a variable for
> > > > "where
> > > > to show the ICE if gcc crashes"?  (perhaps stashing it in the
> > > > diagnostic_context???)
> > > 
> > > Yes, the goal is ultimately removal of global state, however I'm
> > > not
> > > really ure what the better approach to your problem is, after all
> > > even
> > > moving it to the diagnostic context is sort of a global state, and
> > > sort
> > > of dupplicates input_location.  That said it is somewhat more
> > > constrained, so if it removes usage of input_location perhaps its
> > > worthwhile?
> > 
> > Reduction of global state is of course good - but in particular
> > input_location
> > should be something only used during parsing because it's a quite
> > broken concept otherwise.  And fiddling with it tends to be quite
> > fragile...
> > for example see g:7d6f7e92c3b737736a2d8ff97a71af9f230c2f88
> > for the "fun" you can have with "stale" values in input_location ...
> 
> Yeah.  Another example, from the analyzer, is
> g:2fbea4190e76a59c4880727cf84706fe083c00ae (PR 93349)

So, one rather useful this patch allows doing, even if you apply it
locally, is that you can block off access to input_location in the same
scope you currently save and restore it, and then once you've fixed up
all the asserts you find with a bootstrap and test cycle, you can be
somewhat confident nothing uses it and the save and restore dance can
go.  I may have a look at doing that with some of these.

> 
> > IMHO users should have their own "copy", for example the gimplifier
> > instead of mucking with and using input_location could use a
> > similar state in its gimplify_ctx.
> 
> Some ideas (not necessarily good ones):
> 
> (a) the diagnostic_context could have an ice_location field, and use
> that in internal_error (and maybe an RAII class for setting/clearing
> it).

If this is useful to people as it seems to be, this seems sensible, my
one concern is when exactly should ice_location be set? other than "it
should match input_location".  There's still the global state of the
diagnostic context, but at least its more understandable and isolated.
On the other hand it offers the opertunity to have a stack of
ice_locations, if you walk up the stack looking at all the RAII objects,
perhaps that would be useful, especially with things like template
instantiation?

> (b) move input_location to diagnostic_context, and add:
>        #define input_location (global_dc->x_input_location)
> or:
>        #define input_location (global_dc->x_default_location)
> which add an indirection everywhere.  I don't love these ideas, in that
> we already overuse the preprocessor IMHO.

There's that, also it doesn't seem to really reduce the complexity? it
just merges too globals into one block of memory?

Thanks

Trev

> 
> Trevor: BTW, if you're looking for global state to eliminate, it might
> be nice to move the globals in input.c for caching source lines
> (fcache_tab etc) into a new source_cache class, and have the
> diagnostic_context own it via a new "source_cache *" field.
> 
> Dave
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-01 10:16     ` Trevor Saunders
  2021-07-01 12:53       ` Richard Biener
@ 2021-07-02 15:46       ` Jason Merrill
  2021-07-02 23:23         ` Trevor Saunders
  1 sibling, 1 reply; 25+ messages in thread
From: Jason Merrill @ 2021-07-02 15:46 UTC (permalink / raw)
  To: Trevor Saunders, David Malcolm; +Cc: gcc-patches

On 7/1/21 6:16 AM, Trevor Saunders wrote:
> On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
>> On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
>>> This makes it possible to assert if input_location is used during the
>>> lifetime
>>> of a scope.  This will allow us to find places that currently use it
>>> within a
>>> function and its callees, or prevent adding uses within the lifetime
>>> of a
>>> function after all existing uses are removed.
>>>
>>> bootstrapped and regtested on x86_64-linux-gnu, ok?
>>>
>>> Trev
>>
>> [...snip...]
>>
>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
>>> index d58586f2526..3f68d1d79eb 100644
>>> --- a/gcc/diagnostic.c
>>> +++ b/gcc/diagnostic.c
>>> @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
>>>     auto_diagnostic_group d;
>>>     va_list ap;
>>>     va_start (ap, gmsgid);
>>> -  rich_location richloc (line_table, input_location);
>>> +  rich_location richloc (line_table, UNKNOWN_LOCATION);
>>>     diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
>>>     va_end (ap);
>>>   
>>
>> I actually make use of this in the analyzer: the analyzer sets
>> input_location to stmt->location when analyzing a given stmt - that
>> way, if the analyzer ICEs, the ICE is shown at the code construct that
>> crashed the analyzer.
>>
>> This behavior is useful to me, and would be lost with the proposed
>> patch.
> 
> I made this change because otherwise if the compiler ICE's while access
> to input_location is blocked we end up infinitely recursing complaining
> we can't access it while trying to say where the last error was.  I was
> nervous about the change before, and now I agree we need something
> else.

How about allowing a scope (like internal_error) to explicitly un-poison 
the variable?

Separately, all the location_t (input_location) changes are pretty 
clunky, can we make that conversion part of the macro?

Jason


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
  2021-06-30  9:00   ` Richard Biener
  2021-06-30 15:13   ` David Malcolm
@ 2021-07-02 19:20   ` Martin Sebor
  2021-07-02 23:47     ` Trevor Saunders
  2 siblings, 1 reply; 25+ messages in thread
From: Martin Sebor @ 2021-07-02 19:20 UTC (permalink / raw)
  To: Trevor Saunders, gcc-patches

On 6/29/21 11:35 PM, Trevor Saunders wrote:
> This makes it possible to assert if input_location is used during the lifetime
> of a scope.  This will allow us to find places that currently use it within a
> function and its callees, or prevent adding uses within the lifetime of a
> function after all existing uses are removed.

I of course support removing global state but I have questions about
this approach.  I'm probably missing some context but I don't
understand how it's better than replacing the variables with
functions now (defining the variables as static in some .c file).

Also, it seems as though the mechanism to enforce this policy of not
using global variables directly is to trigger an ICE when the piece
code that does end up using runs.  If this is correct, I would be
very uncomfortable with this approach, and not just because it would
expose our users to a GCC-internal policy but generally because
the enforcement of a policy should happen as early as possible so
that violators can fix them before they submit code for review.

Finally, I've been under the impression that defining global objects
that require dynamic initialization is discouraged in GCC.  This patch
seems to do just that: define poisonable objects in each file that
defines such a variable.  I don't see any uses of auto_poison in
this patch, so it looks as though the poisonable definitions aren't
actually doing anything useful yet but might start enforcing
the policy if some other patch defines an auto_poison variable
referring to the same global in a file/scope from which functions
changed in this patch that access the variable are called?  (This
probably exposes my overall confusion with how this works.)

Martin

> 
> bootstrapped and regtested on x86_64-linux-gnu, ok?
> 
> Trev
> 
> gcc/cp/ChangeLog:
> 
> 	* call.c (add_builtin_candidate): Adjust.
> 	* decl.c (compute_array_index_type_loc): Likewise.
> 	* decl2.c (get_guard_cond): Likewise.
> 	(one_static_initialization_or_destruction): Likewise.
> 	(do_static_initialization_or_destruction): Likewise.
> 	* init.c (build_new_1): Likewise.
> 	(build_vec_init): Likewise.
> 	* module.cc (finish_module_processing): Likewise.
> 	* parser.c (cp_convert_range_for): Likewise.
> 	(cp_parser_perform_range_for_lookup): Likewise.
> 	(cp_parser_omp_for_incr): Likewise.
> 	(cp_convert_omp_range_for): Likewise.
> 	* pt.c (fold_expression): Likewise.
> 	(tsubst_copy_and_build): Likewise.
> 	* typeck.c (common_pointer_type): Likewise.
> 	(cp_build_array_ref): Likewise.
> 	(get_member_function_from_ptrfunc): Likewise.
> 	(cp_build_unary_op): Likewise.
> 	(convert_ptrmem): Likewise.
> 	(cp_build_modify_expr): Likewise.
> 	(build_ptrmemfunc): Likewise.
> 
> gcc/ChangeLog:
> 
> 	* diagnostic.c (internal_error): Remove use of input_location.
> 	* input.c (input_location): Change type to poisonable<location_t>.
> 	* input.h (input_location): Adjust prototype.
> 
> gcc/objc/ChangeLog:
> 
> 	* objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
> ---
>   gcc/cp/call.c                       |  2 +-
>   gcc/cp/decl.c                       |  2 +-
>   gcc/cp/decl2.c                      | 12 +++++------
>   gcc/cp/init.c                       | 14 ++++++------
>   gcc/cp/module.cc                    |  2 +-
>   gcc/cp/parser.c                     | 11 +++++-----
>   gcc/cp/pt.c                         |  4 ++--
>   gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
>   gcc/diagnostic.c                    |  2 +-
>   gcc/input.c                         |  2 +-
>   gcc/input.h                         |  3 ++-
>   gcc/objc/objc-next-runtime-abi-02.c |  2 +-
>   12 files changed, 47 insertions(+), 42 deletions(-)
> 
> diff --git a/gcc/cp/call.c b/gcc/cp/call.c
> index e4df72ec1a3..c94fe0b3bd2 100644
> --- a/gcc/cp/call.c
> +++ b/gcc/cp/call.c
> @@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
>       {
>         if (TYPE_PTR_OR_PTRMEM_P (type1))
>   	{
> -	  tree cptype = composite_pointer_type (input_location,
> +	  tree cptype = composite_pointer_type (op_location_t (input_location),
>   						type1, type2,
>   						error_mark_node,
>   						error_mark_node,
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index fa6af6fec11..84e2bdae6bf 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
>   	 cp_build_binary_op will be appropriately folded.  */
>         {
>   	processing_template_decl_sentinel s;
> -	itype = cp_build_binary_op (input_location,
> +	itype = cp_build_binary_op (op_location_t (input_location),
>   				    MINUS_EXPR,
>   				    cp_convert (ssizetype, size, complain),
>   				    cp_convert (ssizetype, integer_one_node,
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index 090a83bd670..ddb7e248c63 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
>         guard_value = integer_one_node;
>         if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>   	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> -      guard = cp_build_binary_op (input_location,
> +      guard = cp_build_binary_op (location_t (input_location),
>   				  BIT_AND_EXPR, guard, guard_value,
>   				  tf_warning_or_error);
>       }
> @@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
>     guard_value = integer_zero_node;
>     if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>       guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> -  return cp_build_binary_op (input_location,
> +  return cp_build_binary_op (location_t (input_location),
>   			     EQ_EXPR, guard, guard_value,
>   			     tf_warning_or_error);
>   }
> @@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>   	 last to destroy the variable.  */
>         else if (initp)
>   	guard_cond
> -	  = cp_build_binary_op (input_location,
> +	  = cp_build_binary_op (location_t (input_location),
>   				EQ_EXPR,
>   				cp_build_unary_op (PREINCREMENT_EXPR,
>   						   guard,
> @@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>   				tf_warning_or_error);
>         else
>   	guard_cond
> -	  = cp_build_binary_op (input_location,
> +	  = cp_build_binary_op (location_t (input_location),
>   				EQ_EXPR,
>   				cp_build_unary_op (PREDECREMENT_EXPR,
>   						   guard,
> @@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>     /* Build the outer if-stmt to check for initialization or destruction.  */
>     init_if_stmt = begin_if_stmt ();
>     cond = initp ? integer_one_node : integer_zero_node;
> -  cond = cp_build_binary_op (input_location,
> +  cond = cp_build_binary_op (location_t (input_location),
>   			     EQ_EXPR,
>   			     initialize_p_decl,
>   			     cond,
> @@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>       /* Conditionalize this initialization on being in the right priority
>          and being initializing/finalizing appropriately.  */
>       priority_if_stmt = begin_if_stmt ();
> -    cond = cp_build_binary_op (input_location,
> +    cond = cp_build_binary_op (location_t (input_location),
>   			       EQ_EXPR,
>   			       priority_decl,
>   			       build_int_cst (NULL_TREE, priority),
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index 88f6f90a800..d9acdefae7c 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>   	  nelts = error_mark_node;
>   	}
>         if (nelts != error_mark_node)
> -	nelts = cp_build_binary_op (input_location,
> +	nelts = cp_build_binary_op (location_t (input_location),
>   				    MULT_EXPR, nelts,
>   				    inner_nelts_cst,
>   				    complain);
> @@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>               }
>   	  init_expr
>   	    = build_vec_init (data_addr,
> -			      cp_build_binary_op (input_location,
> +			      cp_build_binary_op (location_t (input_location),
>   						  MINUS_EXPR, outer_nelts,
>   						  integer_one_node,
>   						  complain),
> @@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>       {
>         if (check_new)
>   	{
> -	  tree ifexp = cp_build_binary_op (input_location,
> +	  tree ifexp = cp_build_binary_op (location_t (input_location),
>   					   NE_EXPR, alloc_node,
>   					   nullptr_node,
>   					   complain);
> -	  rval = build_conditional_expr (input_location, ifexp, rval,
> -					 alloc_node, complain);
> +	  rval = build_conditional_expr (location_t (input_location), ifexp,
> +					 rval, alloc_node, complain);
>   	}
>   
>         /* Perform the allocation before anything else, so that ALLOC_NODE
> @@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
>         && from_array != 2)
>       {
>         tree e;
> -      tree m = cp_build_binary_op (input_location,
> +      tree m = cp_build_binary_op (location_t (input_location),
>   				   MINUS_EXPR, maxindex, iterator,
>   				   complain);
>   
>         /* Flatten multi-dimensional array since build_vec_delete only
>   	 expects one-dimensional array.  */
>         if (TREE_CODE (type) == ARRAY_TYPE)
> -	m = cp_build_binary_op (input_location,
> +	m = cp_build_binary_op (location_t (input_location),
>   				MULT_EXPR, m,
>   				/* Avoid mixing signed and unsigned.  */
>   				convert (TREE_TYPE (m),
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index f259515a498..72f32487e51 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
>   	  elf_out to (fd, e);
>   	  if (to.begin ())
>   	    {
> -	      auto loc = input_location;
> +	      location_t loc = input_location;
>   	      /* So crashes finger-point the module decl.  */
>   	      input_location = state->loc;
>   	      state->write (&to, reader);
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index 02daa7a6f6a..e90ee873a94 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
>     finish_init_stmt (statement);
>   
>     /* The new for condition.  */
> -  condition = build_x_binary_op (input_location, NE_EXPR,
> +  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
>   				 begin, ERROR_MARK,
>   				 end, ERROR_MARK,
>   				 NULL, tf_warning_or_error);
> @@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
>   	  if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
>   	    {
>   	      if (cxx_dialect >= cxx17
> -		  && (build_x_binary_op (input_location, NE_EXPR,
> +		  && (build_x_binary_op (location_t (input_location), NE_EXPR,
>   					 *begin, ERROR_MARK,
>   					 *end, ERROR_MARK,
>   					 NULL, tf_none)
> @@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
>   					tf_warning_or_error);
>   	    }
>   	  else
> -	    lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
> -				     ERROR_MARK, NULL, tf_warning_or_error);
> +	    lhs = build_x_binary_op (location_t (input_location), op, lhs,
> +				     ERROR_MARK, rhs, ERROR_MARK, NULL,
> +				     tf_warning_or_error);
>   	}
>       }
>     while (token->type == CPP_PLUS || token->type == CPP_MINUS);
> @@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
>     if (CLASS_TYPE_P (iter_type))
>       cond = build2 (NE_EXPR, boolean_type_node, begin, end);
>     else
> -    cond = build_x_binary_op (input_location, NE_EXPR,
> +    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
>   			      begin, ERROR_MARK,
>   			      end, ERROR_MARK,
>   			      NULL, tf_warning_or_error);
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f2039e09cd7..b679e34bfa4 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, tsubst_flags_t complain)
>       case COMPOUND_EXPR:
>         return build_x_compound_expr (input_location, left, right, complain);
>       default:
> -      return build_x_binary_op (input_location, code,
> +      return build_x_binary_op (location_t (input_location), code,
>                                   left, TREE_CODE (left),
>                                   right, TREE_CODE (right),
>                                   /*overload=*/NULL,
> @@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
>   	warning_sentinel s4(warn_tautological_compare, was_dep);
>   
>   	tree r = build_x_binary_op
> -	  (input_location, TREE_CODE (t),
> +	  (location_t (input_location), TREE_CODE (t),
>   	   op0,
>   	   (warning_suppressed_p (TREE_OPERAND (t, 0))
>   	    ? ERROR_MARK
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index a483e1f988d..98aa9e69612 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
>                 || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
>                 || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
>   
> -  return composite_pointer_type (input_location, t1, t2,
> +  return composite_pointer_type (location_t (input_location), t1, t2,
>   				 error_mark_node, error_mark_node,
>                                    CPO_CONVERSION, tf_warning_or_error);
>   }
> @@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
>   
>       warn_array_subscript_with_type_char (loc, idx);
>   
> -    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
> +    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
> +			      complain);
>       if (first)
>         ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
>       ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
> @@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>   	{
>   	  int flag_sanitize_save;
>   	case ptrmemfunc_vbit_in_pfn:
> -	  e1 = cp_build_binary_op (input_location,
> +	  e1 = cp_build_binary_op (location_t (input_location),
>   				   BIT_AND_EXPR, idx, integer_one_node,
>   				   complain);
> -	  idx = cp_build_binary_op (input_location,
> +	  idx = cp_build_binary_op (location_t (input_location),
>   				    MINUS_EXPR, idx, integer_one_node,
>   				    complain);
>   	  if (idx == error_mark_node)
> @@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>   	  break;
>   
>   	case ptrmemfunc_vbit_in_delta:
> -	  e1 = cp_build_binary_op (input_location,
> +	  e1 = cp_build_binary_op (location_t (input_location),
>   				   BIT_AND_EXPR, delta, integer_one_node,
>   				   complain);
>   	  /* Don't instrument the RSHIFT_EXPR we're about to create because
> @@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>   	     well with SAVE_EXPRs therein.  */
>   	  flag_sanitize_save = flag_sanitize;
>   	  flag_sanitize = 0;
> -	  delta = cp_build_binary_op (input_location,
> +	  delta = cp_build_binary_op (location_t (input_location),
>   				      RSHIFT_EXPR, delta, integer_one_node,
>   				      complain);
>   	  flag_sanitize = flag_sanitize_save;
> @@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>   		     cp_build_addr_expr (e2, complain));
>   
>         e2 = fold_convert (TREE_TYPE (e3), e2);
> -      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
> +      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
> +				   complain);
>         if (e1 == error_mark_node)
>   	return error_mark_node;
>   
> @@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
>   
>       case TRUTH_NOT_EXPR:
>         if (gnu_vector_type_p (TREE_TYPE (arg)))
> -	return cp_build_binary_op (input_location, EQ_EXPR, arg,
> +	return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
>   				   build_zero_cst (TREE_TYPE (arg)), complain);
>         arg = perform_implicit_conversion (boolean_type_node, arg,
>   					 complain);
> @@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
>   	  if (TREE_CODE (expr) == PTRMEM_CST)
>   	    expr = cplus_expand_constant (expr);
>   
> -	  tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
> +	  tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
> +					  expr,
>   					  build_int_cst (TREE_TYPE (expr), -1),
>   					  complain);
>   	  tree op1 = build_nop (ptrdiff_type_node, expr);
> -	  tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
> -					 complain);
> +	  tree op2 = cp_build_binary_op (location_t (input_location),
> +					 PLUS_EXPR, op1, delta, complain);
>   
>   	  expr = fold_build3_loc (input_location,
>   				  COND_EXPR, ptrdiff_type_node, cond, op1, op2);
> @@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   	tree op2 = TREE_OPERAND (lhs, 2);
>   	if (TREE_CODE (op2) != THROW_EXPR)
>   	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
> -	tree cond = build_conditional_expr (input_location,
> +	tree cond = build_conditional_expr (location_t (input_location),
>   					    TREE_OPERAND (lhs, 0), op1, op2,
>   					    complain);
>   
> @@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>   	    /* Do the default thing.  */;
>   	  else
>   	    {
> -	      result = build_new_op (input_location, MODIFY_EXPR,
> +	      result = build_new_op (location_t (input_location), MODIFY_EXPR,
>   				     LOOKUP_NORMAL, lhs, rhs,
>   				     make_node (NOP_EXPR), /*overload=*/NULL,
>   				     complain);
> @@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
>         if (!integer_zerop (n))
>   	{
>   	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
> -	    n = cp_build_binary_op (input_location,
> +	    n = cp_build_binary_op (location_t (input_location),
>   				    LSHIFT_EXPR, n, integer_one_node,
>   				    complain);
> -	  delta = cp_build_binary_op (input_location,
> +	  delta = cp_build_binary_op (location_t (input_location),
>   				      PLUS_EXPR, delta, n, complain);
>   	}
>         return build_ptrmemfunc1 (to_type, delta, npfn);
> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index d58586f2526..3f68d1d79eb 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
>     auto_diagnostic_group d;
>     va_list ap;
>     va_start (ap, gmsgid);
> -  rich_location richloc (line_table, input_location);
> +  rich_location richloc (line_table, UNKNOWN_LOCATION);
>     diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
>     va_end (ap);
>   
> diff --git a/gcc/input.c b/gcc/input.c
> index 9e39e7df83c..1843c3077aa 100644
> --- a/gcc/input.c
> +++ b/gcc/input.c
> @@ -122,7 +122,7 @@ public:
>   
>   /* Current position in real source file.  */
>   
> -location_t input_location = UNKNOWN_LOCATION;
> +poisonable<location_t> input_location (UNKNOWN_LOCATION);
>   
>   class line_maps *line_table;
>   
> diff --git a/gcc/input.h b/gcc/input.h
> index f1ef5d76cfd..2b96ce8008e 100644
> --- a/gcc/input.h
> +++ b/gcc/input.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>   #ifndef GCC_INPUT_H
>   #define GCC_INPUT_H
>   
> +#include "poison.h"
>   #include "line-map.h"
>   
>   extern GTY(()) class line_maps *line_table;
> @@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
>   extern location_t expansion_point_location_if_in_system_header (location_t);
>   extern location_t expansion_point_location (location_t);
>   
> -extern location_t input_location;
> +extern poisonable<location_t> input_location;
>   
>   #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
>   #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
> diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
> index 3cfcd0b1a57..9ecb91cc56b 100644
> --- a/gcc/objc/objc-next-runtime-abi-02.c
> +++ b/gcc/objc/objc-next-runtime-abi-02.c
> @@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
>   			       fold_convert (rcv_p, integer_zero_node), 1);
>   
>   #ifdef OBJCPLUS
> -      ret_val = build_conditional_expr (input_location,
> +      ret_val = build_conditional_expr (location_t (input_location),
>   					ifexp, ret_val, ftree,
>   					tf_warning_or_error);
>   #else
> 


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-02 15:46       ` Jason Merrill
@ 2021-07-02 23:23         ` Trevor Saunders
  0 siblings, 0 replies; 25+ messages in thread
From: Trevor Saunders @ 2021-07-02 23:23 UTC (permalink / raw)
  To: Jason Merrill; +Cc: David Malcolm, gcc-patches

On Fri, Jul 02, 2021 at 11:46:46AM -0400, Jason Merrill wrote:
> On 7/1/21 6:16 AM, Trevor Saunders wrote:
> > On Wed, Jun 30, 2021 at 11:13:23AM -0400, David Malcolm wrote:
> > > On Wed, 2021-06-30 at 01:35 -0400, Trevor Saunders wrote:
> > > > This makes it possible to assert if input_location is used during the
> > > > lifetime
> > > > of a scope.  This will allow us to find places that currently use it
> > > > within a
> > > > function and its callees, or prevent adding uses within the lifetime
> > > > of a
> > > > function after all existing uses are removed.
> > > > 
> > > > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > > > 
> > > > Trev
> > > 
> > > [...snip...]
> > > 
> > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > > index d58586f2526..3f68d1d79eb 100644
> > > > --- a/gcc/diagnostic.c
> > > > +++ b/gcc/diagnostic.c
> > > > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> > > >     auto_diagnostic_group d;
> > > >     va_list ap;
> > > >     va_start (ap, gmsgid);
> > > > -  rich_location richloc (line_table, input_location);
> > > > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> > > >     diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> > > >     va_end (ap);
> > > 
> > > I actually make use of this in the analyzer: the analyzer sets
> > > input_location to stmt->location when analyzing a given stmt - that
> > > way, if the analyzer ICEs, the ICE is shown at the code construct that
> > > crashed the analyzer.
> > > 
> > > This behavior is useful to me, and would be lost with the proposed
> > > patch.
> > 
> > I made this change because otherwise if the compiler ICE's while access
> > to input_location is blocked we end up infinitely recursing complaining
> > we can't access it while trying to say where the last error was.  I was
> > nervous about the change before, and now I agree we need something
> > else.
> 
> How about allowing a scope (like internal_error) to explicitly un-poison the
> variable?

The only reason I didn't add such a thing was not having a need for it,
and not wanting to worry about the possible complexity of combining that
with allowing nested poisoning with a refcount.  However if people think
it would be useful to have this I'm happy to add it to a v2, otherwise
I'm happy to just use this locally for finding code using
input_location, or other globals.

> Separately, all the location_t (input_location) changes are pretty clunky,
> can we make that conversion part of the macro?

Currently its not a macro,  while we could change that, defining  it as
#define input_location ((location_t &) input_location_real)
seems a bit sneaky, but I think you have to define it that way if you
want to avoid updating all the assignments to input_location?

Thanks

Trev

> 
> Jason
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-02 19:20   ` Martin Sebor
@ 2021-07-02 23:47     ` Trevor Saunders
  2021-07-06 20:53       ` Martin Sebor
  0 siblings, 1 reply; 25+ messages in thread
From: Trevor Saunders @ 2021-07-02 23:47 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Fri, Jul 02, 2021 at 01:20:14PM -0600, Martin Sebor wrote:
> On 6/29/21 11:35 PM, Trevor Saunders wrote:
> > This makes it possible to assert if input_location is used during the lifetime
> > of a scope.  This will allow us to find places that currently use it within a
> > function and its callees, or prevent adding uses within the lifetime of a
> > function after all existing uses are removed.
> 
> I of course support removing global state but I have questions about
> this approach.  I'm probably missing some context but I don't
> understand how it's better than replacing the variables with
> functions now (defining the variables as static in some .c file).

Other than requiring either hiding the function calls behind a macro,
rahter than operator overloading, or needing to update all references I
think they do more or less the same thing.

> Also, it seems as though the mechanism to enforce this policy of not
> using global variables directly is to trigger an ICE when the piece
> code that does end up using runs.  If this is correct, I would be
> very uncomfortable with this approach, and not just because it would
> expose our users to a GCC-internal policy but generally because
> the enforcement of a policy should happen as early as possible so
> that violators can fix them before they submit code for review.

Perhaps the asserts should be gcc_checking_assert, to avoid any overhead
in release builds if nothing else.  One would really like to think that
the changed code is covered by the testsuite, if not exercised in
bootstraps, so in most cases it would be caught before patches are
submitted.  Certainly something will eventually slip through, probably
because it depends on the host or target, but that should be the
exception.  Its a rather useful property to know that a global's value
is not significant in a scope, to say remove save and restore of
input_location, or even more importantly remove push / pop of cfun, and
I can't see a way to do that statically, other than possibly a IPA
pass that depends on a LTO build, or analysis of the binary either of
which would be orders of magnitude more work.

> Finally, I've been under the impression that defining global objects
> that require dynamic initialization is discouraged in GCC.  This patch
> seems to do just that: define poisonable objects in each file that
> defines such a variable.  I don't see any uses of auto_poison in
> this patch, so it looks as though the poisonable definitions aren't
> actually doing anything useful yet but might start enforcing
> the policy if some other patch defines an auto_poison variable
> referring to the same global in a file/scope from which functions
> changed in this patch that access the variable are called?  (This
> probably exposes my overall confusion with how this works.)

As for dynamic initialization, that's technically true, but would be
fixed by making the constructor constexpr.
The first three patches in the series do just add infrastructure with
out making use of it to actually block anything, and the final patch
blocks usage in a minimal function as a somewhat toyish example of what
can be done.

thanks

Trev

> 
> Martin
> 
> > 
> > bootstrapped and regtested on x86_64-linux-gnu, ok?
> > 
> > Trev
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	* call.c (add_builtin_candidate): Adjust.
> > 	* decl.c (compute_array_index_type_loc): Likewise.
> > 	* decl2.c (get_guard_cond): Likewise.
> > 	(one_static_initialization_or_destruction): Likewise.
> > 	(do_static_initialization_or_destruction): Likewise.
> > 	* init.c (build_new_1): Likewise.
> > 	(build_vec_init): Likewise.
> > 	* module.cc (finish_module_processing): Likewise.
> > 	* parser.c (cp_convert_range_for): Likewise.
> > 	(cp_parser_perform_range_for_lookup): Likewise.
> > 	(cp_parser_omp_for_incr): Likewise.
> > 	(cp_convert_omp_range_for): Likewise.
> > 	* pt.c (fold_expression): Likewise.
> > 	(tsubst_copy_and_build): Likewise.
> > 	* typeck.c (common_pointer_type): Likewise.
> > 	(cp_build_array_ref): Likewise.
> > 	(get_member_function_from_ptrfunc): Likewise.
> > 	(cp_build_unary_op): Likewise.
> > 	(convert_ptrmem): Likewise.
> > 	(cp_build_modify_expr): Likewise.
> > 	(build_ptrmemfunc): Likewise.
> > 
> > gcc/ChangeLog:
> > 
> > 	* diagnostic.c (internal_error): Remove use of input_location.
> > 	* input.c (input_location): Change type to poisonable<location_t>.
> > 	* input.h (input_location): Adjust prototype.
> > 
> > gcc/objc/ChangeLog:
> > 
> > 	* objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
> > ---
> >   gcc/cp/call.c                       |  2 +-
> >   gcc/cp/decl.c                       |  2 +-
> >   gcc/cp/decl2.c                      | 12 +++++------
> >   gcc/cp/init.c                       | 14 ++++++------
> >   gcc/cp/module.cc                    |  2 +-
> >   gcc/cp/parser.c                     | 11 +++++-----
> >   gcc/cp/pt.c                         |  4 ++--
> >   gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
> >   gcc/diagnostic.c                    |  2 +-
> >   gcc/input.c                         |  2 +-
> >   gcc/input.h                         |  3 ++-
> >   gcc/objc/objc-next-runtime-abi-02.c |  2 +-
> >   12 files changed, 47 insertions(+), 42 deletions(-)
> > 
> > diff --git a/gcc/cp/call.c b/gcc/cp/call.c
> > index e4df72ec1a3..c94fe0b3bd2 100644
> > --- a/gcc/cp/call.c
> > +++ b/gcc/cp/call.c
> > @@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
> >       {
> >         if (TYPE_PTR_OR_PTRMEM_P (type1))
> >   	{
> > -	  tree cptype = composite_pointer_type (input_location,
> > +	  tree cptype = composite_pointer_type (op_location_t (input_location),
> >   						type1, type2,
> >   						error_mark_node,
> >   						error_mark_node,
> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> > index fa6af6fec11..84e2bdae6bf 100644
> > --- a/gcc/cp/decl.c
> > +++ b/gcc/cp/decl.c
> > @@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
> >   	 cp_build_binary_op will be appropriately folded.  */
> >         {
> >   	processing_template_decl_sentinel s;
> > -	itype = cp_build_binary_op (input_location,
> > +	itype = cp_build_binary_op (op_location_t (input_location),
> >   				    MINUS_EXPR,
> >   				    cp_convert (ssizetype, size, complain),
> >   				    cp_convert (ssizetype, integer_one_node,
> > diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> > index 090a83bd670..ddb7e248c63 100644
> > --- a/gcc/cp/decl2.c
> > +++ b/gcc/cp/decl2.c
> > @@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
> >         guard_value = integer_one_node;
> >         if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
> >   	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> > -      guard = cp_build_binary_op (input_location,
> > +      guard = cp_build_binary_op (location_t (input_location),
> >   				  BIT_AND_EXPR, guard, guard_value,
> >   				  tf_warning_or_error);
> >       }
> > @@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
> >     guard_value = integer_zero_node;
> >     if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
> >       guard_value = fold_convert (TREE_TYPE (guard), guard_value);
> > -  return cp_build_binary_op (input_location,
> > +  return cp_build_binary_op (location_t (input_location),
> >   			     EQ_EXPR, guard, guard_value,
> >   			     tf_warning_or_error);
> >   }
> > @@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
> >   	 last to destroy the variable.  */
> >         else if (initp)
> >   	guard_cond
> > -	  = cp_build_binary_op (input_location,
> > +	  = cp_build_binary_op (location_t (input_location),
> >   				EQ_EXPR,
> >   				cp_build_unary_op (PREINCREMENT_EXPR,
> >   						   guard,
> > @@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
> >   				tf_warning_or_error);
> >         else
> >   	guard_cond
> > -	  = cp_build_binary_op (input_location,
> > +	  = cp_build_binary_op (location_t (input_location),
> >   				EQ_EXPR,
> >   				cp_build_unary_op (PREDECREMENT_EXPR,
> >   						   guard,
> > @@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
> >     /* Build the outer if-stmt to check for initialization or destruction.  */
> >     init_if_stmt = begin_if_stmt ();
> >     cond = initp ? integer_one_node : integer_zero_node;
> > -  cond = cp_build_binary_op (input_location,
> > +  cond = cp_build_binary_op (location_t (input_location),
> >   			     EQ_EXPR,
> >   			     initialize_p_decl,
> >   			     cond,
> > @@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
> >       /* Conditionalize this initialization on being in the right priority
> >          and being initializing/finalizing appropriately.  */
> >       priority_if_stmt = begin_if_stmt ();
> > -    cond = cp_build_binary_op (input_location,
> > +    cond = cp_build_binary_op (location_t (input_location),
> >   			       EQ_EXPR,
> >   			       priority_decl,
> >   			       build_int_cst (NULL_TREE, priority),
> > diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> > index 88f6f90a800..d9acdefae7c 100644
> > --- a/gcc/cp/init.c
> > +++ b/gcc/cp/init.c
> > @@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
> >   	  nelts = error_mark_node;
> >   	}
> >         if (nelts != error_mark_node)
> > -	nelts = cp_build_binary_op (input_location,
> > +	nelts = cp_build_binary_op (location_t (input_location),
> >   				    MULT_EXPR, nelts,
> >   				    inner_nelts_cst,
> >   				    complain);
> > @@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
> >               }
> >   	  init_expr
> >   	    = build_vec_init (data_addr,
> > -			      cp_build_binary_op (input_location,
> > +			      cp_build_binary_op (location_t (input_location),
> >   						  MINUS_EXPR, outer_nelts,
> >   						  integer_one_node,
> >   						  complain),
> > @@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
> >       {
> >         if (check_new)
> >   	{
> > -	  tree ifexp = cp_build_binary_op (input_location,
> > +	  tree ifexp = cp_build_binary_op (location_t (input_location),
> >   					   NE_EXPR, alloc_node,
> >   					   nullptr_node,
> >   					   complain);
> > -	  rval = build_conditional_expr (input_location, ifexp, rval,
> > -					 alloc_node, complain);
> > +	  rval = build_conditional_expr (location_t (input_location), ifexp,
> > +					 rval, alloc_node, complain);
> >   	}
> >         /* Perform the allocation before anything else, so that ALLOC_NODE
> > @@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
> >         && from_array != 2)
> >       {
> >         tree e;
> > -      tree m = cp_build_binary_op (input_location,
> > +      tree m = cp_build_binary_op (location_t (input_location),
> >   				   MINUS_EXPR, maxindex, iterator,
> >   				   complain);
> >         /* Flatten multi-dimensional array since build_vec_delete only
> >   	 expects one-dimensional array.  */
> >         if (TREE_CODE (type) == ARRAY_TYPE)
> > -	m = cp_build_binary_op (input_location,
> > +	m = cp_build_binary_op (location_t (input_location),
> >   				MULT_EXPR, m,
> >   				/* Avoid mixing signed and unsigned.  */
> >   				convert (TREE_TYPE (m),
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index f259515a498..72f32487e51 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
> >   	  elf_out to (fd, e);
> >   	  if (to.begin ())
> >   	    {
> > -	      auto loc = input_location;
> > +	      location_t loc = input_location;
> >   	      /* So crashes finger-point the module decl.  */
> >   	      input_location = state->loc;
> >   	      state->write (&to, reader);
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index 02daa7a6f6a..e90ee873a94 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
> >     finish_init_stmt (statement);
> >     /* The new for condition.  */
> > -  condition = build_x_binary_op (input_location, NE_EXPR,
> > +  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
> >   				 begin, ERROR_MARK,
> >   				 end, ERROR_MARK,
> >   				 NULL, tf_warning_or_error);
> > @@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
> >   	  if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
> >   	    {
> >   	      if (cxx_dialect >= cxx17
> > -		  && (build_x_binary_op (input_location, NE_EXPR,
> > +		  && (build_x_binary_op (location_t (input_location), NE_EXPR,
> >   					 *begin, ERROR_MARK,
> >   					 *end, ERROR_MARK,
> >   					 NULL, tf_none)
> > @@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
> >   					tf_warning_or_error);
> >   	    }
> >   	  else
> > -	    lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
> > -				     ERROR_MARK, NULL, tf_warning_or_error);
> > +	    lhs = build_x_binary_op (location_t (input_location), op, lhs,
> > +				     ERROR_MARK, rhs, ERROR_MARK, NULL,
> > +				     tf_warning_or_error);
> >   	}
> >       }
> >     while (token->type == CPP_PLUS || token->type == CPP_MINUS);
> > @@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
> >     if (CLASS_TYPE_P (iter_type))
> >       cond = build2 (NE_EXPR, boolean_type_node, begin, end);
> >     else
> > -    cond = build_x_binary_op (input_location, NE_EXPR,
> > +    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
> >   			      begin, ERROR_MARK,
> >   			      end, ERROR_MARK,
> >   			      NULL, tf_warning_or_error);
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index f2039e09cd7..b679e34bfa4 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, tsubst_flags_t complain)
> >       case COMPOUND_EXPR:
> >         return build_x_compound_expr (input_location, left, right, complain);
> >       default:
> > -      return build_x_binary_op (input_location, code,
> > +      return build_x_binary_op (location_t (input_location), code,
> >                                   left, TREE_CODE (left),
> >                                   right, TREE_CODE (right),
> >                                   /*overload=*/NULL,
> > @@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
> >   	warning_sentinel s4(warn_tautological_compare, was_dep);
> >   	tree r = build_x_binary_op
> > -	  (input_location, TREE_CODE (t),
> > +	  (location_t (input_location), TREE_CODE (t),
> >   	   op0,
> >   	   (warning_suppressed_p (TREE_OPERAND (t, 0))
> >   	    ? ERROR_MARK
> > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> > index a483e1f988d..98aa9e69612 100644
> > --- a/gcc/cp/typeck.c
> > +++ b/gcc/cp/typeck.c
> > @@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
> >                 || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
> >                 || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
> > -  return composite_pointer_type (input_location, t1, t2,
> > +  return composite_pointer_type (location_t (input_location), t1, t2,
> >   				 error_mark_node, error_mark_node,
> >                                    CPO_CONVERSION, tf_warning_or_error);
> >   }
> > @@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
> >       warn_array_subscript_with_type_char (loc, idx);
> > -    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
> > +    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
> > +			      complain);
> >       if (first)
> >         ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
> >       ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
> > @@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
> >   	{
> >   	  int flag_sanitize_save;
> >   	case ptrmemfunc_vbit_in_pfn:
> > -	  e1 = cp_build_binary_op (input_location,
> > +	  e1 = cp_build_binary_op (location_t (input_location),
> >   				   BIT_AND_EXPR, idx, integer_one_node,
> >   				   complain);
> > -	  idx = cp_build_binary_op (input_location,
> > +	  idx = cp_build_binary_op (location_t (input_location),
> >   				    MINUS_EXPR, idx, integer_one_node,
> >   				    complain);
> >   	  if (idx == error_mark_node)
> > @@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
> >   	  break;
> >   	case ptrmemfunc_vbit_in_delta:
> > -	  e1 = cp_build_binary_op (input_location,
> > +	  e1 = cp_build_binary_op (location_t (input_location),
> >   				   BIT_AND_EXPR, delta, integer_one_node,
> >   				   complain);
> >   	  /* Don't instrument the RSHIFT_EXPR we're about to create because
> > @@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
> >   	     well with SAVE_EXPRs therein.  */
> >   	  flag_sanitize_save = flag_sanitize;
> >   	  flag_sanitize = 0;
> > -	  delta = cp_build_binary_op (input_location,
> > +	  delta = cp_build_binary_op (location_t (input_location),
> >   				      RSHIFT_EXPR, delta, integer_one_node,
> >   				      complain);
> >   	  flag_sanitize = flag_sanitize_save;
> > @@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
> >   		     cp_build_addr_expr (e2, complain));
> >         e2 = fold_convert (TREE_TYPE (e3), e2);
> > -      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
> > +      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
> > +				   complain);
> >         if (e1 == error_mark_node)
> >   	return error_mark_node;
> > @@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
> >       case TRUTH_NOT_EXPR:
> >         if (gnu_vector_type_p (TREE_TYPE (arg)))
> > -	return cp_build_binary_op (input_location, EQ_EXPR, arg,
> > +	return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
> >   				   build_zero_cst (TREE_TYPE (arg)), complain);
> >         arg = perform_implicit_conversion (boolean_type_node, arg,
> >   					 complain);
> > @@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
> >   	  if (TREE_CODE (expr) == PTRMEM_CST)
> >   	    expr = cplus_expand_constant (expr);
> > -	  tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
> > +	  tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
> > +					  expr,
> >   					  build_int_cst (TREE_TYPE (expr), -1),
> >   					  complain);
> >   	  tree op1 = build_nop (ptrdiff_type_node, expr);
> > -	  tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
> > -					 complain);
> > +	  tree op2 = cp_build_binary_op (location_t (input_location),
> > +					 PLUS_EXPR, op1, delta, complain);
> >   	  expr = fold_build3_loc (input_location,
> >   				  COND_EXPR, ptrdiff_type_node, cond, op1, op2);
> > @@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
> >   	tree op2 = TREE_OPERAND (lhs, 2);
> >   	if (TREE_CODE (op2) != THROW_EXPR)
> >   	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
> > -	tree cond = build_conditional_expr (input_location,
> > +	tree cond = build_conditional_expr (location_t (input_location),
> >   					    TREE_OPERAND (lhs, 0), op1, op2,
> >   					    complain);
> > @@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
> >   	    /* Do the default thing.  */;
> >   	  else
> >   	    {
> > -	      result = build_new_op (input_location, MODIFY_EXPR,
> > +	      result = build_new_op (location_t (input_location), MODIFY_EXPR,
> >   				     LOOKUP_NORMAL, lhs, rhs,
> >   				     make_node (NOP_EXPR), /*overload=*/NULL,
> >   				     complain);
> > @@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
> >         if (!integer_zerop (n))
> >   	{
> >   	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
> > -	    n = cp_build_binary_op (input_location,
> > +	    n = cp_build_binary_op (location_t (input_location),
> >   				    LSHIFT_EXPR, n, integer_one_node,
> >   				    complain);
> > -	  delta = cp_build_binary_op (input_location,
> > +	  delta = cp_build_binary_op (location_t (input_location),
> >   				      PLUS_EXPR, delta, n, complain);
> >   	}
> >         return build_ptrmemfunc1 (to_type, delta, npfn);
> > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > index d58586f2526..3f68d1d79eb 100644
> > --- a/gcc/diagnostic.c
> > +++ b/gcc/diagnostic.c
> > @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
> >     auto_diagnostic_group d;
> >     va_list ap;
> >     va_start (ap, gmsgid);
> > -  rich_location richloc (line_table, input_location);
> > +  rich_location richloc (line_table, UNKNOWN_LOCATION);
> >     diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
> >     va_end (ap);
> > diff --git a/gcc/input.c b/gcc/input.c
> > index 9e39e7df83c..1843c3077aa 100644
> > --- a/gcc/input.c
> > +++ b/gcc/input.c
> > @@ -122,7 +122,7 @@ public:
> >   /* Current position in real source file.  */
> > -location_t input_location = UNKNOWN_LOCATION;
> > +poisonable<location_t> input_location (UNKNOWN_LOCATION);
> >   class line_maps *line_table;
> > diff --git a/gcc/input.h b/gcc/input.h
> > index f1ef5d76cfd..2b96ce8008e 100644
> > --- a/gcc/input.h
> > +++ b/gcc/input.h
> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >   #ifndef GCC_INPUT_H
> >   #define GCC_INPUT_H
> > +#include "poison.h"
> >   #include "line-map.h"
> >   extern GTY(()) class line_maps *line_table;
> > @@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
> >   extern location_t expansion_point_location_if_in_system_header (location_t);
> >   extern location_t expansion_point_location (location_t);
> > -extern location_t input_location;
> > +extern poisonable<location_t> input_location;
> >   #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
> >   #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
> > diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
> > index 3cfcd0b1a57..9ecb91cc56b 100644
> > --- a/gcc/objc/objc-next-runtime-abi-02.c
> > +++ b/gcc/objc/objc-next-runtime-abi-02.c
> > @@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
> >   			       fold_convert (rcv_p, integer_zero_node), 1);
> >   #ifdef OBJCPLUS
> > -      ret_val = build_conditional_expr (input_location,
> > +      ret_val = build_conditional_expr (location_t (input_location),
> >   					ifexp, ret_val, ftree,
> >   					tf_warning_or_error);
> >   #else
> > 
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/4] allow poisoning input_location in ranges it should not be used
  2021-07-02 23:47     ` Trevor Saunders
@ 2021-07-06 20:53       ` Martin Sebor
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Sebor @ 2021-07-06 20:53 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: gcc-patches

On 7/2/21 5:47 PM, Trevor Saunders wrote:
> On Fri, Jul 02, 2021 at 01:20:14PM -0600, Martin Sebor wrote:
>> On 6/29/21 11:35 PM, Trevor Saunders wrote:
>>> This makes it possible to assert if input_location is used during the lifetime
>>> of a scope.  This will allow us to find places that currently use it within a
>>> function and its callees, or prevent adding uses within the lifetime of a
>>> function after all existing uses are removed.
>>
>> I of course support removing global state but I have questions about
>> this approach.  I'm probably missing some context but I don't
>> understand how it's better than replacing the variables with
>> functions now (defining the variables as static in some .c file).
> 
> Other than requiring either hiding the function calls behind a macro,
> rahter than operator overloading, or needing to update all references I
> think they do more or less the same thing.
> 
>> Also, it seems as though the mechanism to enforce this policy of not
>> using global variables directly is to trigger an ICE when the piece
>> code that does end up using runs.  If this is correct, I would be
>> very uncomfortable with this approach, and not just because it would
>> expose our users to a GCC-internal policy but generally because
>> the enforcement of a policy should happen as early as possible so
>> that violators can fix them before they submit code for review.
> 
> Perhaps the asserts should be gcc_checking_assert, to avoid any overhead
> in release builds if nothing else.  One would really like to think that
> the changed code is covered by the testsuite, if not exercised in
> bootstraps, so in most cases it would be caught before patches are
> submitted.  Certainly something will eventually slip through, probably
> because it depends on the host or target, but that should be the
> exception.

It's always the exception when these things slip through, but they
do.  I don't think the risks in this case justify the benefits of
enforcing an internal policy whose violations are otherwise entirely
benign.

   Its a rather useful property to know that a global's value
> is not significant in a scope, to say remove save and restore of
> input_location, or even more importantly remove push / pop of cfun, and
> I can't see a way to do that statically, other than possibly a IPA
> pass that depends on a LTO build, or analysis of the binary either of
> which would be orders of magnitude more work.

My concern is that poisoning a variable in one scope/file could
expose latent violations in other files far removed from it, and
that could easily happen under conditions not be exercised during
testing because of less than complete coverage.  We would have to
carry this risk potentially for a number of releases, until a full
replacement took place.

IMO, a safer and less costly solution to the global state problem
is to fully remove accesses to one variable at a time, replacing
each with the preferred alternative.  A piecemeal approach seems
fraught with too much risk for what to me seems like very little
immediate gain.  I don't see a value in enforcing this policy one
scope at a time.

Martin

> 
>> Finally, I've been under the impression that defining global objects
>> that require dynamic initialization is discouraged in GCC.  This patch
>> seems to do just that: define poisonable objects in each file that
>> defines such a variable.  I don't see any uses of auto_poison in
>> this patch, so it looks as though the poisonable definitions aren't
>> actually doing anything useful yet but might start enforcing
>> the policy if some other patch defines an auto_poison variable
>> referring to the same global in a file/scope from which functions
>> changed in this patch that access the variable are called?  (This
>> probably exposes my overall confusion with how this works.)
> 
> As for dynamic initialization, that's technically true, but would be
> fixed by making the constructor constexpr.
> The first three patches in the series do just add infrastructure with
> out making use of it to actually block anything, and the final patch
> blocks usage in a minimal function as a somewhat toyish example of what
> can be done.
> 
> thanks
> 
> Trev
> 
>>
>> Martin
>>
>>>
>>> bootstrapped and regtested on x86_64-linux-gnu, ok?
>>>
>>> Trev
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> 	* call.c (add_builtin_candidate): Adjust.
>>> 	* decl.c (compute_array_index_type_loc): Likewise.
>>> 	* decl2.c (get_guard_cond): Likewise.
>>> 	(one_static_initialization_or_destruction): Likewise.
>>> 	(do_static_initialization_or_destruction): Likewise.
>>> 	* init.c (build_new_1): Likewise.
>>> 	(build_vec_init): Likewise.
>>> 	* module.cc (finish_module_processing): Likewise.
>>> 	* parser.c (cp_convert_range_for): Likewise.
>>> 	(cp_parser_perform_range_for_lookup): Likewise.
>>> 	(cp_parser_omp_for_incr): Likewise.
>>> 	(cp_convert_omp_range_for): Likewise.
>>> 	* pt.c (fold_expression): Likewise.
>>> 	(tsubst_copy_and_build): Likewise.
>>> 	* typeck.c (common_pointer_type): Likewise.
>>> 	(cp_build_array_ref): Likewise.
>>> 	(get_member_function_from_ptrfunc): Likewise.
>>> 	(cp_build_unary_op): Likewise.
>>> 	(convert_ptrmem): Likewise.
>>> 	(cp_build_modify_expr): Likewise.
>>> 	(build_ptrmemfunc): Likewise.
>>>
>>> gcc/ChangeLog:
>>>
>>> 	* diagnostic.c (internal_error): Remove use of input_location.
>>> 	* input.c (input_location): Change type to poisonable<location_t>.
>>> 	* input.h (input_location): Adjust prototype.
>>>
>>> gcc/objc/ChangeLog:
>>>
>>> 	* objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
>>> ---
>>>    gcc/cp/call.c                       |  2 +-
>>>    gcc/cp/decl.c                       |  2 +-
>>>    gcc/cp/decl2.c                      | 12 +++++------
>>>    gcc/cp/init.c                       | 14 ++++++------
>>>    gcc/cp/module.cc                    |  2 +-
>>>    gcc/cp/parser.c                     | 11 +++++-----
>>>    gcc/cp/pt.c                         |  4 ++--
>>>    gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
>>>    gcc/diagnostic.c                    |  2 +-
>>>    gcc/input.c                         |  2 +-
>>>    gcc/input.h                         |  3 ++-
>>>    gcc/objc/objc-next-runtime-abi-02.c |  2 +-
>>>    12 files changed, 47 insertions(+), 42 deletions(-)
>>>
>>> diff --git a/gcc/cp/call.c b/gcc/cp/call.c
>>> index e4df72ec1a3..c94fe0b3bd2 100644
>>> --- a/gcc/cp/call.c
>>> +++ b/gcc/cp/call.c
>>> @@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
>>>        {
>>>          if (TYPE_PTR_OR_PTRMEM_P (type1))
>>>    	{
>>> -	  tree cptype = composite_pointer_type (input_location,
>>> +	  tree cptype = composite_pointer_type (op_location_t (input_location),
>>>    						type1, type2,
>>>    						error_mark_node,
>>>    						error_mark_node,
>>> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
>>> index fa6af6fec11..84e2bdae6bf 100644
>>> --- a/gcc/cp/decl.c
>>> +++ b/gcc/cp/decl.c
>>> @@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
>>>    	 cp_build_binary_op will be appropriately folded.  */
>>>          {
>>>    	processing_template_decl_sentinel s;
>>> -	itype = cp_build_binary_op (input_location,
>>> +	itype = cp_build_binary_op (op_location_t (input_location),
>>>    				    MINUS_EXPR,
>>>    				    cp_convert (ssizetype, size, complain),
>>>    				    cp_convert (ssizetype, integer_one_node,
>>> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
>>> index 090a83bd670..ddb7e248c63 100644
>>> --- a/gcc/cp/decl2.c
>>> +++ b/gcc/cp/decl2.c
>>> @@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
>>>          guard_value = integer_one_node;
>>>          if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>>>    	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
>>> -      guard = cp_build_binary_op (input_location,
>>> +      guard = cp_build_binary_op (location_t (input_location),
>>>    				  BIT_AND_EXPR, guard, guard_value,
>>>    				  tf_warning_or_error);
>>>        }
>>> @@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
>>>      guard_value = integer_zero_node;
>>>      if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
>>>        guard_value = fold_convert (TREE_TYPE (guard), guard_value);
>>> -  return cp_build_binary_op (input_location,
>>> +  return cp_build_binary_op (location_t (input_location),
>>>    			     EQ_EXPR, guard, guard_value,
>>>    			     tf_warning_or_error);
>>>    }
>>> @@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>>>    	 last to destroy the variable.  */
>>>          else if (initp)
>>>    	guard_cond
>>> -	  = cp_build_binary_op (input_location,
>>> +	  = cp_build_binary_op (location_t (input_location),
>>>    				EQ_EXPR,
>>>    				cp_build_unary_op (PREINCREMENT_EXPR,
>>>    						   guard,
>>> @@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
>>>    				tf_warning_or_error);
>>>          else
>>>    	guard_cond
>>> -	  = cp_build_binary_op (input_location,
>>> +	  = cp_build_binary_op (location_t (input_location),
>>>    				EQ_EXPR,
>>>    				cp_build_unary_op (PREDECREMENT_EXPR,
>>>    						   guard,
>>> @@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>>>      /* Build the outer if-stmt to check for initialization or destruction.  */
>>>      init_if_stmt = begin_if_stmt ();
>>>      cond = initp ? integer_one_node : integer_zero_node;
>>> -  cond = cp_build_binary_op (input_location,
>>> +  cond = cp_build_binary_op (location_t (input_location),
>>>    			     EQ_EXPR,
>>>    			     initialize_p_decl,
>>>    			     cond,
>>> @@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
>>>        /* Conditionalize this initialization on being in the right priority
>>>           and being initializing/finalizing appropriately.  */
>>>        priority_if_stmt = begin_if_stmt ();
>>> -    cond = cp_build_binary_op (input_location,
>>> +    cond = cp_build_binary_op (location_t (input_location),
>>>    			       EQ_EXPR,
>>>    			       priority_decl,
>>>    			       build_int_cst (NULL_TREE, priority),
>>> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
>>> index 88f6f90a800..d9acdefae7c 100644
>>> --- a/gcc/cp/init.c
>>> +++ b/gcc/cp/init.c
>>> @@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>>>    	  nelts = error_mark_node;
>>>    	}
>>>          if (nelts != error_mark_node)
>>> -	nelts = cp_build_binary_op (input_location,
>>> +	nelts = cp_build_binary_op (location_t (input_location),
>>>    				    MULT_EXPR, nelts,
>>>    				    inner_nelts_cst,
>>>    				    complain);
>>> @@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>>>                }
>>>    	  init_expr
>>>    	    = build_vec_init (data_addr,
>>> -			      cp_build_binary_op (input_location,
>>> +			      cp_build_binary_op (location_t (input_location),
>>>    						  MINUS_EXPR, outer_nelts,
>>>    						  integer_one_node,
>>>    						  complain),
>>> @@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>>>        {
>>>          if (check_new)
>>>    	{
>>> -	  tree ifexp = cp_build_binary_op (input_location,
>>> +	  tree ifexp = cp_build_binary_op (location_t (input_location),
>>>    					   NE_EXPR, alloc_node,
>>>    					   nullptr_node,
>>>    					   complain);
>>> -	  rval = build_conditional_expr (input_location, ifexp, rval,
>>> -					 alloc_node, complain);
>>> +	  rval = build_conditional_expr (location_t (input_location), ifexp,
>>> +					 rval, alloc_node, complain);
>>>    	}
>>>          /* Perform the allocation before anything else, so that ALLOC_NODE
>>> @@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
>>>          && from_array != 2)
>>>        {
>>>          tree e;
>>> -      tree m = cp_build_binary_op (input_location,
>>> +      tree m = cp_build_binary_op (location_t (input_location),
>>>    				   MINUS_EXPR, maxindex, iterator,
>>>    				   complain);
>>>          /* Flatten multi-dimensional array since build_vec_delete only
>>>    	 expects one-dimensional array.  */
>>>          if (TREE_CODE (type) == ARRAY_TYPE)
>>> -	m = cp_build_binary_op (input_location,
>>> +	m = cp_build_binary_op (location_t (input_location),
>>>    				MULT_EXPR, m,
>>>    				/* Avoid mixing signed and unsigned.  */
>>>    				convert (TREE_TYPE (m),
>>> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
>>> index f259515a498..72f32487e51 100644
>>> --- a/gcc/cp/module.cc
>>> +++ b/gcc/cp/module.cc
>>> @@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
>>>    	  elf_out to (fd, e);
>>>    	  if (to.begin ())
>>>    	    {
>>> -	      auto loc = input_location;
>>> +	      location_t loc = input_location;
>>>    	      /* So crashes finger-point the module decl.  */
>>>    	      input_location = state->loc;
>>>    	      state->write (&to, reader);
>>> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>>> index 02daa7a6f6a..e90ee873a94 100644
>>> --- a/gcc/cp/parser.c
>>> +++ b/gcc/cp/parser.c
>>> @@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
>>>      finish_init_stmt (statement);
>>>      /* The new for condition.  */
>>> -  condition = build_x_binary_op (input_location, NE_EXPR,
>>> +  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
>>>    				 begin, ERROR_MARK,
>>>    				 end, ERROR_MARK,
>>>    				 NULL, tf_warning_or_error);
>>> @@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
>>>    	  if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
>>>    	    {
>>>    	      if (cxx_dialect >= cxx17
>>> -		  && (build_x_binary_op (input_location, NE_EXPR,
>>> +		  && (build_x_binary_op (location_t (input_location), NE_EXPR,
>>>    					 *begin, ERROR_MARK,
>>>    					 *end, ERROR_MARK,
>>>    					 NULL, tf_none)
>>> @@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
>>>    					tf_warning_or_error);
>>>    	    }
>>>    	  else
>>> -	    lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
>>> -				     ERROR_MARK, NULL, tf_warning_or_error);
>>> +	    lhs = build_x_binary_op (location_t (input_location), op, lhs,
>>> +				     ERROR_MARK, rhs, ERROR_MARK, NULL,
>>> +				     tf_warning_or_error);
>>>    	}
>>>        }
>>>      while (token->type == CPP_PLUS || token->type == CPP_MINUS);
>>> @@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
>>>      if (CLASS_TYPE_P (iter_type))
>>>        cond = build2 (NE_EXPR, boolean_type_node, begin, end);
>>>      else
>>> -    cond = build_x_binary_op (input_location, NE_EXPR,
>>> +    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
>>>    			      begin, ERROR_MARK,
>>>    			      end, ERROR_MARK,
>>>    			      NULL, tf_warning_or_error);
>>> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
>>> index f2039e09cd7..b679e34bfa4 100644
>>> --- a/gcc/cp/pt.c
>>> +++ b/gcc/cp/pt.c
>>> @@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, tsubst_flags_t complain)
>>>        case COMPOUND_EXPR:
>>>          return build_x_compound_expr (input_location, left, right, complain);
>>>        default:
>>> -      return build_x_binary_op (input_location, code,
>>> +      return build_x_binary_op (location_t (input_location), code,
>>>                                    left, TREE_CODE (left),
>>>                                    right, TREE_CODE (right),
>>>                                    /*overload=*/NULL,
>>> @@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
>>>    	warning_sentinel s4(warn_tautological_compare, was_dep);
>>>    	tree r = build_x_binary_op
>>> -	  (input_location, TREE_CODE (t),
>>> +	  (location_t (input_location), TREE_CODE (t),
>>>    	   op0,
>>>    	   (warning_suppressed_p (TREE_OPERAND (t, 0))
>>>    	    ? ERROR_MARK
>>> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
>>> index a483e1f988d..98aa9e69612 100644
>>> --- a/gcc/cp/typeck.c
>>> +++ b/gcc/cp/typeck.c
>>> @@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
>>>                  || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
>>>                  || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
>>> -  return composite_pointer_type (input_location, t1, t2,
>>> +  return composite_pointer_type (location_t (input_location), t1, t2,
>>>    				 error_mark_node, error_mark_node,
>>>                                     CPO_CONVERSION, tf_warning_or_error);
>>>    }
>>> @@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
>>>        warn_array_subscript_with_type_char (loc, idx);
>>> -    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
>>> +    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
>>> +			      complain);
>>>        if (first)
>>>          ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
>>>        ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
>>> @@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>>>    	{
>>>    	  int flag_sanitize_save;
>>>    	case ptrmemfunc_vbit_in_pfn:
>>> -	  e1 = cp_build_binary_op (input_location,
>>> +	  e1 = cp_build_binary_op (location_t (input_location),
>>>    				   BIT_AND_EXPR, idx, integer_one_node,
>>>    				   complain);
>>> -	  idx = cp_build_binary_op (input_location,
>>> +	  idx = cp_build_binary_op (location_t (input_location),
>>>    				    MINUS_EXPR, idx, integer_one_node,
>>>    				    complain);
>>>    	  if (idx == error_mark_node)
>>> @@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>>>    	  break;
>>>    	case ptrmemfunc_vbit_in_delta:
>>> -	  e1 = cp_build_binary_op (input_location,
>>> +	  e1 = cp_build_binary_op (location_t (input_location),
>>>    				   BIT_AND_EXPR, delta, integer_one_node,
>>>    				   complain);
>>>    	  /* Don't instrument the RSHIFT_EXPR we're about to create because
>>> @@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>>>    	     well with SAVE_EXPRs therein.  */
>>>    	  flag_sanitize_save = flag_sanitize;
>>>    	  flag_sanitize = 0;
>>> -	  delta = cp_build_binary_op (input_location,
>>> +	  delta = cp_build_binary_op (location_t (input_location),
>>>    				      RSHIFT_EXPR, delta, integer_one_node,
>>>    				      complain);
>>>    	  flag_sanitize = flag_sanitize_save;
>>> @@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
>>>    		     cp_build_addr_expr (e2, complain));
>>>          e2 = fold_convert (TREE_TYPE (e3), e2);
>>> -      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
>>> +      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
>>> +				   complain);
>>>          if (e1 == error_mark_node)
>>>    	return error_mark_node;
>>> @@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
>>>        case TRUTH_NOT_EXPR:
>>>          if (gnu_vector_type_p (TREE_TYPE (arg)))
>>> -	return cp_build_binary_op (input_location, EQ_EXPR, arg,
>>> +	return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
>>>    				   build_zero_cst (TREE_TYPE (arg)), complain);
>>>          arg = perform_implicit_conversion (boolean_type_node, arg,
>>>    					 complain);
>>> @@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
>>>    	  if (TREE_CODE (expr) == PTRMEM_CST)
>>>    	    expr = cplus_expand_constant (expr);
>>> -	  tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
>>> +	  tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
>>> +					  expr,
>>>    					  build_int_cst (TREE_TYPE (expr), -1),
>>>    					  complain);
>>>    	  tree op1 = build_nop (ptrdiff_type_node, expr);
>>> -	  tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
>>> -					 complain);
>>> +	  tree op2 = cp_build_binary_op (location_t (input_location),
>>> +					 PLUS_EXPR, op1, delta, complain);
>>>    	  expr = fold_build3_loc (input_location,
>>>    				  COND_EXPR, ptrdiff_type_node, cond, op1, op2);
>>> @@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>>>    	tree op2 = TREE_OPERAND (lhs, 2);
>>>    	if (TREE_CODE (op2) != THROW_EXPR)
>>>    	  op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
>>> -	tree cond = build_conditional_expr (input_location,
>>> +	tree cond = build_conditional_expr (location_t (input_location),
>>>    					    TREE_OPERAND (lhs, 0), op1, op2,
>>>    					    complain);
>>> @@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
>>>    	    /* Do the default thing.  */;
>>>    	  else
>>>    	    {
>>> -	      result = build_new_op (input_location, MODIFY_EXPR,
>>> +	      result = build_new_op (location_t (input_location), MODIFY_EXPR,
>>>    				     LOOKUP_NORMAL, lhs, rhs,
>>>    				     make_node (NOP_EXPR), /*overload=*/NULL,
>>>    				     complain);
>>> @@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
>>>          if (!integer_zerop (n))
>>>    	{
>>>    	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
>>> -	    n = cp_build_binary_op (input_location,
>>> +	    n = cp_build_binary_op (location_t (input_location),
>>>    				    LSHIFT_EXPR, n, integer_one_node,
>>>    				    complain);
>>> -	  delta = cp_build_binary_op (input_location,
>>> +	  delta = cp_build_binary_op (location_t (input_location),
>>>    				      PLUS_EXPR, delta, n, complain);
>>>    	}
>>>          return build_ptrmemfunc1 (to_type, delta, npfn);
>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
>>> index d58586f2526..3f68d1d79eb 100644
>>> --- a/gcc/diagnostic.c
>>> +++ b/gcc/diagnostic.c
>>> @@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
>>>      auto_diagnostic_group d;
>>>      va_list ap;
>>>      va_start (ap, gmsgid);
>>> -  rich_location richloc (line_table, input_location);
>>> +  rich_location richloc (line_table, UNKNOWN_LOCATION);
>>>      diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
>>>      va_end (ap);
>>> diff --git a/gcc/input.c b/gcc/input.c
>>> index 9e39e7df83c..1843c3077aa 100644
>>> --- a/gcc/input.c
>>> +++ b/gcc/input.c
>>> @@ -122,7 +122,7 @@ public:
>>>    /* Current position in real source file.  */
>>> -location_t input_location = UNKNOWN_LOCATION;
>>> +poisonable<location_t> input_location (UNKNOWN_LOCATION);
>>>    class line_maps *line_table;
>>> diff --git a/gcc/input.h b/gcc/input.h
>>> index f1ef5d76cfd..2b96ce8008e 100644
>>> --- a/gcc/input.h
>>> +++ b/gcc/input.h
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>>    #ifndef GCC_INPUT_H
>>>    #define GCC_INPUT_H
>>> +#include "poison.h"
>>>    #include "line-map.h"
>>>    extern GTY(()) class line_maps *line_table;
>>> @@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
>>>    extern location_t expansion_point_location_if_in_system_header (location_t);
>>>    extern location_t expansion_point_location (location_t);
>>> -extern location_t input_location;
>>> +extern poisonable<location_t> input_location;
>>>    #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
>>>    #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
>>> diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
>>> index 3cfcd0b1a57..9ecb91cc56b 100644
>>> --- a/gcc/objc/objc-next-runtime-abi-02.c
>>> +++ b/gcc/objc/objc-next-runtime-abi-02.c
>>> @@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
>>>    			       fold_convert (rcv_p, integer_zero_node), 1);
>>>    #ifdef OBJCPLUS
>>> -      ret_val = build_conditional_expr (input_location,
>>> +      ret_val = build_conditional_expr (location_t (input_location),
>>>    					ifexp, ret_val, ftree,
>>>    					tf_warning_or_error);
>>>    #else
>>>
>>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [committed] input.c: move file caching globals to a new file_cache class
  2021-07-01 21:51             ` [committed] input.c: move file caching globals to a new file_cache class David Malcolm
@ 2021-07-11 16:58               ` Lewis Hyatt
  2021-07-14 22:53                 ` David Malcolm
  0 siblings, 1 reply; 25+ messages in thread
From: Lewis Hyatt @ 2021-07-11 16:58 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

Hi David-

I thought this might be a good opportunity to ask about the patch that
supports -finput-charset in diagnostic.c please?
https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564527.html

The patch will require some work to adapt to the new changes below. I
am happy to do that, but thought I should check first whether you have
any interest in this approach? Thanks!

-Lewis

On Thu, Jul 1, 2021 at 5:52 PM David Malcolm via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> This moves some global state from input.c to a new file_cache class,
> of which an instance is owned by global_dc.  Various state is also
> made private.
>
> No functional change intended.
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> Pushed to trunk as b544c348e13ad33d55f0d954370ab1fb0f2bf683.
>
> gcc/ChangeLog:
>         * diagnostic.h (diagnostic_context::m_file_cache): New field.
>         * input.c (class fcache): Rename to...
>         (class file_cache_slot): ...this, making most members private and
>         prefixing fields with "m_".
>         (file_cache_slot::get_file_path): New accessor.
>         (file_cache_slot::get_use_count): New accessor.
>         (file_cache_slot::missing_trailing_newline_p): New accessor.
>         (file_cache_slot::inc_use_count): New.
>         (fcache_buffer_size): Move to...
>         (file_cache_slot::buffer_size): ...here.
>         (fcache_line_record_size): Move to...
>         (file_cache_slot::line_record_size): ...here.
>         (fcache_tab): Delete, in favor of global_dc->m_file_cache.
>         (fcache_tab_size): Move to file_cache::num_file_slots.
>         (diagnostic_file_cache_init): Update for move of fcache_tab
>         to global_dc->m_file_cache.
>         (diagnostic_file_cache_fini): Likewise.
>         (lookup_file_in_cache_tab): Convert to...
>         (file_cache::lookup_file): ...this.
>         (diagnostics_file_cache_forcibly_evict_file): Update for move of
>         fcache_tab to global_dc->m_file_cache, moving most of
>         implementation to...
>         (file_cache::forcibly_evict_file): ...this new function and...
>         (file_cache_slot::evict): ...this new function.
>         (evicted_cache_tab_entry): Convert to...
>         (file_cache::evicted_cache_tab_entry): ...this.
>         (add_file_to_cache_tab): Convert to...
>         (file_cache::add_file): ...this, moving bulk of implementation
>         to...
>         (file_cache_slot::create): ..this new function.
>         (file_cache::file_cache): New.
>         (file_cache::~file_cache): New.
>         (lookup_or_add_file_to_cache_tab): Convert to...
>         (file_cache::lookup_or_add_file): ..this new function.
>         (fcache::fcache): Rename to...
>         (file_cache_slot::file_cache_slot): ...this, adding "m_" prefixes
>         to fields.
>         (fcache::~fcache): Rename to...
>         (file_cache_slot::~file_cache_slot): ...this, adding "m_" prefixes
>         to fields.
>         (needs_read): Convert to...
>         (file_cache_slot::needs_read_p): ...this.
>         (needs_grow): Convert to...
>         (file_cache_slot::needs_grow_p): ...this.
>         (maybe_grow): Convert to...
>         (file_cache_slot::maybe_grow): ...this.
>         (read_data): Convert to...
>         (file_cache_slot::read_data): ...this.
>         (maybe_read_data): Convert to...
>         (file_cache_slot::maybe_read_data): ...this.
>         (get_next_line): Convert to...
>         (file_cache_slot::get_next_line): ...this.
>         (goto_next_line): Convert to...
>         (file_cache_slot::goto_next_line): ...this.
>         (read_line_num): Convert to...
>         (file_cache_slot::read_line_num): ...this.
>         (location_get_source_line): Update for moving of globals to
>         global_dc->m_file_cache.
>         (location_missing_trailing_newline): Likewise.
>         * input.h (class file_cache_slot): New forward decl.
>         (class file_cache): New.
>
> Signed-off-by: David Malcolm <dmalcolm@redhat.com>
> ---
>  gcc/diagnostic.h |   3 +
>  gcc/input.c      | 459 +++++++++++++++++++++++++++--------------------
>  gcc/input.h      |  33 ++++
>  3 files changed, 301 insertions(+), 194 deletions(-)
>
> diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
> index 1b9d6b1f64d..086bc4f903f 100644
> --- a/gcc/diagnostic.h
> +++ b/gcc/diagnostic.h
> @@ -136,6 +136,9 @@ struct diagnostic_context
>    /* Where most of the diagnostic formatting work is done.  */
>    pretty_printer *printer;
>
> +  /* Cache of source code.  */
> +  file_cache *m_file_cache;
> +
>    /* The number of times we have issued diagnostics.  */
>    int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
>
> diff --git a/gcc/input.c b/gcc/input.c
> index 9e39e7df83c..de20d983d2c 100644
> --- a/gcc/input.c
> +++ b/gcc/input.c
> @@ -32,9 +32,29 @@ along with GCC; see the file COPYING3.  If not see
>
>  /* This is a cache used by get_next_line to store the content of a
>     file to be searched for file lines.  */
> -class fcache
> +class file_cache_slot
>  {
>  public:
> +  file_cache_slot ();
> +  ~file_cache_slot ();
> +
> +  bool read_line_num (size_t line_num,
> +                     char ** line, ssize_t *line_len);
> +
> +  /* Accessors.  */
> +  const char *get_file_path () const { return m_file_path; }
> +  unsigned get_use_count () const { return m_use_count; }
> +  bool missing_trailing_newline_p () const
> +  {
> +    return m_missing_trailing_newline;
> +  }
> +
> +  void inc_use_count () { m_use_count++; }
> +
> +  void create (const char *file_path, FILE *fp, unsigned highest_use_count);
> +  void evict ();
> +
> + private:
>    /* These are information used to store a line boundary.  */
>    class line_info
>    {
> @@ -61,36 +81,48 @@ public:
>      {}
>    };
>
> +  bool needs_read_p () const;
> +  bool needs_grow_p () const;
> +  void maybe_grow ();
> +  bool read_data ();
> +  bool maybe_read_data ();
> +  bool get_next_line (char **line, ssize_t *line_len);
> +  bool read_next_line (char ** line, ssize_t *line_len);
> +  bool goto_next_line ();
> +
> +  static const size_t buffer_size = 4 * 1024;
> +  static const size_t line_record_size = 100;
> +
>    /* The number of time this file has been accessed.  This is used
>       to designate which file cache to evict from the cache
>       array.  */
> -  unsigned use_count;
> +  unsigned m_use_count;
>
>    /* The file_path is the key for identifying a particular file in
>       the cache.
>       For libcpp-using code, the underlying buffer for this field is
>       owned by the corresponding _cpp_file within the cpp_reader.  */
> -  const char *file_path;
> +  const char *m_file_path;
>
> -  FILE *fp;
> +  FILE *m_fp;
>
>    /* This points to the content of the file that we've read so
>       far.  */
> -  char *data;
> +  char *m_data;
>
>    /*  The size of the DATA array above.*/
> -  size_t size;
> +  size_t m_size;
>
>    /* The number of bytes read from the underlying file so far.  This
>       must be less (or equal) than SIZE above.  */
> -  size_t nb_read;
> +  size_t m_nb_read;
>
>    /* The index of the beginning of the current line.  */
> -  size_t line_start_idx;
> +  size_t m_line_start_idx;
>
>    /* The number of the previous line read.  This starts at 1.  Zero
>       means we've read no line so far.  */
> -  size_t line_num;
> +  size_t m_line_num;
>
>    /* This is the total number of lines of the current file.  At the
>       moment, we try to get this information from the line map
> @@ -100,24 +132,21 @@ public:
>       the number of lines before compilation really starts.  For e.g,
>       the C front-end, it can happen that we start emitting diagnostics
>       before the line map has seen the end of the file.  */
> -  size_t total_lines;
> +  size_t m_total_lines;
>
>    /* Could this file be missing a trailing newline on its final line?
>       Initially true (to cope with empty files), set to true/false
>       as each line is read.  */
> -  bool missing_trailing_newline;
> +  bool m_missing_trailing_newline;
>
>    /* This is a record of the beginning and end of the lines we've seen
>       while reading the file.  This is useful to avoid walking the data
>       from the beginning when we are asked to read a line that is
>       before LINE_START_IDX above.  Note that the maximum size of this
> -     record is fcache_line_record_size, so that the memory consumption
> +     record is line_record_size, so that the memory consumption
>       doesn't explode.  We thus scale total_lines down to
> -     fcache_line_record_size.  */
> -  vec<line_info, va_heap> line_record;
> -
> -  fcache ();
> -  ~fcache ();
> +     line_record_size.  */
> +  vec<line_info, va_heap> m_line_record;
>  };
>
>  /* Current position in real source file.  */
> @@ -133,11 +162,6 @@ class line_maps *line_table;
>
>  class line_maps *saved_line_table;
>
> -static fcache *fcache_tab;
> -static const size_t fcache_tab_size = 16;
> -static const size_t fcache_buffer_size = 4 * 1024;
> -static const size_t fcache_line_record_size = 100;
> -
>  /* Expand the source location LOC into a human readable location.  If
>     LOC resolves to a builtin location, the file name of the readable
>     location is set to the string "<built-in>". If EXPANSION_POINT_P is
> @@ -233,8 +257,9 @@ expand_location_1 (location_t loc,
>  static void
>  diagnostic_file_cache_init (void)
>  {
> -  if (fcache_tab == NULL)
> -    fcache_tab = new fcache[fcache_tab_size];
> +  gcc_assert (global_dc);
> +  if (global_dc->m_file_cache == NULL)
> +    global_dc->m_file_cache = new file_cache ();
>  }
>
>  /* Free the resources used by the set of cache used for files accessed
> @@ -243,10 +268,10 @@ diagnostic_file_cache_init (void)
>  void
>  diagnostic_file_cache_fini (void)
>  {
> -  if (fcache_tab)
> +  if (global_dc->m_file_cache)
>      {
> -      delete [] (fcache_tab);
> -      fcache_tab = NULL;
> +      delete global_dc->m_file_cache;
> +      global_dc->m_file_cache = NULL;
>      }
>  }
>
> @@ -273,28 +298,25 @@ total_lines_num (const char *file_path)
>     caret diagnostic.  Return the found cached file, or NULL if no
>     cached file was found.  */
>
> -static fcache*
> -lookup_file_in_cache_tab (const char *file_path)
> +file_cache_slot *
> +file_cache::lookup_file (const char *file_path)
>  {
> -  if (file_path == NULL)
> -    return NULL;
> -
> -  diagnostic_file_cache_init ();
> +  gcc_assert (file_path);
>
>    /* This will contain the found cached file.  */
> -  fcache *r = NULL;
> -  for (unsigned i = 0; i < fcache_tab_size; ++i)
> +  file_cache_slot *r = NULL;
> +  for (unsigned i = 0; i < num_file_slots; ++i)
>      {
> -      fcache *c = &fcache_tab[i];
> -      if (c->file_path && !strcmp (c->file_path, file_path))
> +      file_cache_slot *c = &m_file_slots[i];
> +      if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
>         {
> -         ++c->use_count;
> +         c->inc_use_count ();
>           r = c;
>         }
>      }
>
>    if (r)
> -    ++r->use_count;
> +    r->inc_use_count ();
>
>    return r;
>  }
> @@ -308,22 +330,39 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path)
>  {
>    gcc_assert (file_path);
>
> -  fcache *r = lookup_file_in_cache_tab (file_path);
> +  if (!global_dc->m_file_cache)
> +    return;
> +
> +  global_dc->m_file_cache->forcibly_evict_file (file_path);
> +}
> +
> +void
> +file_cache::forcibly_evict_file (const char *file_path)
> +{
> +  gcc_assert (file_path);
> +
> +  file_cache_slot *r = lookup_file (file_path);
>    if (!r)
>      /* Not found.  */
>      return;
>
> -  r->file_path = NULL;
> -  if (r->fp)
> -    fclose (r->fp);
> -  r->fp = NULL;
> -  r->nb_read = 0;
> -  r->line_start_idx = 0;
> -  r->line_num = 0;
> -  r->line_record.truncate (0);
> -  r->use_count = 0;
> -  r->total_lines = 0;
> -  r->missing_trailing_newline = true;
> +  r->evict ();
> +}
> +
> +void
> +file_cache_slot::evict ()
> +{
> +  m_file_path = NULL;
> +  if (m_fp)
> +    fclose (m_fp);
> +  m_fp = NULL;
> +  m_nb_read = 0;
> +  m_line_start_idx = 0;
> +  m_line_num = 0;
> +  m_line_record.truncate (0);
> +  m_use_count = 0;
> +  m_total_lines = 0;
> +  m_missing_trailing_newline = true;
>  }
>
>  /* Return the file cache that has been less used, recently, or the
> @@ -331,26 +370,26 @@ diagnostics_file_cache_forcibly_evict_file (const char *file_path)
>     *HIGHEST_USE_COUNT is set to the highest use count of the entries
>     in the cache table.  */
>
> -static fcache*
> -evicted_cache_tab_entry (unsigned *highest_use_count)
> +file_cache_slot*
> +file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
>  {
>    diagnostic_file_cache_init ();
>
> -  fcache *to_evict = &fcache_tab[0];
> -  unsigned huc = to_evict->use_count;
> -  for (unsigned i = 1; i < fcache_tab_size; ++i)
> +  file_cache_slot *to_evict = &m_file_slots[0];
> +  unsigned huc = to_evict->get_use_count ();
> +  for (unsigned i = 1; i < num_file_slots; ++i)
>      {
> -      fcache *c = &fcache_tab[i];
> -      bool c_is_empty = (c->file_path == NULL);
> +      file_cache_slot *c = &m_file_slots[i];
> +      bool c_is_empty = (c->get_file_path () == NULL);
>
> -      if (c->use_count < to_evict->use_count
> -         || (to_evict->file_path && c_is_empty))
> +      if (c->get_use_count () < to_evict->get_use_count ()
> +         || (to_evict->get_file_path () && c_is_empty))
>         /* We evict C because it's either an entry with a lower use
>            count or one that is empty.  */
>         to_evict = c;
>
> -      if (huc < c->use_count)
> -       huc = c->use_count;
> +      if (huc < c->get_use_count ())
> +       huc = c->get_use_count ();
>
>        if (c_is_empty)
>         /* We've reached the end of the cache; subsequent elements are
> @@ -368,10 +407,10 @@ evicted_cache_tab_entry (unsigned *highest_use_count)
>     accessed by caret diagnostic.  This cache is added to an array of
>     cache and can be retrieved by lookup_file_in_cache_tab.  This
>     function returns the created cache.  Note that only the last
> -   fcache_tab_size files are cached.  */
> +   num_file_slots files are cached.  */
>
> -static fcache*
> -add_file_to_cache_tab (const char *file_path)
> +file_cache_slot*
> +file_cache::add_file (const char *file_path)
>  {
>
>    FILE *fp = fopen (file_path, "r");
> @@ -379,22 +418,45 @@ add_file_to_cache_tab (const char *file_path)
>      return NULL;
>
>    unsigned highest_use_count = 0;
> -  fcache *r = evicted_cache_tab_entry (&highest_use_count);
> -  r->file_path = file_path;
> -  if (r->fp)
> -    fclose (r->fp);
> -  r->fp = fp;
> -  r->nb_read = 0;
> -  r->line_start_idx = 0;
> -  r->line_num = 0;
> -  r->line_record.truncate (0);
> +  file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count);
> +  r->create (file_path, fp, highest_use_count);
> +  return r;
> +}
> +
> +/* Populate this slot for use on FILE_PATH and FP, dropping any
> +   existing cached content within it.  */
> +
> +void
> +file_cache_slot::create (const char *file_path, FILE *fp,
> +                        unsigned highest_use_count)
> +{
> +  m_file_path = file_path;
> +  if (m_fp)
> +    fclose (m_fp);
> +  m_fp = fp;
> +  m_nb_read = 0;
> +  m_line_start_idx = 0;
> +  m_line_num = 0;
> +  m_line_record.truncate (0);
>    /* Ensure that this cache entry doesn't get evicted next time
>       add_file_to_cache_tab is called.  */
> -  r->use_count = ++highest_use_count;
> -  r->total_lines = total_lines_num (file_path);
> -  r->missing_trailing_newline = true;
> +  m_use_count = ++highest_use_count;
> +  m_total_lines = total_lines_num (file_path);
> +  m_missing_trailing_newline = true;
> +}
>
> -  return r;
> +/* file_cache's ctor.  */
> +
> +file_cache::file_cache ()
> +: m_file_slots (new file_cache_slot[num_file_slots])
> +{
> +}
> +
> +/* file_cache's dtor.  */
> +
> +file_cache::~file_cache ()
> +{
> +  delete[] m_file_slots;
>  }
>
>  /* Lookup the cache used for the content of a given file accessed by
> @@ -402,41 +464,41 @@ add_file_to_cache_tab (const char *file_path)
>     for this file, add it to the array of cached file and return
>     it.  */
>
> -static fcache*
> -lookup_or_add_file_to_cache_tab (const char *file_path)
> +file_cache_slot*
> +file_cache::lookup_or_add_file (const char *file_path)
>  {
> -  fcache *r = lookup_file_in_cache_tab (file_path);
> +  file_cache_slot *r = lookup_file (file_path);
>    if (r == NULL)
> -    r = add_file_to_cache_tab (file_path);
> +    r = add_file (file_path);
>    return r;
>  }
>
>  /* Default constructor for a cache of file used by caret
>     diagnostic.  */
>
> -fcache::fcache ()
> -: use_count (0), file_path (NULL), fp (NULL), data (0),
> -  size (0), nb_read (0), line_start_idx (0), line_num (0),
> -  total_lines (0), missing_trailing_newline (true)
> +file_cache_slot::file_cache_slot ()
> +: m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0),
> +  m_size (0), m_nb_read (0), m_line_start_idx (0), m_line_num (0),
> +  m_total_lines (0), m_missing_trailing_newline (true)
>  {
> -  line_record.create (0);
> +  m_line_record.create (0);
>  }
>
>  /* Destructor for a cache of file used by caret diagnostic.  */
>
> -fcache::~fcache ()
> +file_cache_slot::~file_cache_slot ()
>  {
> -  if (fp)
> +  if (m_fp)
>      {
> -      fclose (fp);
> -      fp = NULL;
> +      fclose (m_fp);
> +      m_fp = NULL;
>      }
> -  if (data)
> +  if (m_data)
>      {
> -      XDELETEVEC (data);
> -      data = 0;
> +      XDELETEVEC (m_data);
> +      m_data = 0;
>      }
> -  line_record.release ();
> +  m_line_record.release ();
>  }
>
>  /* Returns TRUE iff the cache would need to be filled with data coming
> @@ -444,55 +506,55 @@ fcache::~fcache ()
>     current line is empty.  Note that if the cache is full, it would
>     need to be extended and filled again.  */
>
> -static bool
> -needs_read (fcache *c)
> +bool
> +file_cache_slot::needs_read_p () const
>  {
> -  return (c->nb_read == 0
> -         || c->nb_read == c->size
> -         || (c->line_start_idx >= c->nb_read - 1));
> +  return (m_nb_read == 0
> +         || m_nb_read == m_size
> +         || (m_line_start_idx >= m_nb_read - 1));
>  }
>
>  /*  Return TRUE iff the cache is full and thus needs to be
>      extended.  */
>
> -static bool
> -needs_grow (fcache *c)
> +bool
> +file_cache_slot::needs_grow_p () const
>  {
> -  return c->nb_read == c->size;
> +  return m_nb_read == m_size;
>  }
>
>  /* Grow the cache if it needs to be extended.  */
>
> -static void
> -maybe_grow (fcache *c)
> +void
> +file_cache_slot::maybe_grow ()
>  {
> -  if (!needs_grow (c))
> +  if (!needs_grow_p ())
>      return;
>
> -  size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
> -  c->data = XRESIZEVEC (char, c->data, size);
> -  c->size = size;
> +  size_t size = m_size == 0 ? buffer_size : m_size * 2;
> +  m_data = XRESIZEVEC (char, m_data, size);
> +  m_size = size;
>  }
>
>  /*  Read more data into the cache.  Extends the cache if need be.
>      Returns TRUE iff new data could be read.  */
>
> -static bool
> -read_data (fcache *c)
> +bool
> +file_cache_slot::read_data ()
>  {
> -  if (feof (c->fp) || ferror (c->fp))
> +  if (feof (m_fp) || ferror (m_fp))
>      return false;
>
> -  maybe_grow (c);
> +  maybe_grow ();
>
> -  char * from = c->data + c->nb_read;
> -  size_t to_read = c->size - c->nb_read;
> -  size_t nb_read = fread (from, 1, to_read, c->fp);
> +  char * from = m_data + m_nb_read;
> +  size_t to_read = m_size - m_nb_read;
> +  size_t nb_read = fread (from, 1, to_read, m_fp);
>
> -  if (ferror (c->fp))
> +  if (ferror (m_fp))
>      return false;
>
> -  c->nb_read += nb_read;
> +  m_nb_read += nb_read;
>    return !!nb_read;
>  }
>
> @@ -500,12 +562,12 @@ read_data (fcache *c)
>     coming from the file FP.  Return TRUE iff the cache was filled with
>     mode data.  */
>
> -static bool
> -maybe_read_data (fcache *c)
> +bool
> +file_cache_slot::maybe_read_data ()
>  {
> -  if (!needs_read (c))
> +  if (!needs_read_p ())
>      return false;
> -  return read_data (c);
> +  return read_data ();
>  }
>
>  /* Read a new line from file FP, using C as a cache for the data
> @@ -518,18 +580,18 @@ maybe_read_data (fcache *c)
>     otherwise.  Note that subsequent calls to get_next_line might
>     make the content of *LINE invalid.  */
>
> -static bool
> -get_next_line (fcache *c, char **line, ssize_t *line_len)
> +bool
> +file_cache_slot::get_next_line (char **line, ssize_t *line_len)
>  {
>    /* Fill the cache with data to process.  */
> -  maybe_read_data (c);
> +  maybe_read_data ();
>
> -  size_t remaining_size = c->nb_read - c->line_start_idx;
> +  size_t remaining_size = m_nb_read - m_line_start_idx;
>    if (remaining_size == 0)
>      /* There is no more data to process.  */
>      return false;
>
> -  char *line_start = c->data + c->line_start_idx;
> +  char *line_start = m_data + m_line_start_idx;
>
>    char *next_line_start = NULL;
>    size_t len = 0;
> @@ -539,10 +601,10 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
>        /* We haven't found the end-of-line delimiter in the cache.
>          Fill the cache with more data from the file and look for the
>          '\n'.  */
> -      while (maybe_read_data (c))
> +      while (maybe_read_data ())
>         {
> -         line_start = c->data + c->line_start_idx;
> -         remaining_size = c->nb_read - c->line_start_idx;
> +         line_start = m_data + m_line_start_idx;
> +         remaining_size = m_nb_read - m_line_start_idx;
>           line_end = (char *) memchr (line_start, '\n', remaining_size);
>           if (line_end != NULL)
>             {
> @@ -558,19 +620,19 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
>              of when the line ends up with a '\n' and line_end points to
>              that terminal '\n'.  That consistency is useful below in
>              the len calculation.  */
> -         line_end = c->data + c->nb_read ;
> -         c->missing_trailing_newline = true;
> +         line_end = m_data + m_nb_read ;
> +         m_missing_trailing_newline = true;
>         }
>        else
> -       c->missing_trailing_newline = false;
> +       m_missing_trailing_newline = false;
>      }
>    else
>      {
>        next_line_start = line_end + 1;
> -      c->missing_trailing_newline = false;
> +      m_missing_trailing_newline = false;
>      }
>
> -  if (ferror (c->fp))
> +  if (ferror (m_fp))
>      return false;
>
>    /* At this point, we've found the end of the of line.  It either
> @@ -580,54 +642,56 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
>
>    len = line_end - line_start;
>
> -  if (c->line_start_idx < c->nb_read)
> +  if (m_line_start_idx < m_nb_read)
>      *line = line_start;
>
> -  ++c->line_num;
> +  ++m_line_num;
>
>    /* Before we update our line record, make sure the hint about the
>       total number of lines of the file is correct.  If it's not, then
>       we give up recording line boundaries from now on.  */
>    bool update_line_record = true;
> -  if (c->line_num > c->total_lines)
> +  if (m_line_num > m_total_lines)
>      update_line_record = false;
>
>      /* Now update our line record so that re-reading lines from the
> -     before c->line_start_idx is faster.  */
> +     before m_line_start_idx is faster.  */
>    if (update_line_record
> -      && c->line_record.length () < fcache_line_record_size)
> +      && m_line_record.length () < line_record_size)
>      {
>        /* If the file lines fits in the line record, we just record all
>          its lines ...*/
> -      if (c->total_lines <= fcache_line_record_size
> -         && c->line_num > c->line_record.length ())
> -       c->line_record.safe_push (fcache::line_info (c->line_num,
> -                                                c->line_start_idx,
> -                                                line_end - c->data));
> -      else if (c->total_lines > fcache_line_record_size)
> +      if (m_total_lines <= line_record_size
> +         && m_line_num > m_line_record.length ())
> +       m_line_record.safe_push
> +         (file_cache_slot::line_info (m_line_num,
> +                                      m_line_start_idx,
> +                                      line_end - m_data));
> +      else if (m_total_lines > line_record_size)
>         {
>           /* ... otherwise, we just scale total_lines down to
> -            (fcache_line_record_size lines.  */
> -         size_t n = (c->line_num * fcache_line_record_size) / c->total_lines;
> -         if (c->line_record.length () == 0
> -             || n >= c->line_record.length ())
> -           c->line_record.safe_push (fcache::line_info (c->line_num,
> -                                                    c->line_start_idx,
> -                                                    line_end - c->data));
> +            (line_record_size lines.  */
> +         size_t n = (m_line_num * line_record_size) / m_total_lines;
> +         if (m_line_record.length () == 0
> +             || n >= m_line_record.length ())
> +           m_line_record.safe_push
> +             (file_cache_slot::line_info (m_line_num,
> +                                          m_line_start_idx,
> +                                          line_end - m_data));
>         }
>      }
>
> -  /* Update c->line_start_idx so that it points to the next line to be
> +  /* Update m_line_start_idx so that it points to the next line to be
>       read.  */
>    if (next_line_start)
> -    c->line_start_idx = next_line_start - c->data;
> +    m_line_start_idx = next_line_start - m_data;
>    else
>      /* We didn't find any terminal '\n'.  Let's consider that the end
>         of line is the end of the data in the cache.  The next
>         invocation of get_next_line will either read more data from the
>         underlying file or return false early because we've reached the
>         end of the file.  */
> -    c->line_start_idx = c->nb_read;
> +    m_line_start_idx = m_nb_read;
>
>    *line_len = len;
>
> @@ -640,13 +704,13 @@ get_next_line (fcache *c, char **line, ssize_t *line_len)
>     copying from the cache involved.  Return TRUE upon successful
>     completion.  */
>
> -static bool
> -goto_next_line (fcache *cache)
> +bool
> +file_cache_slot::goto_next_line ()
>  {
>    char *l;
>    ssize_t len;
>
> -  return get_next_line (cache, &l, &len);
> +  return get_next_line (&l, &len);
>  }
>
>  /* Read an arbitrary line number LINE_NUM from the file cached in C.
> @@ -656,54 +720,54 @@ goto_next_line (fcache *cache)
>     *LINE is only valid until the next call of read_line_num.
>     This function returns bool if a line was read.  */
>
> -static bool
> -read_line_num (fcache *c, size_t line_num,
> -              char **line, ssize_t *line_len)
> +bool
> +file_cache_slot::read_line_num (size_t line_num,
> +                      char ** line, ssize_t *line_len)
>  {
>    gcc_assert (line_num > 0);
>
> -  if (line_num <= c->line_num)
> +  if (line_num <= m_line_num)
>      {
> -      /* We've been asked to read lines that are before c->line_num.
> +      /* We've been asked to read lines that are before m_line_num.
>          So lets use our line record (if it's not empty) to try to
>          avoid re-reading the file from the beginning again.  */
>
> -      if (c->line_record.is_empty ())
> +      if (m_line_record.is_empty ())
>         {
> -         c->line_start_idx = 0;
> -         c->line_num = 0;
> +         m_line_start_idx = 0;
> +         m_line_num = 0;
>         }
>        else
>         {
> -         fcache::line_info *i = NULL;
> -         if (c->total_lines <= fcache_line_record_size)
> +         file_cache_slot::line_info *i = NULL;
> +         if (m_total_lines <= line_record_size)
>             {
>               /* In languages where the input file is not totally
> -                preprocessed up front, the c->total_lines hint
> +                preprocessed up front, the m_total_lines hint
>                  can be smaller than the number of lines of the
>                  file.  In that case, only the first
> -                c->total_lines have been recorded.
> +                m_total_lines have been recorded.
>
> -                Otherwise, the first c->total_lines we've read have
> +                Otherwise, the first m_total_lines we've read have
>                  their start/end recorded here.  */
> -             i = (line_num <= c->total_lines)
> -               ? &c->line_record[line_num - 1]
> -               : &c->line_record[c->total_lines - 1];
> +             i = (line_num <= m_total_lines)
> +               ? &m_line_record[line_num - 1]
> +               : &m_line_record[m_total_lines - 1];
>               gcc_assert (i->line_num <= line_num);
>             }
>           else
>             {
>               /*  So the file had more lines than our line record
>                   size.  Thus the number of lines we've recorded has
> -                 been scaled down to fcache_line_reacord_size.  Let's
> +                 been scaled down to line_record_size.  Let's
>                   pick the start/end of the recorded line that is
>                   closest to line_num.  */
> -             size_t n = (line_num <= c->total_lines)
> -               ? line_num * fcache_line_record_size / c->total_lines
> -               : c ->line_record.length () - 1;
> -             if (n < c->line_record.length ())
> +             size_t n = (line_num <= m_total_lines)
> +               ? line_num * line_record_size / m_total_lines
> +               : m_line_record.length () - 1;
> +             if (n < m_line_record.length ())
>                 {
> -                 i = &c->line_record[n];
> +                 i = &m_line_record[n];
>                   gcc_assert (i->line_num <= line_num);
>                 }
>             }
> @@ -711,33 +775,33 @@ read_line_num (fcache *c, size_t line_num,
>           if (i && i->line_num == line_num)
>             {
>               /* We have the start/end of the line.  */
> -             *line = c->data + i->start_pos;
> +             *line = m_data + i->start_pos;
>               *line_len = i->end_pos - i->start_pos;
>               return true;
>             }
>
>           if (i)
>             {
> -             c->line_start_idx = i->start_pos;
> -             c->line_num = i->line_num - 1;
> +             m_line_start_idx = i->start_pos;
> +             m_line_num = i->line_num - 1;
>             }
>           else
>             {
> -             c->line_start_idx = 0;
> -             c->line_num = 0;
> +             m_line_start_idx = 0;
> +             m_line_num = 0;
>             }
>         }
>      }
>
> -  /*  Let's walk from line c->line_num up to line_num - 1, without
> +  /*  Let's walk from line m_line_num up to line_num - 1, without
>        copying any line.  */
> -  while (c->line_num < line_num - 1)
> -    if (!goto_next_line (c))
> +  while (m_line_num < line_num - 1)
> +    if (!goto_next_line ())
>        return false;
>
>    /* The line we want is the next one.  Let's read and copy it back to
>       the caller.  */
> -  return get_next_line (c, line, line_len);
> +  return get_next_line (line, line_len);
>  }
>
>  /* Return the physical source line that corresponds to FILE_PATH/LINE.
> @@ -756,11 +820,16 @@ location_get_source_line (const char *file_path, int line)
>    if (line == 0)
>      return char_span (NULL, 0);
>
> -  fcache *c = lookup_or_add_file_to_cache_tab (file_path);
> +  if (file_path == NULL)
> +    return char_span (NULL, 0);
> +
> +  diagnostic_file_cache_init ();
> +
> +  file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
>    if (c == NULL)
>      return char_span (NULL, 0);
>
> -  bool read = read_line_num (c, line, &buffer, &len);
> +  bool read = c->read_line_num (line, &buffer, &len);
>    if (!read)
>      return char_span (NULL, 0);
>
> @@ -774,11 +843,13 @@ location_get_source_line (const char *file_path, int line)
>  bool
>  location_missing_trailing_newline (const char *file_path)
>  {
> -  fcache *c = lookup_or_add_file_to_cache_tab (file_path);
> +  diagnostic_file_cache_init ();
> +
> +  file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
>    if (c == NULL)
>      return false;
>
> -  return c->missing_trailing_newline;
> +  return c->missing_trailing_newline_p ();
>  }
>
>  /* Test if the location originates from the spelling location of a
> diff --git a/gcc/input.h b/gcc/input.h
> index f1ef5d76cfd..bbcec84c521 100644
> --- a/gcc/input.h
> +++ b/gcc/input.h
> @@ -88,6 +88,39 @@ class char_span
>  extern char_span location_get_source_line (const char *file_path, int line);
>
>  extern bool location_missing_trailing_newline (const char *file_path);
> +
> +/* Forward decl of slot within file_cache, so that the definition doesn't
> +   need to be in this header.  */
> +class file_cache_slot;
> +
> +/* A cache of source files for use when emitting diagnostics
> +   (and in a few places in the C/C++ frontends).
> +
> +   Results are only valid until the next call to the cache, as
> +   slots can be evicted.
> +
> +   Filenames are stored by pointer, and so must outlive the cache
> +   instance.  */
> +
> +class file_cache
> +{
> + public:
> +  file_cache ();
> +  ~file_cache ();
> +
> +  file_cache_slot *lookup_or_add_file (const char *file_path);
> +  void forcibly_evict_file (const char *file_path);
> +
> + private:
> +  file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
> +  file_cache_slot *add_file (const char *file_path);
> +  file_cache_slot *lookup_file (const char *file_path);
> +
> + private:
> +  static const size_t num_file_slots = 16;
> +  file_cache_slot *m_file_slots;
> +};
> +
>  extern expanded_location
>  expand_location_to_spelling_point (location_t,
>                                    enum location_aspect aspect
> --
> 2.26.3
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [committed] input.c: move file caching globals to a new file_cache class
  2021-07-11 16:58               ` Lewis Hyatt
@ 2021-07-14 22:53                 ` David Malcolm
  0 siblings, 0 replies; 25+ messages in thread
From: David Malcolm @ 2021-07-14 22:53 UTC (permalink / raw)
  To: Lewis Hyatt; +Cc: gcc-patches

On Sun, 2021-07-11 at 12:58 -0400, Lewis Hyatt wrote:
> Hi David-
> 
> I thought this might be a good opportunity to ask about the patch
> that
> supports -finput-charset in diagnostic.c please?
> https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564527.html
> 
> The patch will require some work to adapt to the new changes below. 

Sorry about that, I forgot about your patch.

> I
> am happy to do that, but thought I should check first whether you
> have
> any interest in this approach? Thanks!

The basic approach seems good to me, so please do update the patch and
resend it.

Dave


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2021-07-14 22:53 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-30  5:35 [PATCH 1/4] add utility to poison globals that should not be used Trevor Saunders
2021-06-30  5:35 ` [PATCH 2/4] allow poisoning input_location in ranges it " Trevor Saunders
2021-06-30  9:00   ` Richard Biener
2021-06-30 12:33     ` Trevor Saunders
2021-06-30 19:09       ` Richard Biener
2021-07-01 10:23         ` Trevor Saunders
2021-07-01 12:48           ` Richard Biener
2021-06-30 15:13   ` David Malcolm
2021-06-30 19:34     ` Jason Merrill
2021-07-01 10:16     ` Trevor Saunders
2021-07-01 12:53       ` Richard Biener
2021-07-01 15:40         ` David Malcolm
2021-07-01 16:04           ` David Malcolm
2021-07-01 21:51             ` [committed] input.c: move file caching globals to a new file_cache class David Malcolm
2021-07-11 16:58               ` Lewis Hyatt
2021-07-14 22:53                 ` David Malcolm
2021-07-02  0:44           ` [PATCH 2/4] allow poisoning input_location in ranges it should not be used Trevor Saunders
2021-07-02 15:46       ` Jason Merrill
2021-07-02 23:23         ` Trevor Saunders
2021-07-02 19:20   ` Martin Sebor
2021-07-02 23:47     ` Trevor Saunders
2021-07-06 20:53       ` Martin Sebor
2021-06-30  5:35 ` [PATCH 3/4] allow poisoning cfun Trevor Saunders
2021-06-30  5:35 ` [PATCH 4/4] poison input_location and cfun in one spot Trevor Saunders
2021-06-30  9:02   ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).