On Mon, 2018-01-08 at 19:08 +0100, Jakub Jelinek wrote:
> On Mon, Jan 08, 2018 at 01:02:37PM -0500, David Malcolm wrote:
> > Thanks Nathan and Jakub: a quick smoketest using TREE_LANG_FLAG_0
> > worked, and fixes this issue.
> > 
> > However, should I be using a TREE_LANG_FLAG for something that's in
> > tree.h/c, rather than just in the "cp" subdir?  (the wrapper nodes
> > are
> > only added to C++ in this patch kit, but given that e.g. STRIP_NOPS
> > needs to remove them, the lang-independent code needs to handle
> > them,
> > and ultimately we may want wrapper nodes in other FEs).
> 
> If location_wrapper_p etc. are in generic code rather than only in
> the FE,
> sure, you'd need to use some generic flag rather than FE specific.
> I bet e.g. private_flag and protected_flag aren't used yet for
> VIEW_CONVERT_EXPR/NON_LVALUE_EXPR, but they are used on some other
> expressions, e.g. CALL_EXPR, which suggests that it could be used for
> that.
> 
>       Jakub

Thanks.  "public_flag" seemed to be available for those codes, so I
used that, via a new EXPR_LOCATION_WRAPPER_P macro

Here's an updated version of patch 2 of the kit to do so [1].

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.
Also, manually tested with "make s-selftest-c++" (since we don't run
the selftests for cc1plus by default).

OK for trunk in conjunction with the rest of the kit?  (I'm
about to post an updated version of the [03/14] patch, which is
the only other part of the kit still needing review).

Dave

[1] (it also merges in the part of patch [08/14] for making wrappers
for STRING_CST use VIEW_CONVERT_EXPR, which Jason has already approved;
needs to be here to avoid git conflicts; all of this will be one
squashed patch if/when committed).

Blurb follows:

Changed in v2.4:
* use a flag rather than types for indicating location_wrapper_p (to
cope with decls changing type from under us)
* add the STRING_CST part of the [08/14] lvalue_kind patch

Changed in v2.3:
* move most of location_wrapper_p's comment inside the function
(approved by Jason here:
   https://gcc.gnu.org/ml/gcc-patches/2017-11/msg02618.html )

Changed in v2.2:
* added tree_strip_any_location_wrapper
* removed checking for !CONSTANT_CLASS_P on VIEW_CONVERT_EXPR

Changed in v2.1:
* updated comments for location_wrapper_p and
maybe_wrap_with_location
* added selftests

This patch provides a mechanism in tree.c for adding a wrapper node
for expressing a location_t, for those nodes for which
!CAN_HAVE_LOCATION_P.  It's called in later patches in the kit via a
new method of cp_expr.

In this version of the patch, I use NON_LVALUE_EXPR for wrapping
constants, and VIEW_CONVERT_EXPR for other nodes.

I also turned off wrapper nodes for EXCEPTIONAL_CLASS_P, for the sake
of keeping the patch kit more minimal.

The patch also adds a STRIP_ANY_LOCATION_WRAPPER macro for stripping
such nodes, used later on in the patch kit.

gcc/cp/ChangeLog:
        PR c++/43486
        * cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.

gcc/ChangeLog:
        PR c++/43486
        * tree-core.h: Document EXPR_LOCATION_WRAPPER_P's usage of
        "public_flag".
        * tree.c (maybe_wrap_with_location): New function.
        (selftest::test_location_wrappers): New function.
        (selftest::tree_c_tests): Call it.
        * tree.h (STRIP_ANY_LOCATION_WRAPPER): New macro.
        (maybe_wrap_with_location): New decl.
        (EXPR_LOCATION_WRAPPER_P): New macro.
        (location_wrapper_p): New inline function.
        (tree_strip_any_location_wrapper): New inline function.
---
 gcc/cp/cp-tree.h |  6 ++++
 gcc/tree-core.h  |  3 ++
 gcc/tree.c       | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/tree.h       | 47 ++++++++++++++++++++++++++++++++
 4 files changed, 139 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d408370..d4b45a4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -93,6 +93,12 @@ public:
     set_location (make_location (m_loc, start, finish));
   }
 
+  cp_expr& maybe_add_location_wrapper ()
+  {
+    m_value = maybe_wrap_with_location (m_value, m_loc);
+    return *this;
+  }
+
  private:
   tree m_value;
   location_t m_loc;
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index b08d215..b127bc7 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1116,6 +1116,9 @@ struct GTY(()) tree_base {
        SSA_NAME_IS_VIRTUAL_OPERAND in
           SSA_NAME
 
+       EXPR_LOCATION_WRAPPER_P in
+          NON_LVALUE_EXPR, VIEW_CONVERT_EXPR
+
    private_flag:
 
        TREE_PRIVATE in
diff --git a/gcc/tree.c b/gcc/tree.c
index aa647de..8b1c4b2 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -14066,6 +14066,40 @@ set_source_range (tree expr, source_range src_range)
   return adhoc;
 }
 
+/* Return EXPR, potentially wrapped with a node expression LOC,
+   if !CAN_HAVE_LOCATION_P (expr).
+
+   NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
+   VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.
+
+   Wrapper nodes can be identified using location_wrapper_p.  */
+
+tree
+maybe_wrap_with_location (tree expr, location_t loc)
+{
+  if (expr == NULL)
+    return NULL;
+  if (loc == UNKNOWN_LOCATION)
+    return expr;
+  if (CAN_HAVE_LOCATION_P (expr))
+    return expr;
+  /* We should only be adding wrappers for constants and for decls,
+     or for some exceptional tree nodes (e.g. BASELINK in the C++ FE).  */
+  gcc_assert (CONSTANT_CLASS_P (expr)
+             || DECL_P (expr)
+             || EXCEPTIONAL_CLASS_P (expr));
+
+  if (EXCEPTIONAL_CLASS_P (expr))
+    return expr;
+
+  tree_code code = (CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST
+                   ? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR);
+  tree wrapper = build1_loc (loc, code, TREE_TYPE (expr), expr);
+  /* Mark this node as being a wrapper.  */
+  EXPR_LOCATION_WRAPPER_P (wrapper) = 1;
+  return wrapper;
+}
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
@@ -14436,6 +14470,54 @@ test_vector_cst_patterns ()
   check_vector_cst_fill (elements, build_vector (vector_type, elements), 4);
 }
 
+/* Verify location wrappers.  */
+
+static void
+test_location_wrappers ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Wrapping a constant.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_cst));
+  ASSERT_FALSE (location_wrapper_p (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_cst));
+  ASSERT_EQ (int_cst, tree_strip_any_location_wrapper (wrapped_int_cst));
+
+  /* Wrapping a STRING_CST.  */
+  tree string_cst = build_string (4, "foo");
+  ASSERT_FALSE (CAN_HAVE_LOCATION_P (string_cst));
+  ASSERT_FALSE (location_wrapper_p (string_cst));
+
+  tree wrapped_string_cst = maybe_wrap_with_location (string_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_cst));
+  ASSERT_EQ (VIEW_CONVERT_EXPR, TREE_CODE (wrapped_string_cst));
+  ASSERT_EQ (loc, EXPR_LOCATION (wrapped_string_cst));
+  ASSERT_EQ (string_cst, tree_strip_any_location_wrapper (wrapped_string_cst));
+
+
+  /* Wrapping a variable.  */
+  tree int_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                            get_identifier ("some_int_var"),
+                            integer_type_node);
+  ASSERT_FALSE (CAN_HAVE_LOCATION_P (int_var));
+  ASSERT_FALSE (location_wrapper_p (int_var));
+
+  tree wrapped_int_var = maybe_wrap_with_location (int_var, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_var));
+  ASSERT_EQ (loc, EXPR_LOCATION (wrapped_int_var));
+  ASSERT_EQ (int_var, tree_strip_any_location_wrapper (wrapped_int_var));
+
+  /* Verify that "reinterpret_cast<int>(some_int_var)" is not a location
+     wrapper.  */
+  tree r_cast = build1 (NON_LVALUE_EXPR, integer_type_node, int_var);
+  ASSERT_FALSE (location_wrapper_p (r_cast));
+  ASSERT_EQ (r_cast, tree_strip_any_location_wrapper (r_cast));
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -14445,6 +14527,7 @@ tree_c_tests ()
   test_identifiers ();
   test_labels ();
   test_vector_cst_patterns ();
+  test_location_wrappers ();
 }
 
 } // namespace selftest
diff --git a/gcc/tree.h b/gcc/tree.h
index aedd48d..f347b13 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -483,6 +483,12 @@ extern void omp_clause_range_check_failed (const_tree, 
const char *, int,
 #define STRIP_USELESS_TYPE_CONVERSION(EXP) \
   (EXP) = tree_ssa_strip_useless_type_conversions (EXP)
 
+/* Remove any VIEW_CONVERT_EXPR or NON_LVALUE_EXPR that's purely
+   in use to provide a location_t.  */
+
+#define STRIP_ANY_LOCATION_WRAPPER(EXP) \
+  (EXP) = tree_strip_any_location_wrapper (CONST_CAST_TREE (EXP))
+
 /* Nonzero if TYPE represents a vector type.  */
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
@@ -1180,6 +1186,8 @@ get_expr_source_range (tree expr)
 
 extern void protected_set_expr_location (tree, location_t);
 
+extern tree maybe_wrap_with_location (tree, location_t);
+
 /* In a TARGET_EXPR node.  */
 #define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
 #define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 
1)
@@ -3677,6 +3685,45 @@ id_equal (const char *str, const_tree id)
   return !strcmp (str, IDENTIFIER_POINTER (id));
 }
 
+/* In NON_LVALUE_EXPR and VIEW_CONVERT_EXPR, set when this node is merely a
+   wrapper added to express a location_t on behalf of the node's child
+   (e.g. by maybe_wrap_with_location).  */
+
+#define EXPR_LOCATION_WRAPPER_P(NODE) \
+  (TREE_CHECK2(NODE, NON_LVALUE_EXPR, VIEW_CONVERT_EXPR)->base.public_flag)
+
+/* Test if EXP is merely a wrapper node, added to express a location_t
+   on behalf of the node's child (e.g. by maybe_wrap_with_location).  */
+
+inline bool
+location_wrapper_p (const_tree exp)
+{
+  /* A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and
+     the flag EXPR_LOCATION_WRAPPER_P is set.
+     It normally has the same type as its operand, but it can have a
+     different one if the type of the operand has changed (e.g. when
+     merging duplicate decls).
+
+     NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
+     VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.  */
+  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
+       || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
+      && EXPR_LOCATION_WRAPPER_P (exp))
+    return true;
+  return false;
+}
+
+/* Implementation of STRIP_ANY_LOCATION_WRAPPER.  */
+
+inline tree
+tree_strip_any_location_wrapper (tree exp)
+{
+  if (location_wrapper_p (exp))
+    return TREE_OPERAND (exp, 0);
+  else
+    return exp;
+}
+
 #define error_mark_node                        global_trees[TI_ERROR_MARK]
 
 #define intQI_type_node                        global_trees[TI_INTQI_TYPE]
-- 
1.8.5.3

Reply via email to