public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486)
@ 2017-10-20 22:38 David Malcolm
  2017-10-24 14:05 ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-10-20 22:38 UTC (permalink / raw)
  To: Jason Merrill, Nathan Sidwell, Jakub Jelinek, Richard Biener,
	gcc-patches
  Cc: David Malcolm

[following up on a discussion at Cauldron]

This is a work-in-progress attempt at retaining source-location
information for uses of variables and for constants: the tree nodes
that don't have an EXPR_LOCATION in our internal representation.

I'm posting the patch now to check that my approach is correct and
get feedback.  It adds new "wrapper" tree nodes around the nodes
that don't have a location_t, effectively decorating them with a
location_t.

The patch doesn't yet bootstrap, and fails many tests, but it does fix
the missing location information, so that e.g.:

  test.cc:5:38: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
     return callee (first, second, third);
                                        ^

becomes:

  test.cc:5:25: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
     return callee (first, second, third);
                           ^~~~~~

for a mismatching type in a function call involving a variable or constant.

The case of a compound expression already works for this case e.g.:

     return callee (first, second * 2, third);
                           ~~~~~~~^~~

These cases are already handled within the C frontend by the
vec<location_t> that's passed around for callsites.

FWIW I posted a patch to add a vec<location_t> to the C++ frontend:
  "[PATCH] C++: use an optional vec<location_t> for callsites"
    https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
which fixes the cases above, but Jason requested at Cauldron that I pursue
the wrapper node approach (as the vec<location_t> is kind of a workaround)
so here's what I have so far.

Limitations:

* The patch as-is preserves the locations during the frontend, and hence
  solves various issues with diagnostics in the frontend, but the
  locations are discarded during gimplification.  PR 43486 requests
  preserving them into gimple, so although this approach would help with
  that PR, it doesn't fully address it.  I'm happy to defer the
  gimplification issue until after GCC 8.

* To simplify things, the patch only touches the C++ frontend.  Similar
  things would need to happen in the C frontend (and presumably others,
  but I care most about C and C++).

* As noted above, it doesn't yet bootstrap, and introduces various test
  regressions; obviously I'd fix all that assuming the direction of the
  patch is acceptable (folding appears to be the main issue: various
  places in the code expect the result of folding to be a decl, and
  go wrong if they see a wrapper node instead, but we still want the
  location information after folding).

Design questions:

* The patch introduces a new kind of tree node, currently called
  DECL_WRAPPER_EXPR (although it's used for wrapping constants as well
  as decls).  Should wrappers be a new kind of tree node, or should they
  reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR, etc).
    * NOP_EXPR: seems to be for use as an rvalue
    * CONVERT_EXPR: for type conversions
    * NON_LVALUE_EXPR: "Value is same as argument, but guaranteed not an
      lvalue"
      * but we *do* want to support lvalues here
    * VIEW_CONVERT_EXPR: viewing one thing as of a different type
      * can it support lvalues?
    * C_MAYBE_CONST_EXPR perhaps (generalized somehow)
  Any suggestions or guidance here?

Memory usage stats:

I tried running this on a non-trivial C++ file ("kdecore.cc" [1]),
but it doesn't yet work well enough to compile it.  So I hacked it
up like this:

   diff --git a/gcc/tree.c b/gcc/tree.c
   index 270e680..5711b2a 100644
   --- a/gcc/tree.c
   +++ b/gcc/tree.c
   @@ -13764,7 +13764,15 @@ maybe_wrap_with_location (tree expr, location_t loc)
      gcc_assert (CONSTANT_CLASS_P (expr)
                 || DECL_P (expr)
                 || EXCEPTIONAL_CLASS_P (expr));
   +
   +#if 0
      return build1_loc (loc, DECL_USAGE_EXPR, TREE_TYPE (expr), expr);
   +#else
   +  /* Simulate the GGC-effect of building the node... */
   +  (void)build1_loc (loc, DECL_USAGE_EXPR, TREE_TYPE (expr), expr);
   +  /* But don't actually do it.  */
   +  return expr;
   +#endif
    }

    /* Return the name of combined function FN, for debugging purposes.  */

to simulate the effect of allocating the wrapper nodes, without actually
using those nodes.

With that, -ftime-report's memory stats for "TOTAL" went
from 615999 kB to 617773 kB
i.e. about a 0.3% increase in overall GC-managed allocations.

I don't have reliable timing information yet.

Thoughts?

Thanks
Dave

[1] https://github.com/davidmalcolm/gcc-build/blob/master/kdecore.cc

gcc/ChangeLog:
	PR c++/43486
	* builtins.c (fold_builtin_next_arg): Strip off any
	DECL_USAGE_EXPR.
	* gimplify.c (gimplify_expr): Handle DECL_USAGE_EXPR.
	* tree.c (maybe_wrap_with_location): New function.
	* tree.def (DECL_USAGE_EXPR): New tree code.
	* tree.h (STRIP_DECL_USAGE_EXPR): New macro.
	(maybe_wrap_with_location): New decl.

gcc/c-family/ChangeLog:
	PR c++/43486
	* c-format.c (check_format_arg): Strip of any DECL_USAGE_EXPR.
	* c-pretty-print.c (c_pretty_printer::expression): Handle
	DECL_USAGE_EXPR.

gcc/cp/ChangeLog:
	PR c++/43486
	* constexpr.c (cxx_eval_constant_expression): Handle
	DECL_USAGE_EXPR.
	(cxx_eval_outermost_constant_expr): Use STRIP_DECL_USAGE_EXPR.
	(potential_constant_expression_1): Handle DECL_USAGE_EXPR.
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
	* error.c (dump_expr): Handle DECL_USAGE_EXPR.
	* expr.c (mark_exp_read): Likewise.
	* parser.c (cp_parser_primary_expression): Call
	maybe_add_location_wrapper on the result for literals.
	(cp_parser_postfix_expression): Likewise for RID_TYPEID.
	(cp_parser_unary_expression): Likewise for RID_ALIGNOF and
	RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.
	* semantics.c (finish_call_expr): Use STRIP_DECL_USAGE_EXPR.
	(finish_id_expression): Rename to...
	(finish_id_expression_1): ...this.
	(finish_id_expression): Reintroduce, calling the above, and
	calling maybe_add_location_wrapper on the result.
	* tree.c (lvalue_kind): Use STRIP_DECL_USAGE_EXPR.
	* typeck.c (cp_build_function_call_vec): Likewise.
	(build_address): Use the EXPR_LOCATION when building the
	ADDR_EXPR.

gcc/testsuite/ChangeLog:
	PR c++/43486
	* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
	to reflect that the arguments are correctly underlined.
	* g++.dg/plugin/diagnostic-test-expressions-1.C: Add test coverage
	for globals, params, locals and literals.
	(test_sizeof): Directly test the location of "sizeof", rather than
	when used in compound expressions.
	(test_alignof): Likewise for "alignof".
	(test_string_literals): Likewise for string literals.
	(test_numeric_literals): Likewise for numeric literals.
	(test_builtin_offsetof): Likewise for "__builtin_offsetof".
	(test_typeid): Likewise for typeid.
	(test_unary_plus): New.
	* gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
	(cb_walk_tree_fn): Handle DECL_USAGE_EXPR.
---
 gcc/builtins.c                                     |   3 +-
 gcc/c-family/c-format.c                            |   3 +
 gcc/c-family/c-pretty-print.c                      |   1 +
 gcc/cp/constexpr.c                                 |   4 +
 gcc/cp/cp-tree.h                                   |   6 +
 gcc/cp/error.c                                     |   1 +
 gcc/cp/expr.c                                      |   1 +
 gcc/cp/parser.c                                    |  15 +-
 gcc/cp/semantics.c                                 |  60 +++--
 gcc/cp/tree.c                                      |   2 +
 gcc/cp/typeck.c                                    |   4 +-
 gcc/gimplify.c                                     |   3 +
 .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
 .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260 +++++++++++++--------
 .../diagnostic_plugin_test_tree_expression_range.c |   2 +
 gcc/tree.c                                         |  20 ++
 gcc/tree.def                                       |   3 +
 gcc/tree.h                                         |  10 +
 18 files changed, 288 insertions(+), 137 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index d3498bb..5398df4 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -9566,7 +9566,8 @@ fold_builtin_next_arg (tree exp, bool va_start_p)
 	 We must also strip off INDIRECT_EXPR for C++ reference
 	 parameters.  */
       while (CONVERT_EXPR_P (arg)
-	     || TREE_CODE (arg) == INDIRECT_REF)
+	     || TREE_CODE (arg) == INDIRECT_REF
+	     || TREE_CODE (arg) == DECL_USAGE_EXPR)
 	arg = TREE_OPERAND (arg, 0);
       if (arg != last_parm)
 	{
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 164d035..ae07201 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,6 +1536,9 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
+  if (TREE_CODE (format_tree) == DECL_USAGE_EXPR)
+    format_tree = TREE_OPERAND (format_tree, 0);
+
   if (VAR_P (format_tree))
     {
       /* Pull out a constant value if the front end didn't.  */
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 0f48b9e..c4a7d2c 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -2311,6 +2311,7 @@ c_pretty_printer::expression (tree e)
 
     case NON_LVALUE_EXPR:
     case SAVE_EXPR:
+    case DECL_USAGE_EXPR:
       expression (TREE_OPERAND (e, 0));
       break;
 
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5919282..7551f17 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4423,6 +4423,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 				       non_constant_p, overflow_p);
       break;
 
+    case DECL_USAGE_EXPR:
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
     case NOP_EXPR:
@@ -4697,6 +4698,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
   r = cxx_eval_constant_expression (&ctx, r,
 				    false, &non_constant_p, &overflow_p);
 
+  STRIP_DECL_USAGE_EXPR (r);
+
   verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
 
   /* Mutable logic is a bit tricky: we want to allow initialization of
@@ -5290,6 +5293,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
         }
       return true;
 
+    case DECL_USAGE_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b74b6d9..254999a 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/cp/error.c b/gcc/cp/error.c
index 7a98d2e..e78f7d9 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2424,6 +2424,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
       break;
 
     CASE_CONVERT:
+    case DECL_USAGE_EXPR:
     case IMPLICIT_CONV_EXPR:
     case VIEW_CONVERT_EXPR:
       {
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 23e30cf..ce900a3 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -277,6 +277,7 @@ mark_exp_read (tree exp)
     case MODIFY_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
+    case DECL_USAGE_EXPR:
     CASE_CONVERT:
     case ADDR_EXPR:
     case INDIRECT_REF:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2337be5..ffe2605 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5065,7 +5065,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  if (!cast_p)
 	    cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
 	}
-      return cp_expr (token->u.value, token->location);
+      return (cp_expr (token->u.value, token->location)
+	      .maybe_add_location_wrapper ());
 
     case CPP_CHAR_USERDEF:
     case CPP_CHAR16_USERDEF:
@@ -5087,9 +5088,10 @@ cp_parser_primary_expression (cp_parser *parser,
       /* ??? Should wide strings be allowed when parser->translate_strings_p
 	 is false (i.e. in attributes)?  If not, we can kill the third
 	 argument to cp_parser_string_literal.  */
-      return cp_parser_string_literal (parser,
-				       parser->translate_strings_p,
-				       true);
+      return (cp_parser_string_literal (parser,
+					parser->translate_strings_p,
+					true)
+	      .maybe_add_location_wrapper ());
 
     case CPP_OPEN_PAREN:
       /* If we see `( { ' then we are looking at the beginning of
@@ -6776,6 +6778,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -8107,7 +8110,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
-	    return ret_expr;
+	    return ret_expr.maybe_add_location_wrapper ();
 	  }
 
 	case RID_NEW:
@@ -9933,7 +9936,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
-  return expr;
+  return expr.maybe_add_location_wrapper ();
 }
 
 /* Parse a trait expression.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a512664..2737776 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2324,6 +2324,10 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
      it so that we can tell this is a call to a known function.  */
   fn = maybe_undo_parenthesized_ref (fn);
 
+  /* Strip away any wrapper to ensure we recognize the underlying fn,
+     if any.  */
+  STRIP_DECL_USAGE_EXPR (fn);
+
   orig_fn = fn;
 
   if (processing_template_decl)
@@ -3450,20 +3454,20 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool force_use)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-cp_expr
-finish_id_expression (tree id_expression,
-		      tree decl,
-		      tree scope,
-		      cp_id_kind *idk,
-		      bool integral_constant_expression_p,
-		      bool allow_non_integral_constant_expression_p,
-		      bool *non_integral_constant_expression_p,
-		      bool template_p,
-		      bool done,
-		      bool address_p,
-		      bool template_arg_p,
-		      const char **error_msg,
-		      location_t location)
+static cp_expr
+finish_id_expression_1 (tree id_expression,
+			tree decl,
+			tree scope,
+			cp_id_kind *idk,
+			bool integral_constant_expression_p,
+			bool allow_non_integral_constant_expression_p,
+			bool *non_integral_constant_expression_p,
+			bool template_p,
+			bool done,
+			bool address_p,
+			bool template_arg_p,
+			const char **error_msg,
+			location_t location)
 {
   decl = strip_using_decl (decl);
 
@@ -3763,6 +3767,34 @@ finish_id_expression (tree id_expression,
   return cp_expr (decl, location);
 }
 
+/* As per finish_id_expression_1, but adding a wrapper node
+   around the result if needed to express LOCATION.  */
+
+cp_expr
+finish_id_expression (tree id_expression,
+		      tree decl,
+		      tree scope,
+		      cp_id_kind *idk,
+		      bool integral_constant_expression_p,
+		      bool allow_non_integral_constant_expression_p,
+		      bool *non_integral_constant_expression_p,
+		      bool template_p,
+		      bool done,
+		      bool address_p,
+		      bool template_arg_p,
+		      const char **error_msg,
+		      location_t location)
+{
+  cp_expr result
+    = finish_id_expression_1 (id_expression, decl, scope, idk,
+			      integral_constant_expression_p,
+			      allow_non_integral_constant_expression_p,
+			      non_integral_constant_expression_p,
+			      template_p, done, address_p, template_arg_p,
+			      error_msg, location);
+  return result.maybe_add_location_wrapper ();
+}
+
 /* Implement the __typeof keyword: Return the type of EXPR, suitable for
    use as a type-specifier.  */
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 366f46f..c48a5be 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -63,6 +63,8 @@ lvalue_kind (const_tree ref)
   if (REFERENCE_REF_P (ref))
     return lvalue_kind (TREE_OPERAND (ref, 0));
 
+  STRIP_DECL_USAGE_EXPR (ref);
+
   if (TREE_TYPE (ref)
       && TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
     {
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 19fbe3c..473ca18 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3599,6 +3599,8 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
       && TREE_TYPE (function) == TREE_TYPE (TREE_OPERAND (function, 0)))
     function = TREE_OPERAND (function, 0);
 
+  STRIP_DECL_USAGE_EXPR (function);
+
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
       /* If the function is a non-template member function
@@ -5621,7 +5623,7 @@ build_address (tree t)
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
   gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR);
-  t = build_fold_addr_expr (t);
+  t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t);
   if (TREE_CODE (t) != ADDR_EXPR)
     t = rvalue (t);
   return t;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2c1ec85..109c498 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11254,6 +11254,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       else if (ret != GS_UNHANDLED)
 	break;
 
+      if (TREE_CODE (*expr_p) == DECL_USAGE_EXPR)
+	*expr_p = TREE_OPERAND (*expr_p, 0);
+
       /* Make sure that all the cases set 'ret' appropriately.  */
       ret = GS_UNHANDLED;
       switch (TREE_CODE (*expr_p))
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index bc3a938..5fcde0b 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -1,9 +1,6 @@
 // { dg-options "-fdiagnostics-show-caret" }
 
-/* A collection of calls where argument 2 is of the wrong type.
-
-   TODO: we should put the caret and underline for the diagnostic
-   at the second argument, rather than the close paren.  */
+/* A collection of calls where argument 2 is of the wrong type.  */
 
 /* decl, with argname.  */
 
@@ -14,7 +11,7 @@ int test_1 (int first, int second, float third)
   return callee_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_1 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
   /* { dg-begin-multiline-output "" }
@@ -32,7 +29,7 @@ int test_2 (int first, int second, float third)
   return callee_2 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_2 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
   /* { dg-begin-multiline-output "" }
@@ -53,7 +50,7 @@ int test_3 (int first, int second, float third)
   return callee_3 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_3 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
   /* { dg-begin-multiline-output "" }
@@ -71,7 +68,7 @@ int test_4 (int first, int second, float third)
   return s4::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s4::member_1 (first, second, third);
-                                            ^
+                               ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s4 { static int member_1 (int one, const char *two, float three); };
@@ -89,7 +86,7 @@ int test_5 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s5 { int member_1 (int one, const char *two, float three); };
@@ -106,7 +103,7 @@ int test_6 (int first, int second, float third, s6 *ptr)
   return ptr->member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return ptr->member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s6 { int member_1 (int one, const char *two, float three); };
@@ -128,7 +125,7 @@ int test_7 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
    return test_7 <const char *> (first, second, third);
-                                                     ^
+                                        ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  int test_7 (int one, T two, float three);
@@ -146,7 +143,7 @@ int test_8 (int first, int second, float third)
   return s8 <const char *>::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s8 <const char *>::member_1 (first, second, third);
-                                                           ^
+                                              ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s8 { static int member_1 (int one, T two, float three); };
@@ -165,7 +162,7 @@ int test_9 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s9 { int member_1 (int one, T two, float three); };
@@ -182,7 +179,7 @@ int test_10 (int first, int second, float third)
   return callee_10 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_10 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
   /* { dg-begin-multiline-output "" }
@@ -200,7 +197,7 @@ int test_11 (int first, int second, float third)
   return callee_11 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_11 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
   /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
index a145dfe..5e4d78b 100644
--- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
+++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
@@ -19,6 +19,113 @@ extern void __emit_expression_range (int dummy, ...);
 
 int global;
 
+void test_global (void)
+{
+  __emit_expression_range (0, global); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, global);
+                               ^~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_param (int param)
+{
+  __emit_expression_range (0, param); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, param);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_local (void)
+{
+  int local = 5;
+
+  __emit_expression_range (0, local); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, local);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_integer_constants (void)
+{
+  __emit_expression_range (0, 1234); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 1234);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  /* Ensure that zero works.  */
+
+  __emit_expression_range (0, 0); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 0);
+                               ^
+   { dg-end-multiline-output "" } */
+}
+
+void test_character_constants (void)
+{
+  __emit_expression_range (0, 'a'); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 'a');
+                               ^~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_floating_constants (void)
+{
+  __emit_expression_range (0, 98.6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, .6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, .6);
+                               ^~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.);
+                               ^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23 ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23 );
+                               ^~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.6f ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6f );
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23l ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23l );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+enum test_enum {
+  TEST_ENUM_VALUE
+};
+
+void test_enumeration_constant (void)
+{
+  __emit_expression_range (0, TEST_ENUM_VALUE ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, TEST_ENUM_VALUE );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
 void test_parentheses (int a, int b)
 {
   __emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
@@ -103,67 +210,36 @@ int test_postfix_incdec (int i)
 
 int test_sizeof (int i)
 {
-  __emit_expression_range (0, sizeof(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof(int) + i);
-                               ~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + sizeof(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof(int));
-                               ~~^~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, sizeof i + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof i ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof i + i);
-                               ~~~~~~~~~^~~
+   __emit_expression_range (0, sizeof i );
+                               ^~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, i + sizeof i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof (char) ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof i);
-                               ~~^~~~~~~~~~
+   __emit_expression_range (0, sizeof (char) );
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 int test_alignof (int i)
 {
-  __emit_expression_range (0, alignof(int) + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, alignof(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, alignof(int) + i);
-                               ~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + alignof(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + alignof(int));
-                               ~~^~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, __alignof__(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__(int) + i);
-                               ~~~~~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__(int));
-                               ~~^~~~~~~~~~~~~~~~~~
+   __emit_expression_range (0, alignof(int));
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, __alignof__ i + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__ i + i);
-                               ~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0, __alignof__(int));
+                               ^~~~~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__ i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__ i); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__ i);
-                               ~~^~~~~~~~~~~~~~~
+   __emit_expression_range (0, __alignof__ i);
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -200,6 +276,15 @@ void test_indirection (int *ptr)
    { dg-end-multiline-output "" } */
 }
 
+void test_unary_plus (int i)
+{
+  __emit_expression_range (0, +i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, +i );
+                               ^~
+   { dg-end-multiline-output "" } */
+}
+
 void test_unary_minus (int i)
 {
   __emit_expression_range (0, -i ); /* { dg-warning "range" } */
@@ -471,53 +556,36 @@ void test_comma_operator (int a, int b)
 
 /* Literals.  **************************************************/
 
-/* We can't test the ranges of literals directly, since the underlying
-   tree nodes don't retain a location.  However, we can test that they
-   have ranges during parsing by building compound expressions using
-   them, and verifying the ranges of the compound expressions.  */
-
-void test_string_literals (int i)
+void test_string_literals ()
 {
-  __emit_expression_range (0, "foo"[i] ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "0123456789"); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, "foo"[i] );
-                               ~~~~~~~^
+   __emit_expression_range (0, "0123456789");
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &"foo" "bar" ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "foo" "bar" ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &"foo" "bar" );
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, "foo" "bar" );
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 void test_numeric_literals (int i)
 {
-  __emit_expression_range (0, 42 + i ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, 42 + i );
-                               ~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + 42 ); /* { dg-warning "range" } */
+  __emit_expression_range (0, 42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + 42 );
-                               ~~^~~~
+   __emit_expression_range (0, 42 );
+                               ^~
    { dg-end-multiline-output "" } */
 
   /* Verify locations of negative literals (via folding of
      unary negation).  */
 
-  __emit_expression_range (0, -42 + i ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, -42 + i );
-                               ~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + -42 ); /* { dg-warning "range" } */
+  __emit_expression_range (0, -42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + -42 );
-                               ~~^~~~~
+   __emit_expression_range (0, -42 );
+                               ^~~
    { dg-end-multiline-output "" } */
 
   __emit_expression_range (0, i ? 0 : -1 ); /* { dg-warning "range" } */
@@ -529,6 +597,8 @@ void test_numeric_literals (int i)
 
 /* Braced initializers.  ***************************************/
 
+// FIXME:
+
 /* We can't test the ranges of these directly, since the underlying
    tree nodes don't retain a location.  However, we can test that they
    have ranges during parsing by building compound expressions using
@@ -556,6 +626,8 @@ void test_braced_init (void)
 
 /* Statement expressions.  ***************************************/
 
+// FIXME:
+
 void test_statement_expression (void)
 {
   __emit_expression_range (0, ({ static int a; a; }) + 1);  /* { dg-warning "range" } */
@@ -638,16 +710,10 @@ struct s { int i; float f; };
 
 void test_builtin_offsetof (int i)
 {
-  __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
+  __emit_expression_range (0,  __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );
-                                ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );  /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );
-                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0,  __builtin_offsetof (struct s, f) );
+                                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -856,28 +922,22 @@ namespace std
 
 void test_typeid (int i)
 {
-  __emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i));
-                               ^~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, &typeid(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(int));
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, typeid(i));
+                               ^~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i * 2));
-                               ^~~~~~~~~~~~~~
+   __emit_expression_range (0, typeid(int));
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i * 2)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, typeid(int).foo);
-                               ~~~~~~~~~~~~^~~
+   __emit_expression_range (0, typeid(i * 2));
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
index 89cc95a..50c69b8 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c
@@ -57,6 +57,8 @@ cb_walk_tree_fn (tree * tp, int * walk_subtrees,
   if (TREE_CODE (fn) != ADDR_EXPR)
     return NULL_TREE;
   fn = TREE_OPERAND (fn, 0);
+  if (TREE_CODE (fn) == DECL_USAGE_EXPR)
+    fn = TREE_OPERAND (fn, 0);
   if (TREE_CODE (fn) != FUNCTION_DECL)
     return NULL_TREE;
   if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__emit_expression_range"))
diff --git a/gcc/tree.c b/gcc/tree.c
index 62a4386..270e680 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13747,6 +13747,26 @@ set_source_range (tree expr, source_range src_range)
   return adhoc;
 }
 
+/* Return EXPR, potentially wrapped with a DECL_USAGE_EXPR node
+   at LOC, if !CAN_HAVE_LOCATION_P (expr).  */
+
+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));
+  return build1_loc (loc, DECL_USAGE_EXPR, TREE_TYPE (expr), expr);
+}
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
diff --git a/gcc/tree.def b/gcc/tree.def
index 3d2bd95..bb44cc6 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -827,6 +827,9 @@ DEFTREECODE (FIXED_CONVERT_EXPR, "fixed_convert_expr", tcc_unary, 1)
 /* Represents a conversion expected to require no code to be generated.  */
 DEFTREECODE (NOP_EXPR, "nop_expr", tcc_unary, 1)
 
+/* Represents the usage of a decl within an expression.  */
+DEFTREECODE (DECL_USAGE_EXPR, "decl_usage_expr", tcc_unary, 1)
+
 /* Value is same as argument, but guaranteed not an lvalue.  */
 DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", tcc_unary, 1)
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 7214ae2..5c24c07 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -483,6 +483,14 @@ 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 DECL_USAGE_EXPR.  */
+
+#define STRIP_DECL_USAGE_EXPR(EXP) \
+  do { \
+    if (TREE_CODE (EXP) == DECL_USAGE_EXPR)  \
+      (EXP) = TREE_OPERAND ((EXP), 0);	     \
+  } while (0)
+
 /* Nonzero if TYPE represents a vector type.  */
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
@@ -1147,6 +1155,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)
-- 
1.8.5.3

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

* Re: [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486)
  2017-10-20 22:38 [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486) David Malcolm
@ 2017-10-24 14:05 ` Jason Merrill
  2017-10-31 21:28   ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-10-24 14:05 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> Design questions:
>
> * The patch introduces a new kind of tree node, currently called
>   DECL_WRAPPER_EXPR (although it's used for wrapping constants as well
>   as decls).  Should wrappers be a new kind of tree node, or should they
>   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR, etc).
>     * NOP_EXPR: seems to be for use as an rvalue
>     * CONVERT_EXPR: for type conversions
>     * NON_LVALUE_EXPR: "Value is same as argument, but guaranteed not an
>       lvalue"
>       * but we *do* want to support lvalues here

I think using NON_LVALUE_EXPR for constants would be appropriate.

>     * VIEW_CONVERT_EXPR: viewing one thing as of a different type
>       * can it support lvalues?

Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it seems
like the right choice.

Jason

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

* Re: [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486)
  2017-10-24 14:05 ` Jason Merrill
@ 2017-10-31 21:28   ` David Malcolm
  2017-11-02 14:46     ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-10-31 21:28 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
> On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > Design questions:
> > 
> > * The patch introduces a new kind of tree node, currently called
> >   DECL_WRAPPER_EXPR (although it's used for wrapping constants as
> > well
> >   as decls).  Should wrappers be a new kind of tree node, or should
> > they
> >   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR, etc).
> >     * NOP_EXPR: seems to be for use as an rvalue
> >     * CONVERT_EXPR: for type conversions
> >     * NON_LVALUE_EXPR: "Value is same as argument, but guaranteed
> > not an
> >       lvalue"
> >       * but we *do* want to support lvalues here
> 
> I think using NON_LVALUE_EXPR for constants would be appropriate.
> 
> >     * VIEW_CONVERT_EXPR: viewing one thing as of a different type
> >       * can it support lvalues?
> 
> Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it seems
> like the right choice.
> 
> Jason

Thanks.  I've been working on a new version of the patch using those
tree codes, but have run into an issue.

In g++.dg/conversion/reinterpret1.C:

  // PR c++/15076

  struct Y { Y(int &); };

  int v;
  Y y1(reinterpret_cast<int>(v));  // { dg-error "" }

With trunk, this successfully generates an error:

  reinterpret1.C:6:6: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
        ^~~~~~~~~~~~~~~~~~~~~~~~
  reinterpret1.C:3:12: note:   initializing argument 1 of ‘Y::Y(int&)’
   struct Y { Y(int &); };
              ^

where internally there's a NON_LVALUE_EXPR around a VAR_DECL, where
both have the same type:

(gdb) call debug_tree (expr)
 <non_lvalue_expr 0x7ffff145f6e0
    type <integer_type 0x7ffff132e5e8 int public type_6 SI
        size <integer_cst 0x7ffff1331120 constant 32>
        unit-size <integer_cst 0x7ffff1331138 constant 4>
        align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0 2147483647>
        pointer_to_this <pointer_type 0x7ffff1336a80> reference_to_this <reference_type 0x7ffff144ca80>>
   
    arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type 0x7ffff132e5e8 int>
        used public static tree_1 read SI /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5 size <integer_cst 0x7ffff1331120 32> unit-size <integer_cst 0x7ffff1331138 4>
        align:32 warn_if_not_align:0 context <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
        chain <type_decl 0x7ffff141a720 Y type <record_type 0x7ffff144c150 Y>
            public decl_2 VOID /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
            align:8 warn_if_not_align:0 context <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C> chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
    /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 start: /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 finish: /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>

The problem is that this reinterpret cast "looks" just like one of my
location wrappers.

I see a similar issue with constants, where with:

  struct Y { Y(int &); };
  Y y1(reinterpret_cast<int>(42));

trunk generates an error like the above, but my code handles the
  NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
as if it were a location wrapper around the INTEGER_CST, and thus
doesn't emit the error.

I can envisage a few hackish solutions, like assuming that there will
be a location wrapper around such a constant, and thus to expect:
  NON_LVALUE_EXPR<int>(NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42)))
but this seems clunky and fragile; maybe we do need a new tree code for
this (e.g. LOCATION_WRAPPER or somesuch?)

Thoughts?

Thanks
Dave

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

* Re: [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486)
  2017-10-31 21:28   ` David Malcolm
@ 2017-11-02 14:46     ` Jason Merrill
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-11-02 14:46 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
>> On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > Design questions:
>> >
>> > * The patch introduces a new kind of tree node, currently called
>> >   DECL_WRAPPER_EXPR (although it's used for wrapping constants as
>> > well
>> >   as decls).  Should wrappers be a new kind of tree node, or should
>> > they
>> >   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR, etc).
>> >     * NOP_EXPR: seems to be for use as an rvalue
>> >     * CONVERT_EXPR: for type conversions
>> >     * NON_LVALUE_EXPR: "Value is same as argument, but guaranteed
>> > not an
>> >       lvalue"
>> >       * but we *do* want to support lvalues here
>>
>> I think using NON_LVALUE_EXPR for constants would be appropriate.
>>
>> >     * VIEW_CONVERT_EXPR: viewing one thing as of a different type
>> >       * can it support lvalues?
>>
>> Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it seems
>> like the right choice.
>>
>> Jason
>
> Thanks.  I've been working on a new version of the patch using those
> tree codes, but have run into an issue.
>
> In g++.dg/conversion/reinterpret1.C:
>
>   // PR c++/15076
>
>   struct Y { Y(int &); };
>
>   int v;
>   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
>
> With trunk, this successfully generates an error:
>
>   reinterpret1.C:6:6: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
>    Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
>         ^~~~~~~~~~~~~~~~~~~~~~~~
>   reinterpret1.C:3:12: note:   initializing argument 1 of ‘Y::Y(int&)’
>    struct Y { Y(int &); };
>               ^
>
> where internally there's a NON_LVALUE_EXPR around a VAR_DECL, where
> both have the same type:
>
> (gdb) call debug_tree (expr)
>  <non_lvalue_expr 0x7ffff145f6e0
>     type <integer_type 0x7ffff132e5e8 int public type_6 SI
>         size <integer_cst 0x7ffff1331120 constant 32>
>         unit-size <integer_cst 0x7ffff1331138 constant 4>
>         align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0 2147483647>
>         pointer_to_this <pointer_type 0x7ffff1336a80> reference_to_this <reference_type 0x7ffff144ca80>>
>
>     arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type 0x7ffff132e5e8 int>
>         used public static tree_1 read SI /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5 size <integer_cst 0x7ffff1331120 32> unit-size <integer_cst 0x7ffff1331138 4>
>         align:32 warn_if_not_align:0 context <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
>         chain <type_decl 0x7ffff141a720 Y type <record_type 0x7ffff144c150 Y>
>             public decl_2 VOID /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
>             align:8 warn_if_not_align:0 context <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C> chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
>     /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 start: /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 finish: /home/david/coding-3/gcc-git-expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
>
> The problem is that this reinterpret cast "looks" just like one of my
> location wrappers.

Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.

> I see a similar issue with constants, where with:
>
>   struct Y { Y(int &); };
>   Y y1(reinterpret_cast<int>(42));
>
> trunk generates an error like the above, but my code handles the
>   NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> as if it were a location wrapper around the INTEGER_CST, and thus
> doesn't emit the error.

Why doesn't it emit the error?  We should get the same error whether
or not we strip the wrapper.

Jason

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

* [PATCH 02/14] Support for adding and stripping location_t wrapper nodes
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (4 preceding siblings ...)
  2017-11-10 21:43         ` [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-11-15  6:31           ` Trevor Saunders
  2017-11-10 21:44         ` [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind David Malcolm
                           ` (12 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

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, along with a new method of cp_expr.

It's called in later patches in the kit via that new method.

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/ChangeLog:
	PR c++/43486
	* tree.c (maybe_wrap_with_location): New function.
	* tree.h (STRIP_ANY_LOCATION_WRAPPER): New macro.
	(maybe_wrap_with_location): New decl.
	(location_wrapper_p): New inline function.

gcc/cp/ChangeLog:
	PR c++/43486
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
---
 gcc/cp/cp-tree.h |  6 ++++++
 gcc/tree.c       | 27 +++++++++++++++++++++++++++
 gcc/tree.h       | 26 ++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 874cbcb..726b6f5 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.c b/gcc/tree.c
index 28e157f..50c818c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13747,6 +13747,33 @@ set_source_range (tree expr, source_range src_range)
   return adhoc;
 }
 
+/* Return EXPR, potentially wrapped with a LOCATION_WRAPPER_EXPR node
+   at LOC, if !CAN_HAVE_LOCATION_P (expr).  */
+
+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;
+
+  if (CONSTANT_CLASS_P (expr))
+    return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (expr), expr);
+  else
+    return build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+}
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
diff --git a/gcc/tree.h b/gcc/tree.h
index 277aa91..fb45a8d 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -483,6 +483,15 @@ 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) \
+  do {					\
+    if (location_wrapper_p (EXP))	\
+      (EXP) = TREE_OPERAND ((EXP), 0);	\
+  } while (0)
+
 /* Nonzero if TYPE represents a vector type.  */
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
@@ -1147,6 +1156,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)
@@ -3637,6 +3648,21 @@ id_equal (const char *str, const_tree id)
   return !strcmp (str, IDENTIFIER_POINTER (id));
 }
 
+/* Test if EXP is merely a wrapper node, added to express a location_t
+   on behalf of its child.  */
+
+inline bool location_wrapper_p (const_tree exp)
+{
+  if (((TREE_CODE (exp) == NON_LVALUE_EXPR
+	&& CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+	   && !CONSTANT_CLASS_P (TREE_OPERAND (exp, 0))))
+      && (TREE_TYPE (exp)
+	  == TREE_TYPE (TREE_OPERAND (exp, 0))))
+    return true;
+  return false;
+}
+
 #define error_mark_node			global_trees[TI_ERROR_MARK]
 
 #define intQI_type_node			global_trees[TI_INTQI_TYPE]
-- 
1.8.5.3

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

* [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (3 preceding siblings ...)
  2017-11-10 21:43         ` [PATCH 01/14] C++: preserve locations within build_address David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-12-12  2:10           ` Jason Merrill
  2017-11-10 21:43         ` [PATCH 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
                           ` (13 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

The initial version of the patch kit added location wrapper nodes
around constants and uses-of-declarations, along with some other
places in the parser (typeid, alignof, sizeof, offsetof).

This version takes a much more minimal approach: it only adds
location wrapper nodes around the arguments at callsites, thus
not adding wrapper nodes around uses of constants and decls in other
locations.

It keeps them for the other places in the parser (typeid, alignof,
sizeof, offsetof).

In addition, for now, each site that adds wrapper nodes is guarded
with !processing_template_decl, suppressing the creation of wrapper
nodes when processing template declarations.  This is to simplify
the patch kit so that we don't have to support wrapper nodes during
template expansion.

gcc/cp/ChangeLog:
	* parser.c (cp_parser_postfix_expression): Call
	maybe_add_location_wrapper on the result for RID_TYPEID. Pass true
	for new "wrap_locations_p" param of
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true,
	except when processing template decls.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.

FIXME: don't do alignof etc when processing template decls
---
 gcc/cp/parser.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 77b9637..54029ef 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2054,7 +2054,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6776,6 +6777,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    if (!processing_template_decl)
+	      postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7096,7 +7099,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7736,6 +7740,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7755,7 +7763,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7778,12 +7787,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7837,11 +7846,15 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      if (!processing_template_decl)
+		expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -8107,6 +8120,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    if (!processing_template_decl)
+	      ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9933,6 +9948,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  if (!processing_template_decl)
+    expr = expr.maybe_add_location_wrapper ();
   return expr;
 }
 
-- 
1.8.5.3

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

* [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
  2017-11-10 21:43         ` [PATCH 07/14] reject_gcc_builtin: strip any location wrappers David Malcolm
  2017-11-10 21:43         ` [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-12-11 23:37           ` Jason Merrill
  2017-11-10 21:43         ` [PATCH 01/14] C++: preserve locations within build_address David Malcolm
                           ` (15 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/c-family/ChangeLog:
	* c-warn.c (sizeof_pointer_memaccess_warning): Strip any location
	wrappers from src and dest.
---
 gcc/c-family/c-warn.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 09ef685..245c37d 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -770,6 +770,11 @@ sizeof_pointer_memaccess_warning (location_t *sizeof_arg_loc, tree callee,
   if (idx >= 3)
     return;
 
+  if (src)
+    STRIP_ANY_LOCATION_WRAPPER (src);
+  if (dest)
+    STRIP_ANY_LOCATION_WRAPPER (dest);
+
   if (sizeof_arg[idx] == NULL || sizeof_arg[idx] == error_mark_node)
     return;
 
-- 
1.8.5.3

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

* [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
  2017-11-10 21:43         ` [PATCH 07/14] reject_gcc_builtin: strip any location wrappers David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-12-11 23:36           ` Jason Merrill
  2017-11-10 21:43         ` [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c David Malcolm
                           ` (16 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

We need to strip away location wrappers in tree.c predicates like
integer_zerop, otherwise they fail when they're called on
wrapped INTEGER_CST; an example can be seen for
  c-c++-common/Wmemset-transposed-args1.c
in g++.sum, where the warn_for_memset fails to detect integer zero
if the location wrappers aren't stripped.

gcc/ChangeLog:
	* tree.c (integer_zerop): Use STRIP_ANY_LOCATION_WRAPPER on the
	expr.
	(integer_onep): Likewise.
	(integer_each_onep): Likewise.
	(integer_all_onesp): Likewise.
	(integer_minus_onep): Likewise.
	(integer_pow2p): Likewise.
	(integer_nonzerop): Likewise.
	(integer_truep): Likewise.
	(fixed_zerop): Likewise.
	(tree_log2): Likewise.
	(tree_floor_log2): Likewise.
	(tree_ctz): Likewise.
	(real_zerop): Likewise.
	(real_onep): Likewise.
	(real_minus_onep): Likewise.
	(really_constant_p): Likewise.
---
 gcc/tree.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/gcc/tree.c b/gcc/tree.c
index 50c818c..f71b484 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2343,6 +2343,8 @@ zerop (const_tree expr)
 int
 integer_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2369,6 +2371,8 @@ integer_zerop (const_tree expr)
 int
 integer_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2395,6 +2399,8 @@ integer_onep (const_tree expr)
 int
 integer_each_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_onep (TREE_REALPART (expr))
 	    && integer_onep (TREE_IMAGPART (expr)));
@@ -2408,6 +2414,8 @@ integer_each_onep (const_tree expr)
 int
 integer_all_onesp (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_all_onesp (TREE_REALPART (expr))
       && integer_all_onesp (TREE_IMAGPART (expr)))
@@ -2434,6 +2442,8 @@ integer_all_onesp (const_tree expr)
 int
 integer_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_all_onesp (TREE_REALPART (expr))
 	    && integer_zerop (TREE_IMAGPART (expr)));
@@ -2447,6 +2457,8 @@ integer_minus_onep (const_tree expr)
 int
 integer_pow2p (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_pow2p (TREE_REALPART (expr))
       && integer_zerop (TREE_IMAGPART (expr)))
@@ -2464,6 +2476,8 @@ integer_pow2p (const_tree expr)
 int
 integer_nonzerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return ((TREE_CODE (expr) == INTEGER_CST
 	   && wi::to_wide (expr) != 0)
 	  || (TREE_CODE (expr) == COMPLEX_CST
@@ -2478,6 +2492,8 @@ integer_nonzerop (const_tree expr)
 int
 integer_truep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == VECTOR_CST)
     return integer_all_onesp (expr);
   return integer_onep (expr);
@@ -2488,6 +2504,8 @@ integer_truep (const_tree expr)
 int
 fixed_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return (TREE_CODE (expr) == FIXED_CST
 	  && TREE_FIXED_CST (expr).data.is_zero ());
 }
@@ -2498,6 +2516,8 @@ fixed_zerop (const_tree expr)
 int
 tree_log2 (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
@@ -2510,6 +2530,8 @@ tree_log2 (const_tree expr)
 int
 tree_floor_log2 (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
@@ -2522,6 +2544,8 @@ tree_floor_log2 (const_tree expr)
 unsigned int
 tree_ctz (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
       && !POINTER_TYPE_P (TREE_TYPE (expr)))
     return 0;
@@ -2633,6 +2657,8 @@ tree_ctz (const_tree expr)
 int
 real_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2661,6 +2687,8 @@ real_zerop (const_tree expr)
 int
 real_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2688,6 +2716,8 @@ real_onep (const_tree expr)
 int
 real_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2714,6 +2744,8 @@ real_minus_onep (const_tree expr)
 int
 really_constant_p (const_tree exp)
 {
+  STRIP_ANY_LOCATION_WRAPPER (exp);
+
   /* This is not quite the same as STRIP_NOPS.  It does more.  */
   while (CONVERT_EXPR_P (exp)
 	 || TREE_CODE (exp) == NON_LVALUE_EXPR)
-- 
1.8.5.3

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

* [PATCH 07/14] reject_gcc_builtin: strip any location wrappers
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-12-11 23:38           ` Jason Merrill
  2017-11-10 21:43         ` [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc David Malcolm
                           ` (17 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Otherwise pr70144-1.c breaks.

gcc/c-family/ChangeLog:
	* c-common.c (reject_gcc_builtin): Strip any location from EXPR.
---
 gcc/c-family/c-common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 24077c7..739c54e 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7774,6 +7774,8 @@ pointer_to_zero_sized_aggr_p (tree t)
 bool
 reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == ADDR_EXPR)
     expr = TREE_OPERAND (expr, 0);
 
-- 
1.8.5.3

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

* [PATCH 01/14] C++: preserve locations within build_address
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (2 preceding siblings ...)
  2017-11-10 21:43         ` [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c David Malcolm
@ 2017-11-10 21:43         ` David Malcolm
  2017-12-11 23:25           ` Jason Merrill
  2017-11-10 21:43         ` [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) David Malcolm
                           ` (14 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This is needed for the locations of string literals to be usable,
otherwise the ADDR_EXPR has UNKNOWN_LOCATION, despite wrapping
a node with a correct location_t.

gcc/cp/ChangeLog:
	* typeck.c (build_address): Use location of operand when building
	address expression.
---
 gcc/cp/typeck.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9130c10..dd3e19d 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5621,7 +5621,7 @@ build_address (tree t)
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
   gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR);
-  t = build_fold_addr_expr (t);
+  t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t);
   if (TREE_CODE (t) != ADDR_EXPR)
     t = rvalue (t);
   return t;
-- 
1.8.5.3

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

* [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486)
  2017-11-02 14:46     ` Jason Merrill
@ 2017-11-10 21:43       ` David Malcolm
  2017-11-10 21:43         ` [PATCH 07/14] reject_gcc_builtin: strip any location wrappers David Malcolm
                           ` (18 more replies)
  0 siblings, 19 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:43 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Thu, 2017-11-02 at 10:46 -0400, Jason Merrill wrote:
> On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
> > > On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > Design questions:
> > > > 
> > > > * The patch introduces a new kind of tree node, currently
> > > > called
> > > >   DECL_WRAPPER_EXPR (although it's used for wrapping constants
> > > > as
> > > > well
> > > >   as decls).  Should wrappers be a new kind of tree node, or
> > > > should
> > > > they
> > > >   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR,
> > > > etc).
> > > >     * NOP_EXPR: seems to be for use as an rvalue
> > > >     * CONVERT_EXPR: for type conversions
> > > >     * NON_LVALUE_EXPR: "Value is same as argument, but
> > > > guaranteed
> > > > not an
> > > >       lvalue"
> > > >       * but we *do* want to support lvalues here
> > > 
> > > I think using NON_LVALUE_EXPR for constants would be appropriate.
> > > 
> > > >     * VIEW_CONVERT_EXPR: viewing one thing as of a different
> > > > type
> > > >       * can it support lvalues?
> > > 
> > > Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it
> > > seems
> > > like the right choice.
> > > 
> > > Jason
> > 
> > Thanks.  I've been working on a new version of the patch using
> > those
> > tree codes, but have run into an issue.
> > 
> > In g++.dg/conversion/reinterpret1.C:
> > 
> >   // PR c++/15076
> > 
> >   struct Y { Y(int &); };
> > 
> >   int v;
> >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > 
> > With trunk, this successfully generates an error:
> > 
> >   reinterpret1.C:6:6: error: cannot bind non-const lvalue reference
> > of type ‘int&’ to an rvalue of type ‘int’
> >    Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> >         ^~~~~~~~~~~~~~~~~~~~~~~~
> >   reinterpret1.C:3:12: note:   initializing argument 1 of
> > ‘Y::Y(int&)’
> >    struct Y { Y(int &); };
> >               ^
> > 
> > where internally there's a NON_LVALUE_EXPR around a VAR_DECL, where
> > both have the same type:
> > 
> > (gdb) call debug_tree (expr)
> >  <non_lvalue_expr 0x7ffff145f6e0
> >     type <integer_type 0x7ffff132e5e8 int public type_6 SI
> >         size <integer_cst 0x7ffff1331120 constant 32>
> >         unit-size <integer_cst 0x7ffff1331138 constant 4>
> >         align:32 warn_if_not_align:0 symtab:0 alias-set -1
> > canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst
> > 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0
> > 2147483647>
> >         pointer_to_this <pointer_type 0x7ffff1336a80>
> > reference_to_this <reference_type 0x7ffff144ca80>>
> > 
> >     arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type
> > 0x7ffff132e5e8 int>
> >         used public static tree_1 read SI /home/david/coding-3/gcc-
> > git-expr-vs-
> > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5 size
> > <integer_cst 0x7ffff1331120 32> unit-size <integer_cst
> > 0x7ffff1331138 4>
> >         align:32 warn_if_not_align:0 context <translation_unit_decl
> > 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-
> > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> >         chain <type_decl 0x7ffff141a720 Y type <record_type
> > 0x7ffff144c150 Y>
> >             public decl_2 VOID /home/david/coding-3/gcc-git-expr-
> > vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
> >             align:8 warn_if_not_align:0 context
> > <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-git-
> > expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
> >     /home/david/coding-3/gcc-git-expr-vs-
> > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 start:
> > /home/david/coding-3/gcc-git-expr-vs-
> > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6 finish:
> > /home/david/coding-3/gcc-git-expr-vs-
> > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
> > 
> > The problem is that this reinterpret cast "looks" just like one of
> > my
> > location wrappers.
> 
> Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.

> > I see a similar issue with constants, where with:
> > 
> >   struct Y { Y(int &); };
> >   Y y1(reinterpret_cast<int>(42));
> > 
> > trunk generates an error like the above, but my code handles the
> >   NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> > as if it were a location wrapper around the INTEGER_CST, and thus
> > doesn't emit the error.
> 
> Why doesn't it emit the error?  We should get the same error whether
> or not we strip the wrapper.

Thanks: my stripping macro was over-zealous: it was stripping any
NON_LVALUE_EXPR or VIEW_CONVERT_EXPR where the type matched that of
the wrapped node.  I've added the additional condition that a
NON_LVALUE_EXPR has to be around a CONSTANT_CLASS_P, and
a VIEW_CONVERT_EXPR around a !CONSTANT_CLASS_P.

Here's an updated version of the patch (v2), now a patch kit (on top
of r254387).  I split it up thematically for ease of review, but all
the patches go together.

This version of the patch kit bootstraps and passes the regression
tests (on x86_64-pc-linux-gnu)

To do so, I've made some simplfications to how wrappers nodes are
added.

The previous patch added wrappers in the C++ parser around constants
and uses-of-declarations, along with some other places in the
parser (typeid, alignof, sizeof, offsetof).

This version takes a much more minimal approach: it only adds
location wrapper nodes around the arguments at callsites, thus
not adding wrapper nodes around uses of constants and decls in other
locations.

It keeps them for the other places in the parser (typeid, alignof,
sizeof, offsetof).

In addition, for now, each site that adds wrapper nodes is guarded
with !processing_template_decl, suppressing the creation of wrapper
nodes when processing template declarations.  This is to simplify
the patch kit so that we don't have to support wrapper nodes during
template expansion.

With this, we get a big usability win: we always have a location_t
for every argument at a callsite, and so various errors involving
mismatching arguments are much easier to read (as the pertinent
argument is underlined).

I marked this as "PR 43486" as it's a big step towards solving that
PR (which seeks to preserve locations all the way through to the
middle end), but much more would need to be done to solve it:

* this patch kit only adds wrappers to the C++ frontend, not to C

* as noted above, location_t wrapper nodes are only added at
  arguments of callsites (and a few other places), with some
  restrictions.

* none of the wrapper nodes survive past gimplification;
  it's not clear to me how best to preserve them into the
  middle-end.  But even without doing so, we get the big usability
  win.

The later parts of the patch kit add STRIP_ANY_LOCATION_WRAPPER uses
in various places where the tree code of an expression is examined,
so that such conditions use the code of the wrapped node, rather
than that of the wrapper.  One of the risks of the patch kit is that
although the testsuite passes, there are probably places in our code
which still need uses of STRIP_ANY_LOCATION_WRAPPER.


Performance of the patch kit
****************************

Benchmarking shows an apparent 2-3% in cc1plus wallclock compile-time
for kdecore.cc -O3 -g:

Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu: wall
      control: [56.55, 56.54, 56.68, 56.51, 56.45, 56.5, 56.45, 56.46, 56.49, 56.5, 56.42, 56.37, 56.41, 56.55]
   experiment: [57.32, 58.37, 58.17, 58.18, 58.78, 58.48, 57.99, 58.16, 58.14, 57.62, 58.36, 58.1, 57.71, 57.7]
Min: 56.370000 -> 57.320000: 1.02x slower
Avg: 56.491429 -> 58.077143: 1.03x slower
Significant (t=-15.14)
Stddev: 0.07655 -> 0.38426: 5.0199x larger

although I'm not quite sure why; the difference is in "phase setup", which
gains a large "wall" value (but not in usr or sys), whereas "phase parsing"
is unaffected:

unpatched:

 phase setup             :   0.00 ( 0%) usr   0.02 ( 0%) sys   0.02 ( 0%) wall    1488 kB ( 0%) ggc
 phase parsing           :   1.83 ( 4%) usr   0.82 (16%) sys   2.66 ( 5%) wall  156603 kB (12%) ggc
 phase lang. deferred    :   0.30 ( 1%) usr   0.09 ( 2%) sys   0.38 ( 1%) wall   29861 kB ( 2%) ggc
 phase opt and generate  :  48.09 (94%) usr   4.28 (81%) sys  52.55 (93%) wall 1085420 kB (84%) ggc
 phase last asm          :   0.86 ( 2%) usr   0.05 ( 1%) sys   0.92 ( 2%) wall   15806 kB ( 1%) ggc
 phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.01 ( 0%) wall       0 kB ( 0%) ggc
 |name lookup            :   0.30 ( 1%) usr   0.13 ( 2%) sys   0.21 ( 0%) wall    4955 kB ( 0%) ggc
 |overload resolution    :   0.49 ( 1%) usr   0.06 ( 1%) sys   0.68 ( 1%) wall   27263 kB ( 2%) ggc
 garbage collection      :   0.77 ( 2%) usr   0.00 ( 0%) sys   0.77 ( 1%) wall       0 kB ( 0%) ggc
 [...]
 TOTAL                 :  51.08             5.27            56.54            1289189 kB

patched:
 phase setup             :   0.01 ( 0%) usr   0.03 ( 1%) sys   1.91 ( 3%) wall    1488 kB ( 0%) ggc
 phase parsing           :   1.80 ( 4%) usr   0.84 (16%) sys   2.66 ( 5%) wall  158066 kB (12%) ggc
 phase lang. deferred    :   0.29 ( 1%) usr   0.09 ( 2%) sys   0.39 ( 1%) wall   29861 kB ( 2%) ggc
 phase opt and generate  :  48.09 (94%) usr   4.27 (81%) sys  52.52 (90%) wall 1085428 kB (84%) ggc
 phase last asm          :   0.82 ( 2%) usr   0.05 ( 1%) sys   0.89 ( 2%) wall   15806 kB ( 1%) ggc
 phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
 |name lookup            :   0.29 ( 1%) usr   0.07 ( 1%) sys   0.36 ( 1%) wall    4955 kB ( 0%) ggc
 |overload resolution    :   0.51 ( 1%) usr   0.07 ( 1%) sys   0.50 ( 1%) wall   27296 kB ( 2%) ggc
 garbage collection      :   0.79 ( 2%) usr   0.00 ( 0%) sys   0.78 ( 1%) wall       0 kB ( 0%) ggc
 TOTAL                 :  51.01             5.29            58.37            1290660 kB

What's up with that "phase setup" change?  Did I mess up my testing
somehow?


...and a slight increase in GGC usage:

Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu: ggc
      control: [1289179.0, 1289189.0, 1289170.0, 1289186.0, 1289194.0, 1289172.0, 1289176.0, 1289192.0, 1289189.0, 1289179.0, 1289172.0, 1289190.0, 1289169.0, 1289185.0]
   experiment: [1290654.0, 1290660.0, 1290655.0, 1290659.0, 1290631.0, 1290655.0, 1290650.0, 1290652.0, 1290642.0, 1290650.0, 1290658.0, 1290662.0, 1290638.0, 1290655.0]
Mem max: 1289194.000 -> 1290662.000: 1.0011x larger

(this is with stripped binaries, and --enable-checking=release)

Testing with a simple file that includes all of the C++ standard library
(but doesn't do anything with it) shows no change in time, and GGC usage
in the parsing phase increasing 50kB from 149954 kB to 150004 kB.


Next steps?
***********

I'm working on extending the patch kit to add wrapper nodes at all
constants and uses-of-decls in the C++ parser, but of course this
could have some effect on time/memory, and require more uses of
STRIP_ANY_LOCATION_WRAPPER.

An alternative appoach is:

  "[PATCH] C++: use an optional vec<location_t> for callsites"
    https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html

which eschews wrapper nodes in favor of duplicating the C frontend's
workaround here (though Jason disliked this approach, when we discussed
it at Cauldron).

Thoughts?

(I'm keen on getting *some* solution for providing location_t values
for arguments at C++ callsites into gcc 8)


David Malcolm (14):
  C++: preserve locations within build_address
  Support for adding and stripping location_t wrapper nodes
  C++: add location_t wrapper nodes during parsing (minimal impl)
  Update testsuite to show improvements
  tree.c: strip location wrappers from integer_zerop etc
  Fix Wsizeof-pointer-memaccess*.c
  reject_gcc_builtin: strip any location wrappers
  cp/tree.c: strip location wrappers in lvalue_kind
  Strip location wrappers in null_ptr_cst_p
  warn_for_memset: handle location wrappers
  Handle location wrappers in string_conv_p
  C++: introduce null_node_p
  c-format.c: handle location wrappers
  pp_c_cast_expression: don't print casts for location wrappers

 gcc/c-family/c-common.c                            |   3 +
 gcc/c-family/c-common.h                            |   1 +
 gcc/c-family/c-format.c                            |   9 +-
 gcc/c-family/c-pretty-print.c                      |  66 +++++-
 gcc/c-family/c-warn.c                              |   8 +
 gcc/cp/call.c                                      |   6 +-
 gcc/cp/cp-tree.h                                   |  13 ++
 gcc/cp/cvt.c                                       |   2 +-
 gcc/cp/error.c                                     |   2 +-
 gcc/cp/except.c                                    |   2 +-
 gcc/cp/parser.c                                    |  30 ++-
 gcc/cp/tree.c                                      |   2 +
 gcc/cp/typeck.c                                    |   6 +-
 .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
 .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260 +++++++++++++--------
 gcc/tree.c                                         |  59 +++++
 gcc/tree.h                                         |  26 +++
 17 files changed, 392 insertions(+), 130 deletions(-)

-- 
1.8.5.3

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

* [PATCH 11/14] Handle location wrappers in string_conv_p
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (10 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 04/14] Update testsuite to show improvements David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:42           ` Jason Merrill
  2017-11-10 21:44         ` [PATCH 10/14] warn_for_memset: handle location wrappers David Malcolm
                           ` (6 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/cp/ChangeLog:
	* typeck.c (string_conv_p): Strip any location wrapper from "exp".
---
 gcc/cp/typeck.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dd3e19d..523e4d3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2149,6 +2149,8 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
       && !same_type_p (t, wchar_type_node))
     return 0;
 
+  STRIP_ANY_LOCATION_WRAPPER (exp);
+
   if (TREE_CODE (exp) == STRING_CST)
     {
       /* Make sure that we don't try to convert between char and wide chars.  */
-- 
1.8.5.3

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

* [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (5 preceding siblings ...)
  2017-11-10 21:43         ` [PATCH 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:39           ` Jason Merrill
  2017-11-10 21:44         ` [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers David Malcolm
                           ` (11 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Without this, then lvalue_p returns false for decls, and hence
e.g. uses of them for references fail.

Stripping location wrappers in lvalue_kind restores the correct
behavior of lvalue_p etc.

gcc/cp/ChangeLog:
	* tree.c (lvalue_kind): Strip any location wrapper.
---
 gcc/cp/tree.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index b63f2ae..28ff7de 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -56,6 +56,8 @@ lvalue_kind (const_tree ref)
   cp_lvalue_kind op1_lvalue_kind = clk_none;
   cp_lvalue_kind op2_lvalue_kind = clk_none;
 
+  STRIP_ANY_LOCATION_WRAPPER (ref);
+
   /* Expressions of reference type are sometimes wrapped in
      INDIRECT_REFs.  INDIRECT_REFs are just internal compiler
      representation, not part of the language, so we have to look
-- 
1.8.5.3

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

* [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (6 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:46           ` Jason Merrill
  2017-11-10 21:44         ` [PATCH 09/14] Strip location wrappers in null_ptr_cst_p David Malcolm
                           ` (10 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This patch suppresses the user-visible printing of location wrappers
for "%E" (and "%qE"), adding test coverage via selftests.

Seen via a failure of g++.dg/parse/error34.C and g++.dg/parse/error35.C.

gcc/c-family/ChangeLog:
	* c-common.c (selftest::c_family_tests): Call
	selftest::c_pretty_print_c_tests.
	* c-common.h (selftest::c_pretty_print_c_tests): New decl.
	* c-pretty-print.c: Include "selftest.h".
	(pp_c_cast_expression): Don't print casts for location wrappers.
	(selftest::assert_c_pretty_printer_output): New function.
	(ASSERT_C_PRETTY_PRINTER_OUTPUT): New macro.
	(selftest::test_location_wrappers): New function.
	(selftest::c_pretty_print_c_tests): New function.
---
 gcc/c-family/c-common.c       |  1 +
 gcc/c-family/c-common.h       |  1 +
 gcc/c-family/c-pretty-print.c | 66 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 739c54e..bfcf7b9 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8126,6 +8126,7 @@ void
 c_family_tests (void)
 {
   c_format_c_tests ();
+  c_pretty_print_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 7e1877e..1f15762 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1559,6 +1559,7 @@ namespace selftest {
   /* Declarations for specific families of tests within c-family,
      by source file, in alphabetical order.  */
   extern void c_format_c_tests (void);
+  extern void c_pretty_print_c_tests (void);
 
   /* The entrypoint for running all of the above tests.  */
   extern void c_family_tests (void);
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 0f48b9e..fd4cf0e 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "intl.h"
 #include "tree-pretty-print.h"
+#include "selftest.h"
 
 /* The pretty-printer code is primarily designed to closely follow
    (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
@@ -1819,7 +1820,8 @@ pp_c_cast_expression (c_pretty_printer *pp, tree e)
     case FIX_TRUNC_EXPR:
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
-      pp_c_type_cast (pp, TREE_TYPE (e));
+      if (!location_wrapper_p (e))
+	pp_c_type_cast (pp, TREE_TYPE (e));
       pp_c_cast_expression (pp, TREE_OPERAND (e, 0));
       break;
 
@@ -2409,3 +2411,65 @@ pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t)
 
   pp_c_identifier (pp, name);
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for pretty-printing trees.  */
+
+/* Verify that EXPR printed by c_pretty_printer is EXPECTED, using
+   LOC as the effective location for any failures.  */
+
+static void
+assert_c_pretty_printer_output (const location &loc, const char *expected,
+				tree expr)
+{
+  c_pretty_printer pp;
+  pp.expression (expr);
+  ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
+}
+
+/* Helper function for calling assert_c_pretty_printer_output.
+   This is to avoid having to write SELFTEST_LOCATION.  */
+
+#define ASSERT_C_PRETTY_PRINTER_OUTPUT(EXPECTED, EXPR) \
+  SELFTEST_BEGIN_STMT						\
+    assert_c_pretty_printer_output ((SELFTEST_LOCATION),	\
+				    (EXPECTED),		\
+				    (EXPR));			\
+  SELFTEST_END_STMT
+
+/* Verify that location wrappers don't show up in pretty-printed output.  */
+
+static void
+test_location_wrappers ()
+{
+  /* VAR_DECL.  */
+  tree id = get_identifier ("foo");
+  tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id,
+			  integer_type_node);
+  tree wrapped_decl = maybe_wrap_with_location (decl, BUILTINS_LOCATION);
+  ASSERT_NE (wrapped_decl, decl);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", decl);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", wrapped_decl);
+
+  /* INTEGER_CST.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  tree wrapped_cst = maybe_wrap_with_location (int_cst, BUILTINS_LOCATION);
+  ASSERT_NE (wrapped_cst, int_cst);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", int_cst);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", wrapped_cst);
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+c_pretty_print_c_tests ()
+{
+  test_location_wrappers ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
-- 
1.8.5.3

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

* [PATCH 13/14] c-format.c: handle location wrappers
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (8 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 09/14] Strip location wrappers in null_ptr_cst_p David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:45           ` Jason Merrill
  2017-11-10 21:44         ` [PATCH 04/14] Update testsuite to show improvements David Malcolm
                           ` (8 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/c-family/ChangeLog:
	* c-format.c (check_format_arg): Strip any location wrapper around
	format_tree.
---
 gcc/c-family/c-format.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 164d035..6b436ec 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
+  STRIP_ANY_LOCATION_WRAPPER (format_tree);
+
   if (VAR_P (format_tree))
     {
       /* Pull out a constant value if the front end didn't.  */
@@ -1598,6 +1600,7 @@ check_format_arg (void *ctx, tree format_tree,
     }
   res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
   format_tree = TREE_OPERAND (format_tree, 0);
+  STRIP_ANY_LOCATION_WRAPPER (format_tree);
   if (format_types[info->format_type].flags 
       & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
     {
@@ -1634,7 +1637,10 @@ check_format_arg (void *ctx, tree format_tree,
   if (TREE_CODE (format_tree) == ARRAY_REF
       && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
       && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
-    format_tree = TREE_OPERAND (format_tree, 0);
+    {
+      format_tree = TREE_OPERAND (format_tree, 0);
+      STRIP_ANY_LOCATION_WRAPPER (format_tree);
+    }
   if (offset < 0)
     {
       res->number_non_literal++;
@@ -1650,6 +1656,7 @@ check_format_arg (void *ctx, tree format_tree,
 	 const char a[3] = "foo";).  */
       array_size = DECL_SIZE_UNIT (format_tree);
       format_tree = array_init;
+      STRIP_ANY_LOCATION_WRAPPER (format_tree);
     }
   if (TREE_CODE (format_tree) != STRING_CST)
     {
-- 
1.8.5.3

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

* [PATCH 04/14] Update testsuite to show improvements
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (9 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 13/14] c-format.c: handle location wrappers David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-11-10 21:44         ` [PATCH 11/14] Handle location wrappers in string_conv_p David Malcolm
                           ` (7 subsequent siblings)
  18 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/testsuite/ChangeLog:
	PR c++/43486
	* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
	to reflect that the arguments are correctly underlined.
	* g++.dg/plugin/diagnostic-test-expressions-1.C: Add test coverage
	for globals, params, locals and literals.
	(test_sizeof): Directly test the location of "sizeof", rather than
	when used in compound expressions.
	(test_alignof): Likewise for "alignof".
	(test_string_literals): Likewise for string literals.
	(test_numeric_literals): Likewise for numeric literals.
	(test_builtin_offsetof): Likewise for "__builtin_offsetof".
	(test_typeid): Likewise for typeid.
	(test_unary_plus): New.
---
 .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
 .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260 +++++++++++++--------
 2 files changed, 172 insertions(+), 115 deletions(-)

diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index bc3a938..5fcde0b 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -1,9 +1,6 @@
 // { dg-options "-fdiagnostics-show-caret" }
 
-/* A collection of calls where argument 2 is of the wrong type.
-
-   TODO: we should put the caret and underline for the diagnostic
-   at the second argument, rather than the close paren.  */
+/* A collection of calls where argument 2 is of the wrong type.  */
 
 /* decl, with argname.  */
 
@@ -14,7 +11,7 @@ int test_1 (int first, int second, float third)
   return callee_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_1 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
   /* { dg-begin-multiline-output "" }
@@ -32,7 +29,7 @@ int test_2 (int first, int second, float third)
   return callee_2 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_2 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
   /* { dg-begin-multiline-output "" }
@@ -53,7 +50,7 @@ int test_3 (int first, int second, float third)
   return callee_3 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_3 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
   /* { dg-begin-multiline-output "" }
@@ -71,7 +68,7 @@ int test_4 (int first, int second, float third)
   return s4::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s4::member_1 (first, second, third);
-                                            ^
+                               ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s4 { static int member_1 (int one, const char *two, float three); };
@@ -89,7 +86,7 @@ int test_5 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s5 { int member_1 (int one, const char *two, float three); };
@@ -106,7 +103,7 @@ int test_6 (int first, int second, float third, s6 *ptr)
   return ptr->member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return ptr->member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s6 { int member_1 (int one, const char *two, float three); };
@@ -128,7 +125,7 @@ int test_7 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
    return test_7 <const char *> (first, second, third);
-                                                     ^
+                                        ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  int test_7 (int one, T two, float three);
@@ -146,7 +143,7 @@ int test_8 (int first, int second, float third)
   return s8 <const char *>::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s8 <const char *>::member_1 (first, second, third);
-                                                           ^
+                                              ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s8 { static int member_1 (int one, T two, float three); };
@@ -165,7 +162,7 @@ int test_9 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s9 { int member_1 (int one, T two, float three); };
@@ -182,7 +179,7 @@ int test_10 (int first, int second, float third)
   return callee_10 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_10 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
   /* { dg-begin-multiline-output "" }
@@ -200,7 +197,7 @@ int test_11 (int first, int second, float third)
   return callee_11 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_11 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
   /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
index a145dfe..5e4d78b 100644
--- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
+++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
@@ -19,6 +19,113 @@ extern void __emit_expression_range (int dummy, ...);
 
 int global;
 
+void test_global (void)
+{
+  __emit_expression_range (0, global); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, global);
+                               ^~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_param (int param)
+{
+  __emit_expression_range (0, param); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, param);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_local (void)
+{
+  int local = 5;
+
+  __emit_expression_range (0, local); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, local);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_integer_constants (void)
+{
+  __emit_expression_range (0, 1234); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 1234);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  /* Ensure that zero works.  */
+
+  __emit_expression_range (0, 0); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 0);
+                               ^
+   { dg-end-multiline-output "" } */
+}
+
+void test_character_constants (void)
+{
+  __emit_expression_range (0, 'a'); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 'a');
+                               ^~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_floating_constants (void)
+{
+  __emit_expression_range (0, 98.6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, .6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, .6);
+                               ^~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.);
+                               ^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23 ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23 );
+                               ^~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.6f ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6f );
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23l ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23l );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+enum test_enum {
+  TEST_ENUM_VALUE
+};
+
+void test_enumeration_constant (void)
+{
+  __emit_expression_range (0, TEST_ENUM_VALUE ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, TEST_ENUM_VALUE );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
 void test_parentheses (int a, int b)
 {
   __emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
@@ -103,67 +210,36 @@ int test_postfix_incdec (int i)
 
 int test_sizeof (int i)
 {
-  __emit_expression_range (0, sizeof(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof(int) + i);
-                               ~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + sizeof(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof(int));
-                               ~~^~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, sizeof i + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof i ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof i + i);
-                               ~~~~~~~~~^~~
+   __emit_expression_range (0, sizeof i );
+                               ^~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, i + sizeof i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof (char) ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof i);
-                               ~~^~~~~~~~~~
+   __emit_expression_range (0, sizeof (char) );
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 int test_alignof (int i)
 {
-  __emit_expression_range (0, alignof(int) + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, alignof(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, alignof(int) + i);
-                               ~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + alignof(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + alignof(int));
-                               ~~^~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, __alignof__(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__(int) + i);
-                               ~~~~~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__(int));
-                               ~~^~~~~~~~~~~~~~~~~~
+   __emit_expression_range (0, alignof(int));
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, __alignof__ i + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__ i + i);
-                               ~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0, __alignof__(int));
+                               ^~~~~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__ i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__ i); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__ i);
-                               ~~^~~~~~~~~~~~~~~
+   __emit_expression_range (0, __alignof__ i);
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -200,6 +276,15 @@ void test_indirection (int *ptr)
    { dg-end-multiline-output "" } */
 }
 
+void test_unary_plus (int i)
+{
+  __emit_expression_range (0, +i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, +i );
+                               ^~
+   { dg-end-multiline-output "" } */
+}
+
 void test_unary_minus (int i)
 {
   __emit_expression_range (0, -i ); /* { dg-warning "range" } */
@@ -471,53 +556,36 @@ void test_comma_operator (int a, int b)
 
 /* Literals.  **************************************************/
 
-/* We can't test the ranges of literals directly, since the underlying
-   tree nodes don't retain a location.  However, we can test that they
-   have ranges during parsing by building compound expressions using
-   them, and verifying the ranges of the compound expressions.  */
-
-void test_string_literals (int i)
+void test_string_literals ()
 {
-  __emit_expression_range (0, "foo"[i] ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "0123456789"); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, "foo"[i] );
-                               ~~~~~~~^
+   __emit_expression_range (0, "0123456789");
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &"foo" "bar" ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "foo" "bar" ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &"foo" "bar" );
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, "foo" "bar" );
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 void test_numeric_literals (int i)
 {
-  __emit_expression_range (0, 42 + i ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, 42 + i );
-                               ~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + 42 ); /* { dg-warning "range" } */
+  __emit_expression_range (0, 42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + 42 );
-                               ~~^~~~
+   __emit_expression_range (0, 42 );
+                               ^~
    { dg-end-multiline-output "" } */
 
   /* Verify locations of negative literals (via folding of
      unary negation).  */
 
-  __emit_expression_range (0, -42 + i ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, -42 + i );
-                               ~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + -42 ); /* { dg-warning "range" } */
+  __emit_expression_range (0, -42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + -42 );
-                               ~~^~~~~
+   __emit_expression_range (0, -42 );
+                               ^~~
    { dg-end-multiline-output "" } */
 
   __emit_expression_range (0, i ? 0 : -1 ); /* { dg-warning "range" } */
@@ -529,6 +597,8 @@ void test_numeric_literals (int i)
 
 /* Braced initializers.  ***************************************/
 
+// FIXME:
+
 /* We can't test the ranges of these directly, since the underlying
    tree nodes don't retain a location.  However, we can test that they
    have ranges during parsing by building compound expressions using
@@ -556,6 +626,8 @@ void test_braced_init (void)
 
 /* Statement expressions.  ***************************************/
 
+// FIXME:
+
 void test_statement_expression (void)
 {
   __emit_expression_range (0, ({ static int a; a; }) + 1);  /* { dg-warning "range" } */
@@ -638,16 +710,10 @@ struct s { int i; float f; };
 
 void test_builtin_offsetof (int i)
 {
-  __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
+  __emit_expression_range (0,  __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );
-                                ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );  /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );
-                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0,  __builtin_offsetof (struct s, f) );
+                                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -856,28 +922,22 @@ namespace std
 
 void test_typeid (int i)
 {
-  __emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i));
-                               ^~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, &typeid(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(int));
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, typeid(i));
+                               ^~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i * 2));
-                               ^~~~~~~~~~~~~~
+   __emit_expression_range (0, typeid(int));
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i * 2)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, typeid(int).foo);
-                               ~~~~~~~~~~~~^~~
+   __emit_expression_range (0, typeid(i * 2));
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
-- 
1.8.5.3

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

* [PATCH 09/14] Strip location wrappers in null_ptr_cst_p
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (7 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:39           ` Jason Merrill
  2017-11-10 21:44         ` [PATCH 13/14] c-format.c: handle location wrappers David Malcolm
                           ` (9 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Without this, "NULL" fails to be usable in C++11 onwards.

gcc/cp/ChangeLog:
	* call.c (null_ptr_cst_p): Strip location wrappers when
	converting from '0' to a pointer type in C++11 onwards.
---
 gcc/cp/call.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6875492..e4a7f19 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -534,6 +534,8 @@ null_ptr_cst_p (tree t)
 
   if (cxx_dialect >= cxx11)
     {
+      STRIP_ANY_LOCATION_WRAPPER (t);
+
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && !char_type_p (type)
-- 
1.8.5.3

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

* [PATCH 10/14] warn_for_memset: handle location wrappers
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (11 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 11/14] Handle location wrappers in string_conv_p David Malcolm
@ 2017-11-10 21:44         ` David Malcolm
  2017-12-11 23:41           ` Jason Merrill
  2017-11-10 22:11         ` [PATCH 12/14] C++: introduce null_node_p David Malcolm
                           ` (5 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 21:44 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/c-family/ChangeLog:
	* c-warn.c (warn_for_memset): Strip any location wrappers
	from arg0 and arg2.

gcc/cp/ChangeLog:
	* parser.c (cp_parser_postfix_expression): Before warn_for_memset,
	strip any wrapper around "arg2" before testing for CONST_DECL.
---
 gcc/c-family/c-warn.c | 3 +++
 gcc/cp/parser.c       | 1 +
 2 files changed, 4 insertions(+)

diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 245c37d..67e6db6 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -1850,6 +1850,9 @@ void
 warn_for_memset (location_t loc, tree arg0, tree arg2,
 		 int literal_zero_mask)
 {
+  STRIP_ANY_LOCATION_WRAPPER (arg0);
+  STRIP_ANY_LOCATION_WRAPPER (arg2);
+
   if (warn_memset_transposed_args
       && integer_zerop (arg2)
       && (literal_zero_mask & (1 << 2)) != 0
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 54029ef..aee211f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7176,6 +7176,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		tree arg0 = (*args)[0];
 		tree arg1 = (*args)[1];
 		tree arg2 = (*args)[2];
+		STRIP_ANY_LOCATION_WRAPPER (arg2);
 		int literal_mask = ((!!integer_zerop (arg1) << 1)
 				    | (!!integer_zerop (arg2) << 2));
 		if (TREE_CODE (arg2) == CONST_DECL)
-- 
1.8.5.3

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

* [PATCH 12/14] C++: introduce null_node_p
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (12 preceding siblings ...)
  2017-11-10 21:44         ` [PATCH 10/14] warn_for_memset: handle location wrappers David Malcolm
@ 2017-11-10 22:11         ` David Malcolm
  2017-12-11 23:42           ` Jason Merrill
  2017-11-13 19:20         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
                           ` (4 subsequent siblings)
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-10 22:11 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Eschew comparison with null_node in favor of a new null_node_p
function, which strips any location wrappers.

All of these sites require the node to be non-NULL, with the
exception of the one in build_throw, hence the patch adds a
test for NULL before the call to non_null_p at that site, rather
than putting the test in null_node_p itself.

gcc/cp/ChangeLog:
	* call.c (conversion_null_warnings): Replace comparison with
	null_node with call to null_node_p.
	(build_over_call): Likewise.
	* cp-tree.h (null_node_p): New inline function.
	* cvt.c (build_expr_type_conversion): Replace comparison with
	null_node with call to null_node_p.
	* error.c (args_to_string): Likewise.
	* except.c (build_throw): Likewise.
	* typeck.c (cp_build_binary_op): Likewise.
---
 gcc/cp/call.c    | 4 ++--
 gcc/cp/cp-tree.h | 7 +++++++
 gcc/cp/cvt.c     | 2 +-
 gcc/cp/error.c   | 2 +-
 gcc/cp/except.c  | 2 +-
 gcc/cp/typeck.c  | 2 +-
 6 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4a7f19..a963dd4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6536,7 +6536,7 @@ static void
 conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
 {
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if (expr == null_node && TREE_CODE (totype) != BOOLEAN_TYPE
+  if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
       source_location loc =
@@ -7873,7 +7873,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
              func(NULL);
            }
       */
-      if (arg == null_node
+      if (null_node_p (arg)
           && DECL_TEMPLATE_INFO (fn)
           && cand->template_decl
           && !(flags & LOOKUP_EXPLICIT_TMPL_ARGS))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 726b6f5..8735e99 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7440,6 +7440,13 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+inline bool
+null_node_p (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+  return expr == null_node;
+}
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 9ce094e..b3a6f69 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1642,7 +1642,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   tree conv = NULL_TREE;
   tree winner = NULL_TREE;
 
-  if (expr == null_node
+  if (null_node_p (expr)
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
     {
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 2537713..d525103 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3193,7 +3193,7 @@ args_to_string (tree p, int verbose)
   reinit_cxx_pp ();
   for (; p; p = TREE_CHAIN (p))
     {
-      if (TREE_VALUE (p) == null_node)
+      if (null_node_p (TREE_VALUE (p)))
 	pp_cxx_ws_string (cxx_pp, "NULL");
       else
 	dump_type (cxx_pp, error_type (TREE_VALUE (p)), flags);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index ecc8941..30ab23d 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -577,7 +577,7 @@ build_throw (tree exp)
       return exp;
     }
 
-  if (exp == null_node)
+  if (exp && null_node_p (exp))
     warning (0, "throwing NULL, which has integral, not pointer type");
 
   if (exp != NULL_TREE)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 523e4d3..f139161 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4255,7 +4255,7 @@ cp_build_binary_op (location_t location,
     }
 
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if ((orig_op0 == null_node || orig_op1 == null_node)
+  if ((null_node_p (orig_op0) || null_node_p (orig_op1))
       /* It's reasonable to use pointer values as operands of &&
 	 and ||, so NULL is no exception.  */
       && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR 
-- 
1.8.5.3

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

* Re: [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486)
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (13 preceding siblings ...)
  2017-11-10 22:11         ` [PATCH 12/14] C++: introduce null_node_p David Malcolm
@ 2017-11-13 19:20         ` David Malcolm
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                           ` (3 subsequent siblings)
  18 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-13 19:20 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2017-11-10 at 16:45 -0500, David Malcolm wrote:
> On Thu, 2017-11-02 at 10:46 -0400, Jason Merrill wrote:
> > On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <dmalcolm@redhat.com
> > >
> > wrote:
> > > On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
> > > > On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat
> > > > .c
> > > > om>
> > > > wrote:
> > > > > Design questions:
> > > > > 
> > > > > * The patch introduces a new kind of tree node, currently
> > > > > called
> > > > >   DECL_WRAPPER_EXPR (although it's used for wrapping
> > > > > constants
> > > > > as
> > > > > well
> > > > >   as decls).  Should wrappers be a new kind of tree node, or
> > > > > should
> > > > > they
> > > > >   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR,
> > > > > etc).
> > > > >     * NOP_EXPR: seems to be for use as an rvalue
> > > > >     * CONVERT_EXPR: for type conversions
> > > > >     * NON_LVALUE_EXPR: "Value is same as argument, but
> > > > > guaranteed
> > > > > not an
> > > > >       lvalue"
> > > > >       * but we *do* want to support lvalues here
> > > > 
> > > > I think using NON_LVALUE_EXPR for constants would be
> > > > appropriate.
> > > > 
> > > > >     * VIEW_CONVERT_EXPR: viewing one thing as of a different
> > > > > type
> > > > >       * can it support lvalues?
> > > > 
> > > > Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it
> > > > seems
> > > > like the right choice.
> > > > 
> > > > Jason
> > > 
> > > Thanks.  I've been working on a new version of the patch using
> > > those
> > > tree codes, but have run into an issue.
> > > 
> > > In g++.dg/conversion/reinterpret1.C:
> > > 
> > >   // PR c++/15076
> > > 
> > >   struct Y { Y(int &); };
> > > 
> > >   int v;
> > >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > > 
> > > With trunk, this successfully generates an error:
> > > 
> > >   reinterpret1.C:6:6: error: cannot bind non-const lvalue
> > > reference
> > > of type ‘int&’ to an rvalue of type ‘int’
> > >    Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > >         ^~~~~~~~~~~~~~~~~~~~~~~~
> > >   reinterpret1.C:3:12: note:   initializing argument 1 of
> > > ‘Y::Y(int&)’
> > >    struct Y { Y(int &); };
> > >               ^
> > > 
> > > where internally there's a NON_LVALUE_EXPR around a VAR_DECL,
> > > where
> > > both have the same type:
> > > 
> > > (gdb) call debug_tree (expr)
> > >  <non_lvalue_expr 0x7ffff145f6e0
> > >     type <integer_type 0x7ffff132e5e8 int public type_6 SI
> > >         size <integer_cst 0x7ffff1331120 constant 32>
> > >         unit-size <integer_cst 0x7ffff1331138 constant 4>
> > >         align:32 warn_if_not_align:0 symtab:0 alias-set -1
> > > canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst
> > > 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0
> > > 2147483647>
> > >         pointer_to_this <pointer_type 0x7ffff1336a80>
> > > reference_to_this <reference_type 0x7ffff144ca80>>
> > > 
> > >     arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type
> > > 0x7ffff132e5e8 int>
> > >         used public static tree_1 read SI /home/david/coding-
> > > 3/gcc-
> > > git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5 size
> > > <integer_cst 0x7ffff1331120 32> unit-size <integer_cst
> > > 0x7ffff1331138 4>
> > >         align:32 warn_if_not_align:0 context
> > > <translation_unit_decl
> > > 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > >         chain <type_decl 0x7ffff141a720 Y type <record_type
> > > 0x7ffff144c150 Y>
> > >             public decl_2 VOID /home/david/coding-3/gcc-git-expr-
> > > vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
> > >             align:8 warn_if_not_align:0 context
> > > <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-
> > > git-
> > > expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > > chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
> > >     /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > start:
> > > /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > finish:
> > > /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
> > > 
> > > The problem is that this reinterpret cast "looks" just like one
> > > of
> > > my
> > > location wrappers.
> > 
> > Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.
> > > I see a similar issue with constants, where with:
> > > 
> > >   struct Y { Y(int &); };
> > >   Y y1(reinterpret_cast<int>(42));
> > > 
> > > trunk generates an error like the above, but my code handles the
> > >   NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> > > as if it were a location wrapper around the INTEGER_CST, and thus
> > > doesn't emit the error.
> > 
> > Why doesn't it emit the error?  We should get the same error
> > whether
> > or not we strip the wrapper.
> 
> Thanks: my stripping macro was over-zealous: it was stripping any
> NON_LVALUE_EXPR or VIEW_CONVERT_EXPR where the type matched that of
> the wrapped node.  I've added the additional condition that a
> NON_LVALUE_EXPR has to be around a CONSTANT_CLASS_P, and
> a VIEW_CONVERT_EXPR around a !CONSTANT_CLASS_P.
> 
> Here's an updated version of the patch (v2), now a patch kit (on top
> of r254387).  I split it up thematically for ease of review, but all
> the patches go together.
> 
> This version of the patch kit bootstraps and passes the regression
> tests (on x86_64-pc-linux-gnu)
> 
> To do so, I've made some simplfications to how wrappers nodes are
> added.
> 
> The previous patch added wrappers in the C++ parser around constants
> and uses-of-declarations, along with some other places in the
> parser (typeid, alignof, sizeof, offsetof).
> 
> This version takes a much more minimal approach: it only adds
> location wrapper nodes around the arguments at callsites, thus
> not adding wrapper nodes around uses of constants and decls in other
> locations.
> 
> It keeps them for the other places in the parser (typeid, alignof,
> sizeof, offsetof).
> 
> In addition, for now, each site that adds wrapper nodes is guarded
> with !processing_template_decl, suppressing the creation of wrapper
> nodes when processing template declarations.  This is to simplify
> the patch kit so that we don't have to support wrapper nodes during
> template expansion.
> 
> With this, we get a big usability win: we always have a location_t
> for every argument at a callsite, and so various errors involving
> mismatching arguments are much easier to read (as the pertinent
> argument is underlined).
> 
> I marked this as "PR 43486" as it's a big step towards solving that
> PR (which seeks to preserve locations all the way through to the
> middle end), but much more would need to be done to solve it:
> 
> * this patch kit only adds wrappers to the C++ frontend, not to C
> 
> * as noted above, location_t wrapper nodes are only added at
>   arguments of callsites (and a few other places), with some
>   restrictions.
> 
> * none of the wrapper nodes survive past gimplification;
>   it's not clear to me how best to preserve them into the
>   middle-end.  But even without doing so, we get the big usability
>   win.
> 
> The later parts of the patch kit add STRIP_ANY_LOCATION_WRAPPER uses
> in various places where the tree code of an expression is examined,
> so that such conditions use the code of the wrapped node, rather
> than that of the wrapper.  One of the risks of the patch kit is that
> although the testsuite passes, there are probably places in our code
> which still need uses of STRIP_ANY_LOCATION_WRAPPER.
> 
> 
> Performance of the patch kit
> ****************************
> 
> Benchmarking shows an apparent 2-3% in cc1plus wallclock compile-time
> for kdecore.cc -O3 -g:
> 
> Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu:
> wall
>       control: [56.55, 56.54, 56.68, 56.51, 56.45, 56.5, 56.45,
> 56.46, 56.49, 56.5, 56.42, 56.37, 56.41, 56.55]
>    experiment: [57.32, 58.37, 58.17, 58.18, 58.78, 58.48, 57.99,
> 58.16, 58.14, 57.62, 58.36, 58.1, 57.71, 57.7]
> Min: 56.370000 -> 57.320000: 1.02x slower
> Avg: 56.491429 -> 58.077143: 1.03x slower
> Significant (t=-15.14)
> Stddev: 0.07655 -> 0.38426: 5.0199x larger
> 
> although I'm not quite sure why; the difference is in "phase setup",
> which
> gains a large "wall" value (but not in usr or sys), whereas "phase
> parsing"
> is unaffected:
> 
> unpatched:
> 
>  phase setup             :   0.00 ( 0%) usr   0.02 ( 0%) sys   0.02 (
> 0%) wall    1488 kB ( 0%) ggc
>  phase parsing           :   1.83 ( 4%) usr   0.82 (16%) sys   2.66 (
> 5%) wall  156603 kB (12%) ggc
>  phase lang. deferred    :   0.30 ( 1%) usr   0.09 ( 2%) sys   0.38 (
> 1%) wall   29861 kB ( 2%) ggc
>  phase opt and generate  :  48.09 (94%) usr   4.28 (81%) sys  52.55
> (93%) wall 1085420 kB (84%) ggc
>  phase last asm          :   0.86 ( 2%) usr   0.05 ( 1%) sys   0.92 (
> 2%) wall   15806 kB ( 1%) ggc
>  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.01 (
> 0%) wall       0 kB ( 0%) ggc
>  |name lookup            :   0.30 ( 1%) usr   0.13 ( 2%) sys   0.21 (
> 0%) wall    4955 kB ( 0%) ggc
>  |overload resolution    :   0.49 ( 1%) usr   0.06 ( 1%) sys   0.68 (
> 1%) wall   27263 kB ( 2%) ggc
>  garbage collection      :   0.77 ( 2%) usr   0.00 ( 0%) sys   0.77 (
> 1%) wall       0 kB ( 0%) ggc
>  [...]
>  TOTAL                 :  51.08             5.27            56.54    
>         1289189 kB
> 
> patched:
>  phase setup             :   0.01 ( 0%) usr   0.03 ( 1%) sys   1.91 (
> 3%) wall    1488 kB ( 0%) ggc
>  phase parsing           :   1.80 ( 4%) usr   0.84 (16%) sys   2.66 (
> 5%) wall  158066 kB (12%) ggc
>  phase lang. deferred    :   0.29 ( 1%) usr   0.09 ( 2%) sys   0.39 (
> 1%) wall   29861 kB ( 2%) ggc
>  phase opt and generate  :  48.09 (94%) usr   4.27 (81%) sys  52.52
> (90%) wall 1085428 kB (84%) ggc
>  phase last asm          :   0.82 ( 2%) usr   0.05 ( 1%) sys   0.89 (
> 2%) wall   15806 kB ( 1%) ggc
>  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.00 (
> 0%) wall       0 kB ( 0%) ggc
>  |name lookup            :   0.29 ( 1%) usr   0.07 ( 1%) sys   0.36 (
> 1%) wall    4955 kB ( 0%) ggc
>  |overload resolution    :   0.51 ( 1%) usr   0.07 ( 1%) sys   0.50 (
> 1%) wall   27296 kB ( 2%) ggc
>  garbage collection      :   0.79 ( 2%) usr   0.00 ( 0%) sys   0.78 (
> 1%) wall       0 kB ( 0%) ggc
>  TOTAL                 :  51.01             5.29            58.37    
>         1290660 kB
> 
> What's up with that "phase setup" change?  Did I mess up my testing
> somehow?


I had used taskset to pin everything onto one processor.  On using
"echo 3 > /proc/sys/vm/drop_caches" and rerunning, after a warmup, the
slowdown moved to the unpatched binary, with the patched binary
becoming faster.  My theory is that this is NUMA-related, and that the
buffer cache's copy of the binaries can end up on the "wrong" NUMA
node.  Depending on which I run first, I can make the patched or
unpatched binary faster (based on this slowdown of "wall" seen in
"phase setup").

Speed differences in the "parsing" phase are lost in the noise e.g.:

Compilation of cp-stdlib.cc at -O3 with -g for x86_64-pc-linux-gnu: phase parsing: usr
      control: [2.2, 2.25, 2.27, 2.25, 2.23, 2.22, 2.37, 2.23, 2.22, 2.23, 2.25, 2.21, 2.21, 2.26, 2.23, 2.26, 2.26, 2.23, 2.22, 2.25]
   experiment: [2.22, 2.26, 2.26, 2.2, 2.25, 2.2, 2.21, 2.17, 2.25, 2.23, 2.21, 2.21, 2.2, 2.2, 2.25, 2.28, 2.19, 2.2, 2.24, 2.24]
Min: 2.200000 -> 2.170000: 1.01x faster
Avg: 2.242500 -> 2.223500: 1.01x faster
Stddev: 0.03582 -> 0.02889: 1.2399x smaller
Timeline: http://chart.apis.google.com/chart?cht=lc&chs=700x400&chxt=x,y,x,y&chxr=1,1.17,3.37&chco=FF0000,0000FF&chdl=control|experiment&chds=1.17,3.37&chd=t:2.2,2.25,2.27,2.25,2.23,2.22,2.37,2.23,2.22,2.23,2.25,2.21,2.21,2.26,2.23,2.26,2.26,2.23,2.22,2.25|2.22,2.26,2.26,2.2,2.25,2.2,2.21,2.17,2.25,2.23,2.21,2.21,2.2,2.2,2.25,2.28,2.19,2.2,2.24,2.24&chxl=0:|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|2:||Iteration|3:||Time+(secs)&chtt=Compilation+of+cp-stdlib.cc+at+-O3+with+-g+for+x86_64-pc-linux-gnu:+phase+parsing:+usr


Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu: phase parsing: usr
      control: [2.66, 2.61, 2.65, 2.69, 2.62, 2.67, 2.63, 2.6, 2.68, 2.67, 2.64, 2.67, 2.66, 2.67, 2.65, 2.64, 2.69, 2.68, 2.67, 2.67]
   experiment: [2.64, 2.66, 2.7, 2.69, 2.71, 2.67, 2.67, 2.73, 2.68, 2.64, 2.66, 2.71, 2.66, 2.68, 2.66, 2.66, 2.66, 2.72, 2.64, 2.68]
Min: 2.600000 -> 2.640000: 1.02x slower
Avg: 2.656000 -> 2.676000: 1.01x slower
Stddev: 0.02563 -> 0.02664: 1.0393x larger
Timeline: http://chart.apis.google.com/chart?cht=lc&chs=700x400&chxt=x,y,x,y&chxr=1,1.6,3.73&chco=FF0000,0000FF&chdl=control|experiment&chds=1.6,3.73&chd=t:2.66,2.61,2.65,2.69,2.62,2.67,2.63,2.6,2.68,2.67,2.64,2.67,2.66,2.67,2.65,2.64,2.69,2.68,2.67,2.67|2.64,2.66,2.7,2.69,2.71,2.67,2.67,2.73,2.68,2.64,2.66,2.71,2.66,2.68,2.66,2.66,2.66,2.72,2.64,2.68&chxl=0:|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|2:||Iteration|3:||Time+(secs)&chtt=Compilation+of+kdecore.cc+at+-O3+with+-g+for+x86_64-pc-linux-gnu:+phase+parsing:+usr


> ...and a slight increase in GGC usage:
> 
> Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu: ggc
>       control: [1289179.0, 1289189.0, 1289170.0, 1289186.0,
> 1289194.0, 1289172.0, 1289176.0, 1289192.0, 1289189.0, 1289179.0,
> 1289172.0, 1289190.0, 1289169.0, 1289185.0]
>    experiment: [1290654.0, 1290660.0, 1290655.0, 1290659.0,
> 1290631.0, 1290655.0, 1290650.0, 1290652.0, 1290642.0, 1290650.0,
> 1290658.0, 1290662.0, 1290638.0, 1290655.0]
> Mem max: 1289194.000 -> 1290662.000: 1.0011x larger
> 
> (this is with stripped binaries, and --enable-checking=release)
> 
> Testing with a simple file that includes all of the C++ standard
> library
> (but doesn't do anything with it) shows no change in time, and GGC
> usage
> in the parsing phase increasing 50kB from 149954 kB to 150004 kB.
> 
> 
> Next steps?
> ***********
> 
> I'm working on extending the patch kit to add wrapper nodes at all
> constants and uses-of-decls in the C++ parser, but of course this
> could have some effect on time/memory, and require more uses of
> STRIP_ANY_LOCATION_WRAPPER.
> 
> An alternative appoach is:
> 
>   "[PATCH] C++: use an optional vec<location_t> for callsites"
>     https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
> 
> which eschews wrapper nodes in favor of duplicating the C frontend's
> workaround here (though Jason disliked this approach, when we
> discussed
> it at Cauldron).
> 
> Thoughts?
> 
> (I'm keen on getting *some* solution for providing location_t values
> for arguments at C++ callsites into gcc 8)
> 
> 
> David Malcolm (14):
>   C++: preserve locations within build_address
>   Support for adding and stripping location_t wrapper nodes
>   C++: add location_t wrapper nodes during parsing (minimal impl)
>   Update testsuite to show improvements
>   tree.c: strip location wrappers from integer_zerop etc
>   Fix Wsizeof-pointer-memaccess*.c
>   reject_gcc_builtin: strip any location wrappers
>   cp/tree.c: strip location wrappers in lvalue_kind
>   Strip location wrappers in null_ptr_cst_p
>   warn_for_memset: handle location wrappers
>   Handle location wrappers in string_conv_p
>   C++: introduce null_node_p
>   c-format.c: handle location wrappers
>   pp_c_cast_expression: don't print casts for location wrappers
> 
>  gcc/c-family/c-common.c                            |   3 +
>  gcc/c-family/c-common.h                            |   1 +
>  gcc/c-family/c-format.c                            |   9 +-
>  gcc/c-family/c-pretty-print.c                      |  66 +++++-
>  gcc/c-family/c-warn.c                              |   8 +
>  gcc/cp/call.c                                      |   6 +-
>  gcc/cp/cp-tree.h                                   |  13 ++
>  gcc/cp/cvt.c                                       |   2 +-
>  gcc/cp/error.c                                     |   2 +-
>  gcc/cp/except.c                                    |   2 +-
>  gcc/cp/parser.c                                    |  30 ++-
>  gcc/cp/tree.c                                      |   2 +
>  gcc/cp/typeck.c                                    |   6 +-
>  .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
>  .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260
> +++++++++++++--------
>  gcc/tree.c                                         |  59 +++++
>  gcc/tree.h                                         |  26 +++
>  17 files changed, 392 insertions(+), 130 deletions(-)
> 

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

* Re: [PATCH 02/14] Support for adding and stripping location_t wrapper nodes
  2017-11-10 21:43         ` [PATCH 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
@ 2017-11-15  6:31           ` Trevor Saunders
  2017-11-15 11:23             ` Richard Biener
  0 siblings, 1 reply; 111+ messages in thread
From: Trevor Saunders @ 2017-11-15  6:31 UTC (permalink / raw)
  To: David Malcolm
  Cc: Jason Merrill, Nathan Sidwell, Jakub Jelinek, Richard Biener,
	gcc-patches List

On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
> 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, along with a new method of cp_expr.
> 
> It's called in later patches in the kit via that new method.
> 
> 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.

I happened to start reading this series near the end and was rather
confused by this macro since it changes variables in a rather unhygienic
way.  Did you consider just defining a inline function to return the
actual decl?  It seems like its not used that often so the slight extra
syntax should be that big a deal compared to the explicitness.

Other than that the series seems reasonable, and I look forward to
having wrappers in more places.  I seem to remember something I wanted
to warn about they would make much easier.

Thanks

Trev

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

* Re: [PATCH 02/14] Support for adding and stripping location_t wrapper nodes
  2017-11-15  6:31           ` Trevor Saunders
@ 2017-11-15 11:23             ` Richard Biener
  2017-11-15 15:40               ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Richard Biener @ 2017-11-15 11:23 UTC (permalink / raw)
  To: Trevor Saunders
  Cc: David Malcolm, Jason Merrill, Nathan Sidwell, Jakub Jelinek,
	gcc-patches List

On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tbsaunde.org> wrote:
> On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
>> 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, along with a new method of cp_expr.
>>
>> It's called in later patches in the kit via that new method.
>>
>> 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.
>
> I happened to start reading this series near the end and was rather
> confused by this macro since it changes variables in a rather unhygienic
> way.  Did you consider just defining a inline function to return the
> actual decl?  It seems like its not used that often so the slight extra
> syntax should be that big a deal compared to the explicitness.

Existing practice .... (STRIP_NOPS & friends).  I'm fine either way,
the patch looks good.

Eventually you can simplify things by doing less checking in
location_wrapper_p, like only checking

+inline bool location_wrapper_p (const_tree exp)
+{
+  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
+       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+          && (TREE_TYPE (exp)
+                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
+    return true;
+  return false;
+}

and renaming to maybe_location_wrapper_p.  After all you can't really
distinguish location wrappers from non-location wrappers?  (and why
would you want to?)

Thanks,
Richard.

> Other than that the series seems reasonable, and I look forward to
> having wrappers in more places.  I seem to remember something I wanted
> to warn about they would make much easier.
>
> Thanks
>
> Trev
>

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

* Re: [PATCH 02/14] Support for adding and stripping location_t wrapper nodes
  2017-11-15 11:23             ` Richard Biener
@ 2017-11-15 15:40               ` David Malcolm
  2017-11-16 10:04                 ` Richard Biener
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-15 15:40 UTC (permalink / raw)
  To: Richard Biener, Trevor Saunders
  Cc: Jason Merrill, Nathan Sidwell, Jakub Jelinek, gcc-patches List

On Wed, 2017-11-15 at 12:11 +0100, Richard Biener wrote:
> On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tbsaunde.o
> rg> wrote:
> > On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
> > > 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, along with a new method of cp_expr.
> > > 
> > > It's called in later patches in the kit via that new method.
> > > 
> > > 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.
> > 
> > I happened to start reading this series near the end and was rather
> > confused by this macro since it changes variables in a rather
> > unhygienic
> > way.  Did you consider just defining a inline function to return
> > the
> > actual decl?  It seems like its not used that often so the slight
> > extra
> > syntax should be that big a deal compared to the explicitness.
> 
> Existing practice .... (STRIP_NOPS & friends).  I'm fine either way,
> the patch looks good.
> 
> Eventually you can simplify things by doing less checking in
> location_wrapper_p, like only checking
> 
> +inline bool location_wrapper_p (const_tree exp)
> +{
> +  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
> +       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
> +          && (TREE_TYPE (exp)
> +                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
> +    return true;
> +  return false;
> +}
> 
> and renaming to maybe_location_wrapper_p.  After all you can't really
> distinguish location wrappers from non-location wrappers?  (and why
> would you want to?)

That's the implementation I originally tried.

As noted in an earlier thread about this, the problem I ran into was
(in g++.dg/conversion/reinterpret1.C):

  // PR c++/15076

  struct Y { Y(int &); };

  int v;
  Y y1(reinterpret_cast<int>(v));  // { dg-error "" }

where the "reinterpret_cast<int>" has the same type as the VAR_DECL v,
and hence the argument to y1 is a NON_LVALUE_EXPR around a VAR_DECL,
where both have the same type, and hence location_wrapper_p () on the
cast would return true.

Compare with:

  Y y1(v);

where the argument "v" with a location wrapper is a VIEW_CONVERT_EXPR
around a VAR_DECL.

With the simpler conditions you suggested above, both are treated as
location wrappers (leading to the dg-error in the test failing),
whereas with the condition in the patch, only the latter is treated as
a location wrapper, and an error is correctly emitted for the dg-error.

Hope this sounds sane.  Maybe the function needs a more detailed
comment explaining this?

Thanks
Dave


> Thanks,
> Richard.
> 
> > Other than that the series seems reasonable, and I look forward to
> > having wrappers in more places.  I seem to remember something I
> > wanted
> > to warn about they would make much easier.
> > 
> > Thanks
> > 
> > Trev
> > 

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

* Re: [PATCH 02/14] Support for adding and stripping location_t wrapper nodes
  2017-11-15 15:40               ` David Malcolm
@ 2017-11-16 10:04                 ` Richard Biener
  2017-11-30 17:25                   ` [PATCH v2.1] " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Richard Biener @ 2017-11-16 10:04 UTC (permalink / raw)
  To: David Malcolm
  Cc: Trevor Saunders, Jason Merrill, Nathan Sidwell, Jakub Jelinek,
	gcc-patches List

On Wed, Nov 15, 2017 at 4:33 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Wed, 2017-11-15 at 12:11 +0100, Richard Biener wrote:
>> On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tbsaunde.o
>> rg> wrote:
>> > On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
>> > > 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, along with a new method of cp_expr.
>> > >
>> > > It's called in later patches in the kit via that new method.
>> > >
>> > > 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.
>> >
>> > I happened to start reading this series near the end and was rather
>> > confused by this macro since it changes variables in a rather
>> > unhygienic
>> > way.  Did you consider just defining a inline function to return
>> > the
>> > actual decl?  It seems like its not used that often so the slight
>> > extra
>> > syntax should be that big a deal compared to the explicitness.
>>
>> Existing practice .... (STRIP_NOPS & friends).  I'm fine either way,
>> the patch looks good.
>>
>> Eventually you can simplify things by doing less checking in
>> location_wrapper_p, like only checking
>>
>> +inline bool location_wrapper_p (const_tree exp)
>> +{
>> +  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
>> +       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
>> +          && (TREE_TYPE (exp)
>> +                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
>> +    return true;
>> +  return false;
>> +}
>>
>> and renaming to maybe_location_wrapper_p.  After all you can't really
>> distinguish location wrappers from non-location wrappers?  (and why
>> would you want to?)
>
> That's the implementation I originally tried.
>
> As noted in an earlier thread about this, the problem I ran into was
> (in g++.dg/conversion/reinterpret1.C):
>
>   // PR c++/15076
>
>   struct Y { Y(int &); };
>
>   int v;
>   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
>
> where the "reinterpret_cast<int>" has the same type as the VAR_DECL v,
> and hence the argument to y1 is a NON_LVALUE_EXPR around a VAR_DECL,
> where both have the same type, and hence location_wrapper_p () on the
> cast would return true.
>
> Compare with:
>
>   Y y1(v);
>
> where the argument "v" with a location wrapper is a VIEW_CONVERT_EXPR
> around a VAR_DECL.
>
> With the simpler conditions you suggested above, both are treated as
> location wrappers (leading to the dg-error in the test failing),
> whereas with the condition in the patch, only the latter is treated as
> a location wrapper, and an error is correctly emitted for the dg-error.
>
> Hope this sounds sane.  Maybe the function needs a more detailed
> comment explaining this?

Yes.  I guess the above would argue for a new tree code but I can
see that it is better to avoid that.

Thanks,
Richard.

> Thanks
> Dave
>
>
>> Thanks,
>> Richard.
>>
>> > Other than that the series seems reasonable, and I look forward to
>> > having wrappers in more places.  I seem to remember something I
>> > wanted
>> > to warn about they would make much easier.
>> >
>> > Thanks
>> >
>> > Trev
>> >

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

* [PATCH 02/11] cp_tree::maybe_add_location_wrapper: no-op for template decls
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
  2017-11-18  2:50           ` [PATCH 06/11] gcc: Handle location wrappers in operand_equal_p David Malcolm
@ 2017-11-18  2:50           ` David Malcolm
  2017-11-18  2:50           ` [PATCH 01/11] C++: Add location wrappers for all constants and decls David Malcolm
                             ` (8 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

For simplicity, add a gate on !processing_template_decl
to cp_tree::maybe_add_location_wrapper.

gcc/cp/ChangeLog:
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): Do nothing if
	processing_template_decl.
---
 gcc/cp/cp-tree.h | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 03087f0..63e9bff 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -93,11 +93,7 @@ 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;
-  }
+  cp_expr& maybe_add_location_wrapper ();
 
  private:
   tree m_value;
@@ -1642,6 +1638,16 @@ struct warning_sentinel
   ~warning_sentinel() { flag = val; }
 };
 
+inline cp_expr&
+cp_expr::maybe_add_location_wrapper ()
+{
+  /* For now, don't add wrappers when processing template decls.  */
+  if (!processing_template_decl)
+    m_value = maybe_wrap_with_location (m_value, m_loc);
+  return *this;
+}
+
+
 /* The cached class binding level, from the most recently exited
    class, or NULL if none.  */
 
-- 
1.8.5.3

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

* [PATCH 03/11] Implement STRIP_ANY_LOCATION_WRAPPER_SAFE
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (2 preceding siblings ...)
  2017-11-18  2:50           ` [PATCH 01/11] C++: Add location wrappers for all constants and decls David Malcolm
@ 2017-11-18  2:50           ` David Malcolm
  2017-11-18  2:51           ` [PATCH 04/11] C++: add cp_expr::strip_any_location_wrapper method David Malcolm
                             ` (6 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

We occasionally need to handle the NULL case when stripping trees,
so this patch introduces a variant of STRIP_ANY_LOCATION_WRAPPER to
do so.

gcc/ChangeLog:
	* tree.h (STRIP_ANY_LOCATION_WRAPPER_SAFE): New macro.
---
 gcc/tree.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/gcc/tree.h b/gcc/tree.h
index 9a0bd60..98acc8b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -492,6 +492,14 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
       (EXP) = TREE_OPERAND ((EXP), 0);	\
   } while (0)
 
+/* As STRIP_ANY_LOCATION_WRAPPER, but handle NULL_TREE.  */
+
+#define STRIP_ANY_LOCATION_WRAPPER_SAFE(EXP) \
+  do {					\
+    if ((EXP) && location_wrapper_p (EXP))	\
+      (EXP) = TREE_OPERAND ((EXP), 0);		\
+  } while (0)
+
 /* Nonzero if TYPE represents a vector type.  */
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
-- 
1.8.5.3

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

* [RFC v3 00/11] C++: locations for (almost) everything (PR 43486)
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (14 preceding siblings ...)
  2017-11-13 19:20         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
@ 2017-11-18  2:50         ` David Malcolm
  2017-11-18  2:50           ` [PATCH 06/11] gcc: Handle location wrappers in operand_equal_p David Malcolm
                             ` (10 more replies)
  2017-11-30 20:54         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
                           ` (2 subsequent siblings)
  18 siblings, 11 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Here's a follow-up patch kit to v2 which extends the C++ FE to capture
source location information for *all* constants and uses-of-decls,
not just at callsites like v2 does.

I kept the simplifying restriction of not adding wrapper nodes when
processing_template_decl.

Unfortunately it's not complete, but given that the end of stage 1
is on us, I thought I'd post what I have.

Much of the kit involves stripping away the wrapper nodes whenever
we need to look at the TREE_CODE of an expression.

Limitations:
* it doesn't bootstrap yet; with a --disable-bootstrap build the
  regression tests mostly work (332 new FAILs on x86_64-pc-linux-gnu,
  out of ~330k tests).  I've been frantically trying to fix all of
  these, but I seem to be reaching the harder issues and it's clear
  I'm not going to be done.

* only tested so far on x86_64-pc-linux-gnu; I'm fairly sure there
  are target-specific attribute handlers that would need fixing.

* no performance data yet.

* the kit doesn't *use* the locations.  There are dozens of
  diagnostics that are implicitly using input_location, which could
  be improved by using an EXPR_LOCATION, given that we'd be able to
  guarantee that we had locations for every expression, which would
  give lots of little usability wins.

...but it looks like I'm out of time for gcc8 stage1.

Does this approach look promising for gcc 9?

For gcc 8, I'd like to ensure that we have location_t values
for all arguments at C++ callsites; the v2 version of the kit would
do that, alternatively there's the:

  "[PATCH] C++: use an optional vec<location_t> for callsites"
    https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html

approach.

Thoughts?
Dave

David Malcolm (11):
  C++: Add location wrappers for all constants and decls
  cp_tree::maybe_add_location_wrapper: no-op for template decls
  Implement STRIP_ANY_LOCATION_WRAPPER_SAFE
  C++: add cp_expr::strip_any_location_wrapper method
  C++: finish_call_expr: strip location wrapper
  gcc: Handle location wrappers in operand_equal_p
  c-family: handle location wrappers
  C++: handle location wrappers
  objc: handle location wrappers in objc_maybe_build_component_ref
  i386: handle location wrappers in ix86_handle_cconv_attribute
  config: handle location wrappers in various attributes (untested)

 gcc/c-family/c-attribs.c       |   1 +
 gcc/c-family/c-common.c        |   9 ++++
 gcc/c-family/c-format.c        |   2 +
 gcc/c-family/c-warn.c          |  25 ++++++----
 gcc/config/arc/arc.c           |   2 +
 gcc/config/epiphany/epiphany.c |   3 ++
 gcc/config/i386/i386.c         |   1 +
 gcc/config/ia64/ia64.c         |   1 +
 gcc/config/m32r/m32r.c         |   2 +
 gcc/config/mips/mips.c         |   2 +
 gcc/config/msp430/msp430.c     |   2 +-
 gcc/config/s390/s390.c         |   2 +
 gcc/cp/call.c                  |   7 +++
 gcc/cp/class.c                 |   1 +
 gcc/cp/constexpr.c             |   1 +
 gcc/cp/cp-tree.h               |  17 +++++--
 gcc/cp/cvt.c                   |   1 +
 gcc/cp/decl.c                  |   4 ++
 gcc/cp/expr.c                  |   2 +
 gcc/cp/lambda.c                |   3 ++
 gcc/cp/name-lookup.c           |   1 +
 gcc/cp/parser.c                |  94 +++++++++++++++++++++----------------
 gcc/cp/pt.c                    |  10 +++-
 gcc/cp/semantics.c             | 102 +++++++++++++++++++++++++++++------------
 gcc/cp/tree.c                  |   8 ++++
 gcc/cp/typeck.c                |  25 ++++++++--
 gcc/cp/typeck2.c               |   4 ++
 gcc/fold-const.c               |   3 ++
 gcc/objc/objc-act.c            |   2 +
 gcc/tree.c                     |   1 +
 gcc/tree.h                     |   8 ++++
 31 files changed, 260 insertions(+), 86 deletions(-)

-- 
1.8.5.3

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

* [PATCH 01/11] C++: Add location wrappers for all constants and decls
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
  2017-11-18  2:50           ` [PATCH 06/11] gcc: Handle location wrappers in operand_equal_p David Malcolm
  2017-11-18  2:50           ` [PATCH 02/11] cp_tree::maybe_add_location_wrapper: no-op for template decls David Malcolm
@ 2017-11-18  2:50           ` David Malcolm
  2017-11-18  2:50           ` [PATCH 03/11] Implement STRIP_ANY_LOCATION_WRAPPER_SAFE David Malcolm
                             ` (7 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This redoes the approach in the v1 patch, doing it for all constants
and decls, rather than just at callsite args.

gcc/cp/ChangeLog:
	* parser.c (cp_parser_primary_expression): Add location wrappers
	to constants.
	(cp_parser_postfix_expression): Remove the "wrap_locations_p"
	param to cp_parser_parenthesized_expression_list from the earlier
	patch.
	(cp_parser_parenthesized_expression_list): Likewise; don't add
	location wrappers.
	* semantics.c (finish_id_expression): Rename to...
	(finish_id_expression_1): ...this.
	(finish_id_expression): Reintroduce, wrapping the result in a
	location wrapper, if necessary.
---
 gcc/cp/parser.c    | 29 ++++++++++++----------------
 gcc/cp/semantics.c | 56 ++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 15489c1..8834542 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2054,8 +2054,7 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
-   bool = false);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -5066,7 +5065,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  if (!cast_p)
 	    cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
 	}
-      return cp_expr (token->u.value, token->location);
+      return (cp_expr (token->u.value, token->location)
+	      .maybe_add_location_wrapper ());
 
     case CPP_CHAR_USERDEF:
     case CPP_CHAR16_USERDEF:
@@ -5088,9 +5088,10 @@ cp_parser_primary_expression (cp_parser *parser,
       /* ??? Should wide strings be allowed when parser->translate_strings_p
 	 is false (i.e. in attributes)?  If not, we can kill the third
 	 argument to cp_parser_string_literal.  */
-      return cp_parser_string_literal (parser,
-				       parser->translate_strings_p,
-				       true);
+      return (cp_parser_string_literal (parser,
+					parser->translate_strings_p,
+					true)
+	      .maybe_add_location_wrapper ());
 
     case CPP_OPEN_PAREN:
       /* If we see `( { ' then we are looking at the beginning of
@@ -7099,8 +7100,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc,
-		     /*wrap_locations_p=*/true));
+		     /*close_paren_loc=*/&close_paren_loc));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7764,8 +7764,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc,
-					 bool wrap_locations_p)
+					 location_t *close_paren_loc)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7788,12 +7787,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
-  cp_expr expr (NULL_TREE);
-
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
+	tree expr;
+
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7847,15 +7846,11 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
-	    if (wrap_locations_p)
-	      if (!processing_template_decl)
-		expr.maybe_add_location_wrapper ();
-
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr.get_value ());
+	    vec_safe_push (expression_list, expr);
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 51489d1..dfdc458 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3453,20 +3453,20 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-cp_expr
-finish_id_expression (tree id_expression,
-		      tree decl,
-		      tree scope,
-		      cp_id_kind *idk,
-		      bool integral_constant_expression_p,
-		      bool allow_non_integral_constant_expression_p,
-		      bool *non_integral_constant_expression_p,
-		      bool template_p,
-		      bool done,
-		      bool address_p,
-		      bool template_arg_p,
-		      const char **error_msg,
-		      location_t location)
+static cp_expr
+finish_id_expression_1 (tree id_expression,
+			tree decl,
+			tree scope,
+			cp_id_kind *idk,
+			bool integral_constant_expression_p,
+			bool allow_non_integral_constant_expression_p,
+			bool *non_integral_constant_expression_p,
+			bool template_p,
+			bool done,
+			bool address_p,
+			bool template_arg_p,
+			const char **error_msg,
+			location_t location)
 {
   decl = strip_using_decl (decl);
 
@@ -3766,6 +3766,34 @@ finish_id_expression (tree id_expression,
   return cp_expr (decl, location);
 }
 
+/* As per finish_id_expression_1, but adding a wrapper node
+   around the result if needed to express LOCATION.  */
+
+cp_expr
+finish_id_expression (tree id_expression,
+		      tree decl,
+		      tree scope,
+		      cp_id_kind *idk,
+		      bool integral_constant_expression_p,
+		      bool allow_non_integral_constant_expression_p,
+		      bool *non_integral_constant_expression_p,
+		      bool template_p,
+		      bool done,
+		      bool address_p,
+		      bool template_arg_p,
+		      const char **error_msg,
+		      location_t location)
+{
+  cp_expr result
+    = finish_id_expression_1 (id_expression, decl, scope, idk,
+			      integral_constant_expression_p,
+			      allow_non_integral_constant_expression_p,
+			      non_integral_constant_expression_p,
+			      template_p, done, address_p, template_arg_p,
+			      error_msg, location);
+  return result.maybe_add_location_wrapper ();
+}
+
 /* Implement the __typeof keyword: Return the type of EXPR, suitable for
    use as a type-specifier.  */
 
-- 
1.8.5.3

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

* [PATCH 06/11] gcc: Handle location wrappers in operand_equal_p
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
@ 2017-11-18  2:50           ` David Malcolm
  2017-11-18  2:50           ` [PATCH 02/11] cp_tree::maybe_add_location_wrapper: no-op for template decls David Malcolm
                             ` (9 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Fixes e.g. c-c++-common/Wsizeof-pointer-memaccess1.c

gcc/ChangeLog:
	* fold-const.c (operand_equal_p): Handle location wrappers.
	* tree.c (inchash::add_expr): Likewise.
---
 gcc/fold-const.c | 3 +++
 gcc/tree.c       | 1 +
 2 files changed, 4 insertions(+)

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e9cd968..ababa68 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2802,6 +2802,9 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 	  != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
     return 0;
 
+  STRIP_ANY_LOCATION_WRAPPER (arg0);
+  STRIP_ANY_LOCATION_WRAPPER (arg1);
+
   /* Check equality of integer constants before bailing out due to
      precision differences.  */
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
diff --git a/gcc/tree.c b/gcc/tree.c
index f71b484..6ef290d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7092,6 +7092,7 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
 
   if (!(flags & OEP_ADDRESS_OF))
     STRIP_NOPS (t);
+  STRIP_ANY_LOCATION_WRAPPER (t);
 
   code = TREE_CODE (t);
 
-- 
1.8.5.3

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

* [PATCH 09/11] objc: handle location wrappers in objc_maybe_build_component_ref
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (4 preceding siblings ...)
  2017-11-18  2:51           ` [PATCH 04/11] C++: add cp_expr::strip_any_location_wrapper method David Malcolm
@ 2017-11-18  2:51           ` David Malcolm
  2017-11-18  2:51           ` [PATCH 08/11] C++: handle location wrappers David Malcolm
                             ` (4 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:51 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Fixes "self." e.g. in obj-c++.dg/property/dotsyntax-5.mm.

gcc/objc/ChangeLog:
	* objc-act.c (objc_maybe_build_component_ref): Handle location
	wrappers.
---
 gcc/objc/objc-act.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 765192c..15b2dfd 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1376,6 +1376,8 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
       || TREE_CODE (property_ident) != IDENTIFIER_NODE)
     return NULL_TREE;
 
+  STRIP_ANY_LOCATION_WRAPPER (object);
+
   /* The following analysis of 'object' is similar to the one used for
      the 'receiver' of a method invocation.  We need to determine what
      'object' is and find the appropriate property (either declared,
-- 
1.8.5.3

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

* [PATCH 04/11] C++: add cp_expr::strip_any_location_wrapper method
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (3 preceding siblings ...)
  2017-11-18  2:50           ` [PATCH 03/11] Implement STRIP_ANY_LOCATION_WRAPPER_SAFE David Malcolm
@ 2017-11-18  2:51           ` David Malcolm
  2017-11-18  2:51           ` [PATCH 09/11] objc: handle location wrappers in objc_maybe_build_component_ref David Malcolm
                             ` (5 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:51 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This is needed by perform_koenig_lookup.

gcc/cp/ChangeLog:
	* cp-tree.h (cp_expr::strip_any_location_wrapper): New method.
---
 gcc/cp/cp-tree.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 63e9bff..f9c589d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -95,6 +95,11 @@ public:
 
   cp_expr& maybe_add_location_wrapper ();
 
+  void strip_any_location_wrapper ()
+  {
+    STRIP_ANY_LOCATION_WRAPPER (m_value);
+  }
+
  private:
   tree m_value;
   location_t m_loc;
-- 
1.8.5.3

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

* [PATCH 07/11] c-family: handle location wrappers
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (7 preceding siblings ...)
  2017-11-18  2:51           ` [PATCH 05/11] C++: finish_call_expr: strip location wrapper David Malcolm
@ 2017-11-18  2:51           ` David Malcolm
  2017-11-18  3:23           ` [PATCH 11/11] config: handle location wrappers in various attributes (untested) David Malcolm
  2017-11-18  3:54           ` [PATCH 10/11] i386: handle location wrappers in ix86_handle_cconv_attribute David Malcolm
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:51 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/c-family/ChangeLog:
	* c-attribs.c (handle_tm_wrap_attribute): Handle location
	wrappers.
	* c-common.c (c_common_truthvalue_conversion): Likewise.
	(check_user_alignment): Likewise.
	(get_nonnull_operand): Likewise.
	(fold_offsetof_1): Likewise.
	(convert_vector_to_array_for_subscript): Likewise.
	* c-format.c (get_constant): Likewise.
	* c-warn.c (warn_logical_operator): Likewise.
	(find_array_ref_with_const_idx_r): Likewise.
	(warn_array_subscript_with_type_char): Likewise.
---
 gcc/c-family/c-attribs.c |  1 +
 gcc/c-family/c-common.c  |  9 +++++++++
 gcc/c-family/c-format.c  |  2 ++
 gcc/c-family/c-warn.c    | 25 +++++++++++++++++--------
 4 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index bb75cba..e757628 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -2762,6 +2762,7 @@ handle_tm_wrap_attribute (tree *node, tree name, tree args,
   else
     {
       tree wrap_decl = TREE_VALUE (args);
+      STRIP_ANY_LOCATION_WRAPPER_SAFE (wrap_decl);
       if (error_operand_p (wrap_decl))
 	;
       else if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 5a26424..59a4d93 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3228,6 +3228,8 @@ decl_with_nonnull_addr_p (const_tree expr)
 tree
 c_common_truthvalue_conversion (location_t location, tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:   case NE_EXPR:   case UNEQ_EXPR: case LTGT_EXPR:
@@ -5079,6 +5081,9 @@ check_user_alignment (const_tree align, bool allow_zero)
 
   if (error_operand_p (align))
     return -1;
+
+  STRIP_ANY_LOCATION_WRAPPER (align);
+
   if (TREE_CODE (align) != INTEGER_CST
       || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
     {
@@ -5356,6 +5361,8 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
 bool
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
+  STRIP_ANY_LOCATION_WRAPPER (arg_num_expr);
+
   /* Verify the arg number is a small constant.  */
   if (tree_fits_uhwi_p (arg_num_expr))
     {
@@ -6155,6 +6162,7 @@ fold_offsetof_1 (tree expr, enum tree_code ctx)
 	return base;
 
       t = TREE_OPERAND (expr, 1);
+      STRIP_ANY_LOCATION_WRAPPER (t);
 
       /* Check if the offset goes beyond the upper bound of the array.  */
       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
@@ -7600,6 +7608,7 @@ convert_vector_to_array_for_subscript (location_t loc,
 
       ret = !lvalue_p (*vecp);
 
+      STRIP_ANY_LOCATION_WRAPPER (index);
       if (TREE_CODE (index) == INTEGER_CST)
         if (!tree_fits_uhwi_p (index)
             || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type))
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 6b436ec..cdcd03a 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -263,6 +263,8 @@ check_format_string (tree fntype, unsigned HOST_WIDE_INT format_num,
 static bool
 get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (!tree_fits_uhwi_p (expr))
     {
       gcc_assert (!validated_p);
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 0086435..c7bc478 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -246,6 +246,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
   lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
   if (!lhs)
     return;
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
 
   /* If this is an OR operation, invert both sides; now, the result
      should be always false to get a warning.  */
@@ -261,6 +262,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
   rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
   if (!rhs)
     return;
+  STRIP_ANY_LOCATION_WRAPPER (rhs);
 
   /* If this is an OR operation, invert both sides; now, the result
      should be always false to get a warning.  */
@@ -313,10 +315,14 @@ find_array_ref_with_const_idx_r (tree *expr_p, int *, void *)
 {
   tree expr = *expr_p;
 
-  if ((TREE_CODE (expr) == ARRAY_REF
-       || TREE_CODE (expr) == ARRAY_RANGE_REF)
-      && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
-    return integer_type_node;
+  if (TREE_CODE (expr) == ARRAY_REF
+      || TREE_CODE (expr) == ARRAY_RANGE_REF)
+    {
+      tree index = TREE_OPERAND (expr, 1);
+      STRIP_ANY_LOCATION_WRAPPER (index);
+      if (TREE_CODE (index) == INTEGER_CST)
+	return integer_type_node;
+    }
 
   return NULL_TREE;
 }
@@ -1643,10 +1649,13 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
 void
 warn_array_subscript_with_type_char (location_t loc, tree index)
 {
-  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
-      && TREE_CODE (index) != INTEGER_CST)
-    warning_at (loc, OPT_Wchar_subscripts,
-		"array subscript has type %<char%>");
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+    {
+      STRIP_ANY_LOCATION_WRAPPER (index);
+      if (TREE_CODE (index) != INTEGER_CST)
+	warning_at (loc, OPT_Wchar_subscripts,
+		    "array subscript has type %<char%>");
+    }
 }
 
 /* Implement -Wparentheses for the unexpected C precedence rules, to
-- 
1.8.5.3

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

* [PATCH 05/11] C++: finish_call_expr: strip location wrapper
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (6 preceding siblings ...)
  2017-11-18  2:51           ` [PATCH 08/11] C++: handle location wrappers David Malcolm
@ 2017-11-18  2:51           ` David Malcolm
  2017-11-18  2:51           ` [PATCH 07/11] c-family: handle location wrappers David Malcolm
                             ` (2 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:51 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This is needed to recognize calls to known functions, otherwise
such calls get erroneously handled by cp_build_function_call_vec.

gcc/cp/ChangeLog:
	* semantics.c (finish_call_expr): Strip any location wrapper from
	fn.
---
 gcc/cp/semantics.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index dfdc458..f292d17 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2314,6 +2314,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 
   gcc_assert (!TYPE_P (fn));
 
+  STRIP_ANY_LOCATION_WRAPPER (fn);
+
   /* If FN may be a FUNCTION_DECL obfuscated by force_paren_expr, undo
      it so that we can tell this is a call to a known function.  */
   fn = maybe_undo_parenthesized_ref (fn);
-- 
1.8.5.3

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

* [PATCH 08/11] C++: handle location wrappers
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (5 preceding siblings ...)
  2017-11-18  2:51           ` [PATCH 09/11] objc: handle location wrappers in objc_maybe_build_component_ref David Malcolm
@ 2017-11-18  2:51           ` David Malcolm
  2017-11-18  2:51           ` [PATCH 05/11] C++: finish_call_expr: strip location wrapper David Malcolm
                             ` (3 subsequent siblings)
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  2:51 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

gcc/cp/ChangeLog:
	* call.c (build_conditional_expr_1): Handle location wrappers.
	(build_new_op_1): Likewise.
	* class.c (mark_or_check_attr_tags): Likewise.
	* constexpr.c (cxx_eval_constant_expression): Likewise.
	* cvt.c (ocp_convert): Likewise.
	* decl.c (reshape_init_r): Likewise.
	(cp_complete_array_type): Likewise.
	* expr.c (mark_discarded_use): Likewise.
	* lambda.c (build_capture_proxy): Likewise.
	* name-lookup.c (handle_namespace_attrs): Likewise.
	* parser.c (cp_parser_postfix_expression): Likewise when checking
	for calls to memset and for component lookups.
	(cp_parser_unary_expression): Likewise for immediate folding of
	negated constants.
	(cp_parser_template_argument): Likewise.
	(cp_parser_omp_for_incr): Likewise.
	(cp_parser_omp_for_loop_init): Likewise.
	(cp_parser_omp_declare_reduction_exprs): Likewise.
	(cp_parser_cilk_simd_linear): Likewise.
	* pt.c (convert_nontype_argument_function): Likewise.
	(convert_nontype_argument): Likewise.
	* semantics.c (finish_asm_stmt): Likewise.
	(perform_koenig_lookup): Likewise.
	(handle_omp_array_sections_1): Likewise.
	(handle_omp_array_sections): Likewise.
	(omp_reduction_lookup): Likewise.
	(finish_omp_for): Likewise.
	* tree.c (cp_stabilize_reference): Likewise.
	(builtin_valid_in_constant_expr_p): Likewise.
	(is_overloaded_fn): Likewise.
	(get_fns): Likewise.
	(check_abi_tag_args): Likewise.
	* typeck.c (cxx_sizeof_expr): Likewise.
	(cp_build_binary_op): Likewise.
	(cp_build_modify_expr): Likewise.
	(maybe_warn_about_returning_address_of_local): Likewise.
	* typeck2.c (cxx_incomplete_type_diagnostic): Likewise.
	(digest_init_r): Likewise.
---
 gcc/cp/call.c        |  7 ++++++
 gcc/cp/class.c       |  1 +
 gcc/cp/constexpr.c   |  1 +
 gcc/cp/cvt.c         |  1 +
 gcc/cp/decl.c        |  4 ++++
 gcc/cp/expr.c        |  2 ++
 gcc/cp/lambda.c      |  3 +++
 gcc/cp/name-lookup.c |  1 +
 gcc/cp/parser.c      | 65 +++++++++++++++++++++++++++++++++-------------------
 gcc/cp/pt.c          | 10 +++++++-
 gcc/cp/semantics.c   | 44 ++++++++++++++++++++++-------------
 gcc/cp/tree.c        |  8 +++++++
 gcc/cp/typeck.c      | 25 +++++++++++++++++---
 gcc/cp/typeck2.c     |  4 ++++
 14 files changed, 133 insertions(+), 43 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c1b662f..82302b5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4816,6 +4816,9 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
   orig_arg2 = arg2;
   orig_arg3 = arg3;
 
+  STRIP_ANY_LOCATION_WRAPPER (arg2);
+  STRIP_ANY_LOCATION_WRAPPER (arg3);
+
   if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
     {
       tree arg1_type = TREE_TYPE (arg1);
@@ -5588,6 +5591,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
       || error_operand_p (arg3))
     return error_mark_node;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg1);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg2);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (arg3);
+
   bool ismodop = code == MODIFY_EXPR;
   if (ismodop)
     {
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 586a32c..781594c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1377,6 +1377,7 @@ mark_or_check_attr_tags (tree attr, tree *tp, abi_tag_data *p, bool val)
 	 list = TREE_CHAIN (list))
       {
 	tree tag = TREE_VALUE (list);
+	STRIP_ANY_LOCATION_WRAPPER (tag);
 	tree id = get_identifier (TREE_STRING_POINTER (tag));
 	if (tp)
 	  check_tag (tag, id, tp, p);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index d6b6843..3122743 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3943,6 +3943,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 			      tree *jump_target)
 {
   constexpr_ctx new_ctx;
+  STRIP_ANY_LOCATION_WRAPPER (t);
   tree r = t;
 
   if (jump_target && *jump_target)
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index b3a6f69..fdc2b8d 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -766,6 +766,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	     the original value is within the range of the enumeration
 	     values. Otherwise, the resulting enumeration value is
 	     unspecified.  */
+	  STRIP_ANY_LOCATION_WRAPPER (e);
 	  if ((complain & tf_warning)
 	      && TREE_CODE (e) == INTEGER_CST
 	      && ENUM_UNDERLYING_TYPE (type)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7e16f7b..9afce0a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5809,6 +5809,8 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
   if (error_operand_p (init))
     return error_mark_node;
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   if (first_initializer_p && !CP_AGGREGATE_TYPE_P (type)
       && has_designator_problem (d, complain))
     return error_mark_node;
@@ -8115,6 +8117,8 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
   int failure;
   tree type, elt_type;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (initial_value);
+
   /* Don't get confused by a CONSTRUCTOR for some other type.  */
   if (initial_value && TREE_CODE (initial_value) == CONSTRUCTOR
       && !BRACE_ENCLOSED_INITIALIZER_P (initial_value)
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 81b9a5b..07630fc 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -220,6 +220,8 @@ mark_discarded_use (tree expr)
   if (expr == NULL_TREE)
     return expr;
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case COND_EXPR:
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 4480c67..c403a25 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -428,6 +428,8 @@ build_capture_proxy (tree member, tree init)
   TREE_USED (var) = 1;
   DECL_CONTEXT (var) = fn;
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   if (DECL_NORMAL_CAPTURE_P (member))
     {
       if (DECL_VLA_CAPTURE_P (member))
@@ -444,6 +446,7 @@ build_capture_proxy (tree member, tree init)
 	    init = TREE_OPERAND (init, 0);
 	  STRIP_NOPS (init);
 	}
+      STRIP_ANY_LOCATION_WRAPPER (init);
       gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL);
       while (is_normal_capture_proxy (init))
 	init = DECL_CAPTURED_VARIABLE (init);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b4976d8..6d5fdcf 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5026,6 +5026,7 @@ handle_namespace_attrs (tree ns, tree attributes)
 	     rather than the namespace as a whole, so we don't touch the
 	     NAMESPACE_DECL at all.  */
 	  tree x = args ? TREE_VALUE (args) : NULL_TREE;
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (x);
 	  if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
 	    {
 	      warning (OPT_Wattributes,
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8834542..090fb03 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7168,9 +7168,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		  }
 	      }
 
-	    if (TREE_CODE (postfix_expression) == FUNCTION_DECL
-		&& DECL_BUILT_IN_CLASS (postfix_expression) == BUILT_IN_NORMAL
-		&& DECL_FUNCTION_CODE (postfix_expression) == BUILT_IN_MEMSET
+	    tree postfix_expr_noloc = postfix_expression;
+	    STRIP_ANY_LOCATION_WRAPPER (postfix_expr_noloc);
+
+	    if (TREE_CODE (postfix_expr_noloc) == FUNCTION_DECL
+		&& DECL_BUILT_IN_CLASS (postfix_expr_noloc) == BUILT_IN_NORMAL
+		&& DECL_FUNCTION_CODE (postfix_expr_noloc) == BUILT_IN_MEMSET
 		&& vec_safe_length (args) == 3)
 	      {
 		tree arg0 = (*args)[0];
@@ -7184,10 +7187,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		warn_for_memset (input_location, arg0, arg2, literal_mask);
 	      }
 
-	    if (TREE_CODE (postfix_expression) == COMPONENT_REF)
+	    if (TREE_CODE (postfix_expr_noloc) == COMPONENT_REF)
 	      {
-		tree instance = TREE_OPERAND (postfix_expression, 0);
-		tree fn = TREE_OPERAND (postfix_expression, 1);
+		tree instance = TREE_OPERAND (postfix_expr_noloc, 0);
+		tree fn = TREE_OPERAND (postfix_expr_noloc, 1);
 
 		if (processing_template_decl
 		    && (type_dependent_object_expression_p (instance)
@@ -7221,9 +7224,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 					/*koenig_p=*/false,
 					complain);
 	      }
-	    else if (TREE_CODE (postfix_expression) == OFFSET_REF
-		     || TREE_CODE (postfix_expression) == MEMBER_REF
-		     || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
+	    else if (TREE_CODE (postfix_expr_noloc) == OFFSET_REF
+		     || TREE_CODE (postfix_expr_noloc) == MEMBER_REF
+		     || TREE_CODE (postfix_expr_noloc) == DOTSTAR_EXPR)
 	      postfix_expression = (build_offset_ref_call_from_tree
 				    (postfix_expression, &args,
 				     complain));
@@ -8335,18 +8338,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 	case NEGATE_EXPR:
 	  /* Immediately fold negation of a constant, unless the constant is 0
 	     (since -0 == 0) or it would overflow.  */
-	  if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
-	      && CONSTANT_CLASS_P (cast_expression)
-	      && !integer_zerop (cast_expression)
-	      && !TREE_OVERFLOW (cast_expression))
+	  if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER)
 	    {
-	      tree folded = fold_build1 (unary_operator,
-					 TREE_TYPE (cast_expression),
-					 cast_expression);
-	      if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+	      cast_expression.strip_any_location_wrapper ();
+	      if (CONSTANT_CLASS_P (cast_expression)
+		  && !integer_zerop (cast_expression)
+		  && !TREE_OVERFLOW (cast_expression))
 		{
-		  expression = cp_expr (folded, loc);
-		  break;
+		  tree folded = fold_build1 (unary_operator,
+					     TREE_TYPE (cast_expression),
+					     cast_expression);
+		  if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+		    {
+		      expression = cp_expr (folded, loc);
+		      expression.maybe_add_location_wrapper ();
+		      break;
+		    }
 		}
 	    }
 	  /* Fall through.  */
@@ -16415,6 +16422,7 @@ cp_parser_template_argument (cp_parser* parser)
 					       /*cast_p=*/false,
 					       /*template_arg_p=*/true,
 					       &idk);
+      STRIP_ANY_LOCATION_WRAPPER (argument);
       if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
 	  || !cp_parser_next_token_ends_template_argument_p (parser))
 	cp_parser_simulate_error (parser);
@@ -16444,6 +16452,7 @@ cp_parser_template_argument (cp_parser* parser)
 					       /*cast_p=*/false,
 					       /*template_arg_p=*/true,
 					       &idk);
+      STRIP_ANY_LOCATION_WRAPPER (argument);
       if (cp_parser_error_occurred (parser)
 	  || !cp_parser_next_token_ends_template_argument_p (parser))
 	cp_parser_abort_tentative_parse (parser);
@@ -34686,6 +34695,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 	    ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
       cp_lexer_consume_token (parser->lexer);
       lhs = cp_parser_simple_cast_expression (parser);
+      STRIP_ANY_LOCATION_WRAPPER (lhs);
       if (lhs != decl
 	  && (!processing_template_decl || !cp_tree_equal (lhs, decl)))
 	return error_mark_node;
@@ -34693,6 +34703,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
     }
 
   lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
   if (lhs != decl
       && (!processing_template_decl || !cp_tree_equal (lhs, decl)))
     return error_mark_node;
@@ -34720,6 +34731,8 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
   lhs = cp_parser_binary_expression (parser, false, false,
 				     PREC_ADDITIVE_EXPRESSION, NULL);
   token = cp_lexer_peek_token (parser->lexer);
+
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
   decl_first = (lhs == decl
 		|| (processing_template_decl && cp_tree_equal (lhs, decl)));
   if (decl_first)
@@ -34754,6 +34767,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 
   if (!decl_first)
     {
+      STRIP_ANY_LOCATION_WRAPPER (rhs);
       if ((rhs != decl
 	   && (!processing_template_decl || !cp_tree_equal (rhs, decl)))
 	  || op == MINUS_EXPR)
@@ -34943,6 +34957,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
       cp_parser_parse_tentatively (parser);
       decl = cp_parser_primary_expression (parser, false, false,
 					   false, &idk);
+      STRIP_ANY_LOCATION_WRAPPER_SAFE (decl);
       cp_token *last_tok = cp_lexer_peek_token (parser->lexer);
       if (!cp_parser_error_occurred (parser)
 	  && decl
@@ -37563,10 +37578,13 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
 	  unsigned int i;
 	  tree arg;
 	  FOR_EACH_VEC_SAFE_ELT (args, i, arg)
-	    if (arg == omp_priv
-		|| (TREE_CODE (arg) == ADDR_EXPR
-		    && TREE_OPERAND (arg, 0) == omp_priv))
-	      break;
+	    {
+	      STRIP_ANY_LOCATION_WRAPPER (arg);
+	      if (arg == omp_priv
+		  || (TREE_CODE (arg) == ADDR_EXPR
+		      && TREE_OPERAND (arg, 0) == omp_priv))
+		break;
+	    }
 	  cp_parser_abort_tentative_parse (parser);
 	  if (arg == NULL_TREE)
 	    error ("one of the initializer call arguments should be %<omp_priv%>"
@@ -39165,6 +39183,7 @@ cp_parser_cilk_simd_linear (cp_parser *parser, tree clauses)
 
 	      e = cp_parser_assignment_expression (parser);
 	      e = maybe_constant_value (e);
+	      STRIP_ANY_LOCATION_WRAPPER (e);
 
 	      if (e == error_mark_node)
 		{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 562b927..71fce74 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6063,6 +6063,7 @@ convert_nontype_argument_function (tree type, tree expr,
      -- the address of an object or function with external [C++11: or
         internal] linkage.  */
 
+  STRIP_ANY_LOCATION_WRAPPER (fn_no_ptr);
   if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
     {
       if (complain & tf_error)
@@ -6410,6 +6411,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 {
   tree expr_type;
   location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  STRIP_ANY_LOCATION_WRAPPER (expr);
   tree orig_expr = expr;
 
   /* Detect immediately string literals as invalid non-type argument.
@@ -6475,6 +6477,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      to a null value, but otherwise still need to be of a specific form.  */
   if (cxx_dialect >= cxx11)
     {
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       if (TREE_CODE (expr) == PTRMEM_CST)
 	/* A PTRMEM_CST is already constant, and a valid template
 	   argument for a parameter of pointer to member type, we just want
@@ -6506,6 +6509,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   else
     expr = mark_rvalue_use (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* HACK: Due to double coercion, we can get a
      NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
      which is the tree that we built on the first call (see
@@ -6559,6 +6564,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 
       /* Notice that there are constant expressions like '4 % 0' which
 	 do not fold into integer constants.  */
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       if (TREE_CODE (expr) != INTEGER_CST
 	  && !value_dependent_expression_p (expr))
 	{
@@ -6592,6 +6598,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
      conversion (_conv.array_) are applied.  */
   else if (TYPE_PTROBV_P (type))
     {
+      STRIP_ANY_LOCATION_WRAPPER (expr);
       tree decayed = expr;
 
       /* Look through any NOP_EXPRs around an ADDR_EXPR, whether they come from
@@ -6630,6 +6637,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 	/* Null pointer values are OK in C++11.  */;
       else if (TREE_CODE (expr) != ADDR_EXPR)
 	{
+	  STRIP_ANY_LOCATION_WRAPPER (expr);
 	  if (VAR_P (expr))
 	    {
 	      if (complain & tf_error)
@@ -6653,7 +6661,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
       else
 	{
 	  tree decl = TREE_OPERAND (expr, 0);
-
+	  STRIP_ANY_LOCATION_WRAPPER (decl);
 	  if (!VAR_P (decl))
 	    {
 	      if (complain & tf_error)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f292d17..2f37dc8 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1489,6 +1489,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
 	     otherwise we'll get an error.  Gross, but ...  */
 	  STRIP_NOPS (operand);
 
+	  STRIP_ANY_LOCATION_WRAPPER (operand);
+
 	  operand = mark_lvalue_use (operand);
 
 	  if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
@@ -2249,6 +2251,8 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
   bool template_id = false;
   location_t loc = fn.get_location ();
 
+  fn.strip_any_location_wrapper ();
+
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
     {
       /* Use a separate flag to handle null args.  */
@@ -4603,7 +4607,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
 
   type = TREE_TYPE (ret);
   low_bound = TREE_PURPOSE (t);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (low_bound);
   length = TREE_VALUE (t);
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (length);
   if ((low_bound && type_dependent_expression_p (low_bound))
       || (length && type_dependent_expression_p (length)))
     return NULL_TREE;
@@ -4894,11 +4900,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
 	  tree length = TREE_VALUE (t);
 
 	  i--;
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (low_bound);
 	  if (low_bound
 	      && TREE_CODE (low_bound) == INTEGER_CST
 	      && TYPE_PRECISION (TREE_TYPE (low_bound))
 		 > TYPE_PRECISION (sizetype))
 	    low_bound = fold_convert (sizetype, low_bound);
+	  STRIP_ANY_LOCATION_WRAPPER_SAFE (length);
 	  if (length
 	      && TREE_CODE (length) == INTEGER_CST
 	      && TYPE_PRECISION (TREE_TYPE (length))
@@ -5204,6 +5212,7 @@ omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp,
 						  type),
 				false, false);
   tree fns = id;
+  STRIP_ANY_LOCATION_WRAPPER (fns);
   id = NULL_TREE;
   if (fns && is_overloaded_fn (fns))
     {
@@ -8062,22 +8071,25 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv,
       if (decl == NULL)
 	{
 	  if (init != NULL)
-	    switch (TREE_CODE (init))
-	      {
-	      case MODIFY_EXPR:
-		decl = TREE_OPERAND (init, 0);
-		init = TREE_OPERAND (init, 1);
-		break;
-	      case MODOP_EXPR:
-		if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
-		  {
-		    decl = TREE_OPERAND (init, 0);
-		    init = TREE_OPERAND (init, 2);
-		  }
-		break;
-	      default:
-		break;
-	      }
+	    {
+	      STRIP_ANY_LOCATION_WRAPPER (init);
+	      switch (TREE_CODE (init))
+		{
+		case MODIFY_EXPR:
+		  decl = TREE_OPERAND (init, 0);
+		  init = TREE_OPERAND (init, 1);
+		  break;
+		case MODOP_EXPR:
+		  if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
+		    {
+		      decl = TREE_OPERAND (init, 0);
+		      init = TREE_OPERAND (init, 2);
+		    }
+		  break;
+		default:
+		  break;
+		}
+	    }
 
 	  if (decl == NULL)
 	    {
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index fd4641c..3bb8b8f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -333,6 +333,8 @@ bitfield_p (const_tree ref)
 tree
 cp_stabilize_reference (tree ref)
 {
+  STRIP_ANY_LOCATION_WRAPPER (ref);
+
   switch (TREE_CODE (ref))
     {
     case NON_DEPENDENT_EXPR:
@@ -377,6 +379,8 @@ cp_stabilize_reference (tree ref)
 bool
 builtin_valid_in_constant_expr_p (const_tree decl)
 {
+  STRIP_ANY_LOCATION_WRAPPER (decl);
+
   if (!(TREE_CODE (decl) == FUNCTION_DECL
 	&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL))
     /* Not a built-in.  */
@@ -2425,6 +2429,8 @@ lookup_keep (tree lookup, bool keep)
 int
 is_overloaded_fn (tree x)
 {
+  STRIP_ANY_LOCATION_WRAPPER (x);
+
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (x) == OFFSET_REF
       || TREE_CODE (x) == COMPONENT_REF)
@@ -2472,6 +2478,7 @@ really_overloaded_fn (tree x)
 tree
 get_fns (tree from)
 {
+  STRIP_ANY_LOCATION_WRAPPER (from);
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (from) == OFFSET_REF
       || TREE_CODE (from) == COMPONENT_REF)
@@ -4467,6 +4474,7 @@ check_abi_tag_args (tree args, tree name)
   for (tree arg = args; arg; arg = TREE_CHAIN (arg))
     {
       tree elt = TREE_VALUE (arg);
+      STRIP_ANY_LOCATION_WRAPPER (elt);
       if (TREE_CODE (elt) != STRING_CST
 	  || (!same_type_ignoring_top_level_qualifiers_p
 	      (strip_array_types (TREE_TYPE (elt)),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a5e4745..027bafb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1614,6 +1614,8 @@ cxx_sizeof_nowarn (tree type)
 static tree
 cxx_sizeof_expr (tree e, tsubst_flags_t complain)
 {
+  STRIP_ANY_LOCATION_WRAPPER (e);
+
   if (e == error_mark_node)
     return error_mark_node;
 
@@ -4202,6 +4204,9 @@ cp_build_binary_op (location_t location,
   /* True if both operands have arithmetic type.  */
   bool arithmetic_types_p;
 
+  STRIP_ANY_LOCATION_WRAPPER (orig_op0);
+  STRIP_ANY_LOCATION_WRAPPER (orig_op1);
+
   /* Apply default conversions.  */
   op0 = orig_op0;
   op1 = orig_op1;
@@ -4394,6 +4399,7 @@ cp_build_binary_op (location_t location,
 	  tree type0 = TREE_OPERAND (op0, 0);
 	  tree type1 = TREE_OPERAND (op1, 0);
 	  tree first_arg = type0;
+	  STRIP_ANY_LOCATION_WRAPPER (first_arg);
 	  if (!TYPE_P (type0))
 	    type0 = TREE_TYPE (type0);
 	  if (!TYPE_P (type1))
@@ -7751,6 +7757,9 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 {
   lhs = mark_lvalue_use_nonread (lhs);
 
+  STRIP_ANY_LOCATION_WRAPPER (lhs);
+  STRIP_ANY_LOCATION_WRAPPER (rhs);
+
   tree result = NULL_TREE;
   tree newrhs = rhs;
   tree lhstype = TREE_TYPE (lhs);
@@ -8888,10 +8897,16 @@ maybe_warn_about_returning_address_of_local (tree retval)
   for (;;)
     {
       if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
-	whats_returned = TREE_OPERAND (whats_returned, 1);
+	{
+	  whats_returned = TREE_OPERAND (whats_returned, 1);
+	  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+	}
       else if (CONVERT_EXPR_P (whats_returned)
 	       || TREE_CODE (whats_returned) == NON_LVALUE_EXPR)
-	whats_returned = TREE_OPERAND (whats_returned, 0);
+	{
+	  whats_returned = TREE_OPERAND (whats_returned, 0);
+	  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+	}
       else
 	break;
     }
@@ -8899,10 +8914,14 @@ maybe_warn_about_returning_address_of_local (tree retval)
   if (TREE_CODE (whats_returned) != ADDR_EXPR)
     return false;
   whats_returned = TREE_OPERAND (whats_returned, 0);
+  STRIP_ANY_LOCATION_WRAPPER (whats_returned);
 
   while (TREE_CODE (whats_returned) == COMPONENT_REF
 	 || TREE_CODE (whats_returned) == ARRAY_REF)
-    whats_returned = TREE_OPERAND (whats_returned, 0);
+    {
+      whats_returned = TREE_OPERAND (whats_returned, 0);
+      STRIP_ANY_LOCATION_WRAPPER (whats_returned);
+    }
 
   if (TREE_CODE (valtype) == REFERENCE_TYPE)
     {
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e135b0d..77f6f3e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -464,6 +464,8 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
+  STRIP_ANY_LOCATION_WRAPPER_SAFE (value);
+
   if (value != 0 && (VAR_P (value)
 		     || TREE_CODE (value) == PARM_DECL
 		     || TREE_CODE (value) == FIELD_DECL))
@@ -1023,6 +1025,8 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 
   location_t loc = EXPR_LOC_OR_LOC (init, input_location);
 
+  STRIP_ANY_LOCATION_WRAPPER (init);
+
   /* Initialization of an array of chars from a string constant. The initializer
      can be optionally enclosed in braces, but reshape_init has already removed
      them if they were present.  */
-- 
1.8.5.3

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

* [PATCH 11/11] config: handle location wrappers in various attributes (untested)
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (8 preceding siblings ...)
  2017-11-18  2:51           ` [PATCH 07/11] c-family: handle location wrappers David Malcolm
@ 2017-11-18  3:23           ` David Malcolm
  2017-11-18  3:54           ` [PATCH 10/11] i386: handle location wrappers in ix86_handle_cconv_attribute David Malcolm
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  3:23 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

This is incomplete, and untested, but covers some of the cases
where an attribute's value's TREE_CODE is tested (e.g. via STRING_CST).

Alternatively, maybe we need a helper function for extracting
the value (and location_t) of an attribute, issuing an error if it's
not a STRING_CST?

gcc/ChangeLog:
	* config/arc/arc.c (arc_handle_interrupt_attribute): Handle
	location wrapper.
	* config/epiphany/epiphany.c
	(epiphany_handle_interrupt_attribute): Likewise.
	(epiphany_handle_forwarder_attribute): Likewise.
	* config/ia64/ia64.c (ia64_handle_model_attribute): Likewise.
	* config/m32r/m32r.c (m32r_handle_model_attribute): Likewise.
	* config/mips/mips.c (mips_handle_interrupt_attr): Likewise.
	(mips_handle_use_shadow_register_set_attr): Likewise.
	* config/msp430/msp430.c (msp430_attr): Likewise.
	* config/s390/s390.c (s390_handle_hotpatch_attribute): Likewise.
---
 gcc/config/arc/arc.c           | 2 ++
 gcc/config/epiphany/epiphany.c | 3 +++
 gcc/config/ia64/ia64.c         | 1 +
 gcc/config/m32r/m32r.c         | 2 ++
 gcc/config/mips/mips.c         | 2 ++
 gcc/config/msp430/msp430.c     | 2 +-
 gcc/config/s390/s390.c         | 2 ++
 7 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 7be9f7c..d84c2ab 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -1922,6 +1922,8 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
 
   tree value = TREE_VALUE (args);
 
+  STRIP_ANY_LOCATION_WRAPPER (value);
+
   if (TREE_CODE (value) != STRING_CST)
     {
       warning (OPT_Wattributes,
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 26b0f3c..ac64d1f 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -496,6 +496,7 @@ epiphany_handle_interrupt_attribute (tree *node, tree name, tree args,
     }
 
   value = TREE_VALUE (args);
+  STRIP_ANY_LOCATION_WRAPPER (value);
 
   if (TREE_CODE (value) != STRING_CST)
     {
@@ -537,6 +538,8 @@ epiphany_handle_forwarder_attribute (tree *node ATTRIBUTE_UNUSED,
 
   value = TREE_VALUE (args);
 
+  STRIP_ANY_LOCATION_WRAPPER (value);
+
   if (TREE_CODE (value) != STRING_CST)
     {
       warning (OPT_Wattributes,
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 84a5b56..ae7f1f1 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -742,6 +742,7 @@ ia64_handle_model_attribute (tree *node, tree name, tree args,
 
   init_idents ();
   arg = TREE_VALUE (args);
+  STRIP_ANY_LOCATION_WRAPPER (arg);
   if (arg == small_ident1 || arg == small_ident2)
     {
       addr_area = ADDR_AREA_SMALL;
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index f104457..f12a8e9 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -399,6 +399,8 @@ m32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
   init_idents ();
   arg = TREE_VALUE (args);
 
+  STRIP_ANY_LOCATION_WRAPPER (arg);
+
   if (arg != small_ident1
       && arg != small_ident2
       && arg != medium_ident1
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 7dde705..2b9f68a 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1474,6 +1474,7 @@ mips_handle_interrupt_attr (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
       tree cst;
 
       cst = TREE_VALUE (args);
+      STRIP_ANY_LOCATION_WRAPPER (cst);
       if (TREE_CODE (cst) != STRING_CST)
 	{
 	  warning (OPT_Wattributes,
@@ -1528,6 +1529,7 @@ mips_handle_use_shadow_register_set_attr (tree *node ATTRIBUTE_UNUSED,
       tree cst;
 
       cst = TREE_VALUE (args);
+      STRIP_ANY_LOCATION_WRAPPER (cst);
       if (TREE_CODE (cst) != STRING_CST)
 	{
 	  warning (OPT_Wattributes,
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 0ee0b6c..ea40628 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1867,7 +1867,7 @@ msp430_attr (tree * node,
       gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
 
       tree value = TREE_VALUE (args);
-
+      STRIP_ANY_LOCATION_WRAPPER (value);
       switch (TREE_CODE (value))
 	{
 	case STRING_CST:
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 4e08955..2d511b3 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1110,6 +1110,8 @@ s390_handle_hotpatch_attribute (tree *node, tree name, tree args,
     {
       expr = TREE_VALUE (args);
       expr2 = TREE_VALUE (TREE_CHAIN (args));
+      STRIP_ANY_LOCATION_WRAPPER (expr);
+      STRIP_ANY_LOCATION_WRAPPER (expr2);
     }
   if (args == NULL || TREE_CHAIN (args) == NULL)
     err = 1;
-- 
1.8.5.3

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

* [PATCH 10/11] i386: handle location wrappers in ix86_handle_cconv_attribute
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
                             ` (9 preceding siblings ...)
  2017-11-18  3:23           ` [PATCH 11/11] config: handle location wrappers in various attributes (untested) David Malcolm
@ 2017-11-18  3:54           ` David Malcolm
  10 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-11-18  3:54 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

Fixes e.g. g++.dg/abi/regparm1.C

gcc/ChangeLog:
	* config/i386/i386.c (ix86_handle_cconv_attribute): Handle
	location wrappers.
---
 gcc/config/i386/i386.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b2c2934..7014e84 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6283,6 +6283,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
 	}
 
       cst = TREE_VALUE (args);
+      STRIP_ANY_LOCATION_WRAPPER (cst);
       if (TREE_CODE (cst) != INTEGER_CST)
 	{
 	  warning (OPT_Wattributes,
-- 
1.8.5.3

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

* [PATCH v2.1] Support for adding and stripping location_t wrapper nodes
  2017-11-16 10:04                 ` Richard Biener
@ 2017-11-30 17:25                   ` David Malcolm
  2017-11-30 17:46                     ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-30 17:25 UTC (permalink / raw)
  To: Richard Biener, Jason Merrill, Jakub Jelinek
  Cc: Trevor Saunders, Nathan Sidwell, gcc-patches List, David Malcolm

On Thu, 2017-11-16 at 10:58 +0100, Richard Biener wrote:
> On Wed, Nov 15, 2017 at 4:33 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Wed, 2017-11-15 at 12:11 +0100, Richard Biener wrote:
> > > On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tbsaun
> > > de.o
> > > rg> wrote:
> > > > On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
> > > > > 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, along with a new method of cp_expr.
> > > > > 
> > > > > It's called in later patches in the kit via that new method.
> > > > > 
> > > > > 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.
> > > > 
> > > > I happened to start reading this series near the end and was
> > > > rather
> > > > confused by this macro since it changes variables in a rather
> > > > unhygienic
> > > > way.  Did you consider just defining a inline function to
> > > > return
> > > > the
> > > > actual decl?  It seems like its not used that often so the
> > > > slight
> > > > extra
> > > > syntax should be that big a deal compared to the explicitness.
> > > 
> > > Existing practice .... (STRIP_NOPS & friends).  I'm fine either
> > > way,
> > > the patch looks good.
> > > 
> > > Eventually you can simplify things by doing less checking in
> > > location_wrapper_p, like only checking
> > > 
> > > +inline bool location_wrapper_p (const_tree exp)
> > > +{
> > > +  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
> > > +       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
> > > +          && (TREE_TYPE (exp)
> > > +                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
> > > +    return true;
> > > +  return false;
> > > +}
> > > 
> > > and renaming to maybe_location_wrapper_p.  After all you can't
> > > really
> > > distinguish location wrappers from non-location wrappers?  (and
> > > why
> > > would you want to?)
> > 
> > That's the implementation I originally tried.
> > 
> > As noted in an earlier thread about this, the problem I ran into
> > was
> > (in g++.dg/conversion/reinterpret1.C):
> > 
> >   // PR c++/15076
> > 
> >   struct Y { Y(int &); };
> > 
> >   int v;
> >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > 
> > where the "reinterpret_cast<int>" has the same type as the VAR_DECL
> > v,
> > and hence the argument to y1 is a NON_LVALUE_EXPR around a
> > VAR_DECL,
> > where both have the same type, and hence location_wrapper_p () on
> > the
> > cast would return true.
> > 
> > Compare with:
> > 
> >   Y y1(v);
> > 
> > where the argument "v" with a location wrapper is a
> > VIEW_CONVERT_EXPR
> > around a VAR_DECL.
> > 
> > With the simpler conditions you suggested above, both are treated
> > as
> > location wrappers (leading to the dg-error in the test failing),
> > whereas with the condition in the patch, only the latter is treated
> > as
> > a location wrapper, and an error is correctly emitted for the dg-
> > error.
> > 
> > Hope this sounds sane.  Maybe the function needs a more detailed
> > comment explaining this?
> 
> Yes.  I guess the above would argue for a new tree code but I can
> see that it is better to avoid that.
> 
> Thanks,
> Richard.

[...]

Here's an updated version of the patch which:
* adds a much more detailed comment to location_wrapper_p,
* fixes an erroneous reference to LOCATION_WRAPPER_EXPR in the
  comment to maybe_wrap_with_location (from an earlier unfinished
  experiment)
* adds a selftest for handling wrapper nodes.

Is there consensus about whether this approach is sane? i.e.  
* adding wrapper nodes via re-using existing tree codes (this kit), vs
* adding them via some new tree code ("LOCATION_WRAPPER_EXPR"?), vs
* the workaround of:
  "[PATCH] C++: use an optional vec<location_t> for callsites"
    https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html

Jason? Jakub? others?

(I'd like to get some version of this patch kit into gcc 8; I like
this kit's approach, as a minimal way to fix a real usability issue,
whilst giving us a route to doing more in gcc 9 (c.f. the v3 kit))

Thanks
Dave

gcc/ChangeLog:
	PR c++/43486
	* 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.
	(location_wrapper_p): New inline function.

gcc/cp/ChangeLog:
	PR c++/43486
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
---
 gcc/cp/cp-tree.h |  6 ++++++
 gcc/tree.c       | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/tree.h       | 42 ++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4780df4..aa579a4 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.c b/gcc/tree.c
index 5416866..5e2b424 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13791,6 +13791,38 @@ 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.
+   VIEW_CONVERT_EXPR is used for wrapping non-constants.
+
+   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;
+
+  if (CONSTANT_CLASS_P (expr))
+    return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (expr), expr);
+  else
+    return build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+}
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
@@ -14016,6 +14048,39 @@ test_labels ()
   ASSERT_FALSE (FORCED_LABEL (label_decl));
 }
 
+/* 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));
+
+  /* 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));
+
+  /* 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));
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -14024,6 +14089,7 @@ tree_c_tests ()
   test_integer_constants ();
   test_identifiers ();
   test_labels ();
+  test_location_wrappers ();
 }
 
 } // namespace selftest
diff --git a/gcc/tree.h b/gcc/tree.h
index db67858..112471b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -483,6 +483,15 @@ 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) \
+  do {					\
+    if (location_wrapper_p (EXP))	\
+      (EXP) = TREE_OPERAND ((EXP), 0);	\
+  } while (0)
+
 /* Nonzero if TYPE represents a vector type.  */
 
 #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
@@ -1146,6 +1155,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)
@@ -3643,6 +3654,37 @@ id_equal (const char *str, const_tree id)
   return !strcmp (str, IDENTIFIER_POINTER (id));
 }
 
+/* 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).
+
+   A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and the
+   same type as its operand.
+
+   NON_LVALUE_EXPR is used for wrapping constants.
+   VIEW_CONVERT_EXPR is used for wrapping non-constants.
+
+   A subtlety is that we have to test whether we have the correct
+   TREE_CODE for the wrapped TREE_CODE.  Otherwise, e.g. the C++ expression:
+     reinterpret_cast<int>(some_int_var)
+   is a NON_LVALUE_EXPR around a non-constant of the same type, and
+   could thus be mischaracterized as a location wrapper node.
+
+   Hence we need to check CONSTANT_CLASS_P (TREE_OPERAND (EXP, 0))
+   and check for the corresponding NON_LVALUE_EXPR or VIEW_CONVERT_EXPR
+   for EXP to be a wrapper.  */
+
+inline bool location_wrapper_p (const_tree exp)
+{
+  if (((TREE_CODE (exp) == NON_LVALUE_EXPR
+	&& CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+	   && !CONSTANT_CLASS_P (TREE_OPERAND (exp, 0))))
+      && (TREE_TYPE (exp)
+	  == TREE_TYPE (TREE_OPERAND (exp, 0))))
+    return true;
+  return false;
+}
+
 #define error_mark_node			global_trees[TI_ERROR_MARK]
 
 #define intQI_type_node			global_trees[TI_INTQI_TYPE]
-- 
1.8.5.3

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

* Re: [PATCH v2.1] Support for adding and stripping location_t wrapper nodes
  2017-11-30 17:25                   ` [PATCH v2.1] " David Malcolm
@ 2017-11-30 17:46                     ` Jason Merrill
  2017-11-30 18:38                       ` [PATCH, v2.2] " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-11-30 17:46 UTC (permalink / raw)
  To: David Malcolm
  Cc: Richard Biener, Jakub Jelinek, Trevor Saunders, Nathan Sidwell,
	gcc-patches List

On Thu, Nov 30, 2017 at 12:16 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Thu, 2017-11-16 at 10:58 +0100, Richard Biener wrote:
>> On Wed, Nov 15, 2017 at 4:33 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > On Wed, 2017-11-15 at 12:11 +0100, Richard Biener wrote:
>> > > On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tbsaun
>> > > de.o
>> > > rg> wrote:
>> > > > On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm wrote:
>> > > > > 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, along with a new method of cp_expr.
>> > > > >
>> > > > > It's called in later patches in the kit via that new method.
>> > > > >
>> > > > > 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.
>> > > >
>> > > > I happened to start reading this series near the end and was
>> > > > rather
>> > > > confused by this macro since it changes variables in a rather
>> > > > unhygienic
>> > > > way.  Did you consider just defining a inline function to
>> > > > return
>> > > > the
>> > > > actual decl?  It seems like its not used that often so the
>> > > > slight
>> > > > extra
>> > > > syntax should be that big a deal compared to the explicitness.
>> > >
>> > > Existing practice .... (STRIP_NOPS & friends).  I'm fine either
>> > > way, the patch looks good.

Note that STRIP_NOPS is now implemented in terms of such an inline
function, it would make sense to do the same here.

>> > > Eventually you can simplify things by doing less checking in
>> > > location_wrapper_p, like only checking
>> > >
>> > > +inline bool location_wrapper_p (const_tree exp)
>> > > +{
>> > > +  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
>> > > +       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
>> > > +          && (TREE_TYPE (exp)
>> > > +                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
>> > > +    return true;
>> > > +  return false;
>> > > +}
>> > >
>> > > and renaming to maybe_location_wrapper_p.  After all you can't
>> > > really
>> > > distinguish location wrappers from non-location wrappers?  (and
>> > > why
>> > > would you want to?)
>> >
>> > That's the implementation I originally tried.
>> >
>> > As noted in an earlier thread about this, the problem I ran into
>> > was
>> > (in g++.dg/conversion/reinterpret1.C):
>> >
>> >   // PR c++/15076
>> >
>> >   struct Y { Y(int &); };
>> >
>> >   int v;
>> >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
>> >
>> > where the "reinterpret_cast<int>" has the same type as the VAR_DECL
>> > v,
>> > and hence the argument to y1 is a NON_LVALUE_EXPR around a
>> > VAR_DECL,
>> > where both have the same type, and hence location_wrapper_p () on
>> > the
>> > cast would return true.
>> >
>> > Compare with:
>> >
>> >   Y y1(v);
>> >
>> > where the argument "v" with a location wrapper is a
>> > VIEW_CONVERT_EXPR
>> > around a VAR_DECL.
>> >
>> > With the simpler conditions you suggested above, both are treated
>> > as
>> > location wrappers (leading to the dg-error in the test failing),
>> > whereas with the condition in the patch, only the latter is treated
>> > as
>> > a location wrapper, and an error is correctly emitted for the dg-
>> > error.
>> >
>> > Hope this sounds sane.  Maybe the function needs a more detailed
>> > comment explaining this?
>>
>> Yes.  I guess the above would argue for a new tree code but I can
>> see that it is better to avoid that.

Basically, we can only strip a NON_LVALUE_EXPR if the argument is
already not an lvalue.  We shouldn't need any extra check on
VIEW_CONVERT_EXPR.

> [...]
>
> Here's an updated version of the patch which:
> * adds a much more detailed comment to location_wrapper_p,
> * fixes an erroneous reference to LOCATION_WRAPPER_EXPR in the
>   comment to maybe_wrap_with_location (from an earlier unfinished
>   experiment)
> * adds a selftest for handling wrapper nodes.
>
> Is there consensus about whether this approach is sane? i.e.
> * adding wrapper nodes via re-using existing tree codes (this kit), vs
> * adding them via some new tree code ("LOCATION_WRAPPER_EXPR"?), vs
> * the workaround of:
>   "[PATCH] C++: use an optional vec<location_t> for callsites"
>     https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
>
> Jason? Jakub? others?

I still like this approach.

Jason

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

* [PATCH, v2.2] Support for adding and stripping location_t wrapper nodes
  2017-11-30 17:46                     ` Jason Merrill
@ 2017-11-30 18:38                       ` David Malcolm
  2017-11-30 20:30                         ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-30 18:38 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Richard Biener, Jakub Jelinek, Trevor Saunders, Nathan Sidwell,
	gcc-patches List, David Malcolm

On Thu, 2017-11-30 at 12:36 -0500, Jason Merrill wrote:
> On Thu, Nov 30, 2017 at 12:16 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Thu, 2017-11-16 at 10:58 +0100, Richard Biener wrote:
> > > On Wed, Nov 15, 2017 at 4:33 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > On Wed, 2017-11-15 at 12:11 +0100, Richard Biener wrote:
> > > > > On Wed, Nov 15, 2017 at 7:17 AM, Trevor Saunders <tbsaunde@tb
> > > > > saun
> > > > > de.o
> > > > > rg> wrote:
> > > > > > On Fri, Nov 10, 2017 at 04:45:17PM -0500, David Malcolm
> > > > > > wrote:
> > > > > > > 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, along with a new method of cp_expr.
> > > > > > > 
> > > > > > > It's called in later patches in the kit via that new
> > > > > > > method.
> > > > > > > 
> > > > > > > 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.
> > > > > > 
> > > > > > I happened to start reading this series near the end and
> > > > > > was
> > > > > > rather
> > > > > > confused by this macro since it changes variables in a
> > > > > > rather
> > > > > > unhygienic
> > > > > > way.  Did you consider just defining a inline function to
> > > > > > return
> > > > > > the
> > > > > > actual decl?  It seems like its not used that often so the
> > > > > > slight
> > > > > > extra
> > > > > > syntax should be that big a deal compared to the
> > > > > > explicitness.
> > > > > 
> > > > > Existing practice .... (STRIP_NOPS & friends).  I'm fine
> > > > > either
> > > > > way, the patch looks good.
> 
> Note that STRIP_NOPS is now implemented in terms of such an inline
> function, it would make sense to do the same here.

FWIW STRIP_NOPS is currently:

#define STRIP_NOPS(EXP) \
  (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))

and tree_strip_nop_conversions *isn't* inline.

But assuming I follow you, I've updated the new macro to be:

#define STRIP_ANY_LOCATION_WRAPPER(EXP) \
  (EXP) = tree_strip_any_location_wrapper (CONST_CAST_TREE (EXP))

introducing a new inline tree_strip_any_location_wrapper.

> > > > > Eventually you can simplify things by doing less checking in
> > > > > location_wrapper_p, like only checking
> > > > > 
> > > > > +inline bool location_wrapper_p (const_tree exp)
> > > > > +{
> > > > > +  if ((TREE_CODE (exp) == NON_LVALUE_EXPR
> > > > > +       || (TREE_CODE (exp) == VIEW_CONVERT_EXPR
> > > > > +          && (TREE_TYPE (exp)
> > > > > +                 == TREE_TYPE (TREE_OPERAND (exp, 0)))
> > > > > +    return true;
> > > > > +  return false;
> > > > > +}
> > > > > 
> > > > > and renaming to maybe_location_wrapper_p.  After all you
> > > > > can't
> > > > > really
> > > > > distinguish location wrappers from non-location
> > > > > wrappers?  (and
> > > > > why
> > > > > would you want to?)
> > > > 
> > > > That's the implementation I originally tried.
> > > > 
> > > > As noted in an earlier thread about this, the problem I ran
> > > > into
> > > > was
> > > > (in g++.dg/conversion/reinterpret1.C):
> > > > 
> > > >   // PR c++/15076
> > > > 
> > > >   struct Y { Y(int &); };
> > > > 
> > > >   int v;
> > > >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > > > 
> > > > where the "reinterpret_cast<int>" has the same type as the
> > > > VAR_DECL
> > > > v,
> > > > and hence the argument to y1 is a NON_LVALUE_EXPR around a
> > > > VAR_DECL,
> > > > where both have the same type, and hence location_wrapper_p ()
> > > > on
> > > > the
> > > > cast would return true.
> > > > 
> > > > Compare with:
> > > > 
> > > >   Y y1(v);
> > > > 
> > > > where the argument "v" with a location wrapper is a
> > > > VIEW_CONVERT_EXPR
> > > > around a VAR_DECL.
> > > > 
> > > > With the simpler conditions you suggested above, both are
> > > > treated
> > > > as
> > > > location wrappers (leading to the dg-error in the test
> > > > failing),
> > > > whereas with the condition in the patch, only the latter is
> > > > treated
> > > > as
> > > > a location wrapper, and an error is correctly emitted for the
> > > > dg-
> > > > error.
> > > > 
> > > > Hope this sounds sane.  Maybe the function needs a more
> > > > detailed
> > > > comment explaining this?
> > > 
> > > Yes.  I guess the above would argue for a new tree code but I can
> > > see that it is better to avoid that.
> 
> Basically, we can only strip a NON_LVALUE_EXPR if the argument is
> already not an lvalue.  We shouldn't need any extra check on
> VIEW_CONVERT_EXPR.

Aha.  Thanks.  I've updated location_wrapper_p accordingly and updated
its comment to read:

   We don't need to check a VIEW_CONVERT_EXPR that wraps the same type
   for !CONSTANT_CLASS_P; such instances of VIEW_CONVERT_EXPR are always
   wrappers.

> > [...]
> > 
> > Here's an updated version of the patch which:
> > * adds a much more detailed comment to location_wrapper_p,
> > * fixes an erroneous reference to LOCATION_WRAPPER_EXPR in the
> >   comment to maybe_wrap_with_location (from an earlier unfinished
> >   experiment)
> > * adds a selftest for handling wrapper nodes.
> > 
> > Is there consensus about whether this approach is sane? i.e.
> > * adding wrapper nodes via re-using existing tree codes (this kit),
> > vs
> > * adding them via some new tree code ("LOCATION_WRAPPER_EXPR"?), vs
> > * the workaround of:
> >   "[PATCH] C++: use an optional vec<location_t> for callsites"
> >     https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
> > 
> > Jason? Jakub? others?
> 
> I still like this approach.
> 
> Jason

Thanks.

Here's a v2.2 of the patch.

gcc/ChangeLog:
	PR c++/43486
	* 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.
	(location_wrapper_p): New inline function.
	(tree_strip_any_location_wrapper): New inline function.

gcc/cp/ChangeLog:
	PR c++/43486
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
---
 gcc/cp/cp-tree.h |  6 +++++
 gcc/tree.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/tree.h       | 52 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 127 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4780df4..aa579a4 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.c b/gcc/tree.c
index 5416866..253d239 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13791,6 +13791,38 @@ 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.
+   VIEW_CONVERT_EXPR is used for wrapping non-constants.
+
+   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;
+
+  if (CONSTANT_CLASS_P (expr))
+    return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (expr), expr);
+  else
+    return build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+}
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
@@ -14016,6 +14048,42 @@ test_labels ()
   ASSERT_FALSE (FORCED_LABEL (label_decl));
 }
 
+/* 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 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
@@ -14024,6 +14092,7 @@ tree_c_tests ()
   test_integer_constants ();
   test_identifiers ();
   test_labels ();
+  test_location_wrappers ();
 }
 
 } // namespace selftest
diff --git a/gcc/tree.h b/gcc/tree.h
index db67858..acb5883 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)
@@ -1146,6 +1152,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)
@@ -3643,6 +3651,50 @@ id_equal (const char *str, const_tree id)
   return !strcmp (str, IDENTIFIER_POINTER (id));
 }
 
+/* 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).
+
+   A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and the
+   same type as its operand.
+
+   NON_LVALUE_EXPR is used for wrapping constants.
+   VIEW_CONVERT_EXPR is used for wrapping non-constants.
+
+   A subtlety is that we may have to test whether we have the correct
+   TREE_CODE for the wrapped TREE_CODE.  Otherwise, e.g. the C++ expression:
+     reinterpret_cast<int>(some_int_var)
+   is a NON_LVALUE_EXPR around a non-constant of the same type, and
+   could thus be mischaracterized as a location wrapper node.
+
+   Hence we need to check CONSTANT_CLASS_P (TREE_OPERAND (EXP, 0))
+   for a NON_LVALUE_EXPR for EXP to be a wrapper.
+   We don't need to check a VIEW_CONVERT_EXPR that wraps the same type
+   for !CONSTANT_CLASS_P; such instances of VIEW_CONVERT_EXPR are always
+   wrappers.  */
+
+inline bool
+location_wrapper_p (const_tree exp)
+{
+  if (((TREE_CODE (exp) == NON_LVALUE_EXPR
+	&& CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+       || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
+      && (TREE_TYPE (exp)
+	  == TREE_TYPE (TREE_OPERAND (exp, 0))))
+    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

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

* Re: [PATCH, v2.2] Support for adding and stripping location_t wrapper nodes
  2017-11-30 18:38                       ` [PATCH, v2.2] " David Malcolm
@ 2017-11-30 20:30                         ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-11-30 20:30 UTC (permalink / raw)
  To: David Malcolm
  Cc: Richard Biener, Jakub Jelinek, Trevor Saunders, Nathan Sidwell,
	gcc-patches List

On Thu, Nov 30, 2017 at 1:26 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> +/* 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).
> +
> +   A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and the
> +   same type as its operand.
> +
> +   NON_LVALUE_EXPR is used for wrapping constants.
> +   VIEW_CONVERT_EXPR is used for wrapping non-constants.
> +
> +   A subtlety is that we may have to test whether we have the correct
> +   TREE_CODE for the wrapped TREE_CODE.  Otherwise, e.g. the C++ expression:
> +     reinterpret_cast<int>(some_int_var)
> +   is a NON_LVALUE_EXPR around a non-constant of the same type, and
> +   could thus be mischaracterized as a location wrapper node.
> +
> +   Hence we need to check CONSTANT_CLASS_P (TREE_OPERAND (EXP, 0))
> +   for a NON_LVALUE_EXPR for EXP to be a wrapper.
> +   We don't need to check a VIEW_CONVERT_EXPR that wraps the same type
> +   for !CONSTANT_CLASS_P; such instances of VIEW_CONVERT_EXPR are always
> +   wrappers.  */

I think most of this comment (everything after the first paragraph)
belongs inside the function rather than before it.  OK with that
change.

Jason

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

* Re: [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486)
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (15 preceding siblings ...)
  2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
@ 2017-11-30 20:54         ` David Malcolm
  2017-12-11 16:08           ` [PING ^ 2] " David Malcolm
  2017-12-17  1:10         ` [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size David Malcolm
  2018-01-10 19:51         ` [committed] Preserving locations for variable-uses and constants (PR c++/43486) David Malcolm
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-11-30 20:54 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

Ping for the rest of this kit:
  https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00880.html

(thanks for the review of patch 2 of the kit)

On Fri, 2017-11-10 at 16:45 -0500, David Malcolm wrote:
> On Thu, 2017-11-02 at 10:46 -0400, Jason Merrill wrote:
> > On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <dmalcolm@redhat.com
> > >
> > wrote:
> > > On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
> > > > On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redhat
> > > > .c
> > > > om>
> > > > wrote:
> > > > > Design questions:
> > > > > 
> > > > > * The patch introduces a new kind of tree node, currently
> > > > > called
> > > > >   DECL_WRAPPER_EXPR (although it's used for wrapping
> > > > > constants
> > > > > as
> > > > > well
> > > > >   as decls).  Should wrappers be a new kind of tree node, or
> > > > > should
> > > > > they
> > > > >   reuse an existing TREE_CODE? (e.g. NOP_EXPR, CONVERT_EXPR,
> > > > > etc).
> > > > >     * NOP_EXPR: seems to be for use as an rvalue
> > > > >     * CONVERT_EXPR: for type conversions
> > > > >     * NON_LVALUE_EXPR: "Value is same as argument, but
> > > > > guaranteed
> > > > > not an
> > > > >       lvalue"
> > > > >       * but we *do* want to support lvalues here
> > > > 
> > > > I think using NON_LVALUE_EXPR for constants would be
> > > > appropriate.
> > > > 
> > > > >     * VIEW_CONVERT_EXPR: viewing one thing as of a different
> > > > > type
> > > > >       * can it support lvalues?
> > > > 
> > > > Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues, it
> > > > seems
> > > > like the right choice.
> > > > 
> > > > Jason
> > > 
> > > Thanks.  I've been working on a new version of the patch using
> > > those
> > > tree codes, but have run into an issue.
> > > 
> > > In g++.dg/conversion/reinterpret1.C:
> > > 
> > >   // PR c++/15076
> > > 
> > >   struct Y { Y(int &); };
> > > 
> > >   int v;
> > >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > > 
> > > With trunk, this successfully generates an error:
> > > 
> > >   reinterpret1.C:6:6: error: cannot bind non-const lvalue
> > > reference
> > > of type ‘int&’ to an rvalue of type ‘int’
> > >    Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > >         ^~~~~~~~~~~~~~~~~~~~~~~~
> > >   reinterpret1.C:3:12: note:   initializing argument 1 of
> > > ‘Y::Y(int&)’
> > >    struct Y { Y(int &); };
> > >               ^
> > > 
> > > where internally there's a NON_LVALUE_EXPR around a VAR_DECL,
> > > where
> > > both have the same type:
> > > 
> > > (gdb) call debug_tree (expr)
> > >  <non_lvalue_expr 0x7ffff145f6e0
> > >     type <integer_type 0x7ffff132e5e8 int public type_6 SI
> > >         size <integer_cst 0x7ffff1331120 constant 32>
> > >         unit-size <integer_cst 0x7ffff1331138 constant 4>
> > >         align:32 warn_if_not_align:0 symtab:0 alias-set -1
> > > canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst
> > > 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0
> > > 2147483647>
> > >         pointer_to_this <pointer_type 0x7ffff1336a80>
> > > reference_to_this <reference_type 0x7ffff144ca80>>
> > > 
> > >     arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type
> > > 0x7ffff132e5e8 int>
> > >         used public static tree_1 read SI /home/david/coding-
> > > 3/gcc-
> > > git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5 size
> > > <integer_cst 0x7ffff1331120 32> unit-size <integer_cst
> > > 0x7ffff1331138 4>
> > >         align:32 warn_if_not_align:0 context
> > > <translation_unit_decl
> > > 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > >         chain <type_decl 0x7ffff141a720 Y type <record_type
> > > 0x7ffff144c150 Y>
> > >             public decl_2 VOID /home/david/coding-3/gcc-git-expr-
> > > vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
> > >             align:8 warn_if_not_align:0 context
> > > <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-
> > > git-
> > > expr-vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > > chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
> > >     /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > start:
> > > /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > finish:
> > > /home/david/coding-3/gcc-git-expr-vs-
> > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
> > > 
> > > The problem is that this reinterpret cast "looks" just like one
> > > of
> > > my
> > > location wrappers.
> > 
> > Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.
> > > I see a similar issue with constants, where with:
> > > 
> > >   struct Y { Y(int &); };
> > >   Y y1(reinterpret_cast<int>(42));
> > > 
> > > trunk generates an error like the above, but my code handles the
> > >   NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> > > as if it were a location wrapper around the INTEGER_CST, and thus
> > > doesn't emit the error.
> > 
> > Why doesn't it emit the error?  We should get the same error
> > whether
> > or not we strip the wrapper.
> 
> Thanks: my stripping macro was over-zealous: it was stripping any
> NON_LVALUE_EXPR or VIEW_CONVERT_EXPR where the type matched that of
> the wrapped node.  I've added the additional condition that a
> NON_LVALUE_EXPR has to be around a CONSTANT_CLASS_P, and
> a VIEW_CONVERT_EXPR around a !CONSTANT_CLASS_P.
> 
> Here's an updated version of the patch (v2), now a patch kit (on top
> of r254387).  I split it up thematically for ease of review, but all
> the patches go together.
> 
> This version of the patch kit bootstraps and passes the regression
> tests (on x86_64-pc-linux-gnu)
> 
> To do so, I've made some simplfications to how wrappers nodes are
> added.
> 
> The previous patch added wrappers in the C++ parser around constants
> and uses-of-declarations, along with some other places in the
> parser (typeid, alignof, sizeof, offsetof).
> 
> This version takes a much more minimal approach: it only adds
> location wrapper nodes around the arguments at callsites, thus
> not adding wrapper nodes around uses of constants and decls in other
> locations.
> 
> It keeps them for the other places in the parser (typeid, alignof,
> sizeof, offsetof).
> 
> In addition, for now, each site that adds wrapper nodes is guarded
> with !processing_template_decl, suppressing the creation of wrapper
> nodes when processing template declarations.  This is to simplify
> the patch kit so that we don't have to support wrapper nodes during
> template expansion.
> 
> With this, we get a big usability win: we always have a location_t
> for every argument at a callsite, and so various errors involving
> mismatching arguments are much easier to read (as the pertinent
> argument is underlined).
> 
> I marked this as "PR 43486" as it's a big step towards solving that
> PR (which seeks to preserve locations all the way through to the
> middle end), but much more would need to be done to solve it:
> 
> * this patch kit only adds wrappers to the C++ frontend, not to C
> 
> * as noted above, location_t wrapper nodes are only added at
>   arguments of callsites (and a few other places), with some
>   restrictions.
> 
> * none of the wrapper nodes survive past gimplification;
>   it's not clear to me how best to preserve them into the
>   middle-end.  But even without doing so, we get the big usability
>   win.
> 
> The later parts of the patch kit add STRIP_ANY_LOCATION_WRAPPER uses
> in various places where the tree code of an expression is examined,
> so that such conditions use the code of the wrapped node, rather
> than that of the wrapper.  One of the risks of the patch kit is that
> although the testsuite passes, there are probably places in our code
> which still need uses of STRIP_ANY_LOCATION_WRAPPER.
> 
> 
> Performance of the patch kit
> ****************************
> 
> Benchmarking shows an apparent 2-3% in cc1plus wallclock compile-time
> for kdecore.cc -O3 -g:
> 
> Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu:
> wall
>       control: [56.55, 56.54, 56.68, 56.51, 56.45, 56.5, 56.45,
> 56.46, 56.49, 56.5, 56.42, 56.37, 56.41, 56.55]
>    experiment: [57.32, 58.37, 58.17, 58.18, 58.78, 58.48, 57.99,
> 58.16, 58.14, 57.62, 58.36, 58.1, 57.71, 57.7]
> Min: 56.370000 -> 57.320000: 1.02x slower
> Avg: 56.491429 -> 58.077143: 1.03x slower
> Significant (t=-15.14)
> Stddev: 0.07655 -> 0.38426: 5.0199x larger
> 
> although I'm not quite sure why; the difference is in "phase setup",
> which
> gains a large "wall" value (but not in usr or sys), whereas "phase
> parsing"
> is unaffected:
> 
> unpatched:
> 
>  phase setup             :   0.00 ( 0%) usr   0.02 ( 0%) sys   0.02 (
> 0%) wall    1488 kB ( 0%) ggc
>  phase parsing           :   1.83 ( 4%) usr   0.82 (16%) sys   2.66 (
> 5%) wall  156603 kB (12%) ggc
>  phase lang. deferred    :   0.30 ( 1%) usr   0.09 ( 2%) sys   0.38 (
> 1%) wall   29861 kB ( 2%) ggc
>  phase opt and generate  :  48.09 (94%) usr   4.28 (81%) sys  52.55
> (93%) wall 1085420 kB (84%) ggc
>  phase last asm          :   0.86 ( 2%) usr   0.05 ( 1%) sys   0.92 (
> 2%) wall   15806 kB ( 1%) ggc
>  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.01 (
> 0%) wall       0 kB ( 0%) ggc
>  |name lookup            :   0.30 ( 1%) usr   0.13 ( 2%) sys   0.21 (
> 0%) wall    4955 kB ( 0%) ggc
>  |overload resolution    :   0.49 ( 1%) usr   0.06 ( 1%) sys   0.68 (
> 1%) wall   27263 kB ( 2%) ggc
>  garbage collection      :   0.77 ( 2%) usr   0.00 ( 0%) sys   0.77 (
> 1%) wall       0 kB ( 0%) ggc
>  [...]
>  TOTAL                 :  51.08             5.27            56.54    
>         1289189 kB
> 
> patched:
>  phase setup             :   0.01 ( 0%) usr   0.03 ( 1%) sys   1.91 (
> 3%) wall    1488 kB ( 0%) ggc
>  phase parsing           :   1.80 ( 4%) usr   0.84 (16%) sys   2.66 (
> 5%) wall  158066 kB (12%) ggc
>  phase lang. deferred    :   0.29 ( 1%) usr   0.09 ( 2%) sys   0.39 (
> 1%) wall   29861 kB ( 2%) ggc
>  phase opt and generate  :  48.09 (94%) usr   4.27 (81%) sys  52.52
> (90%) wall 1085428 kB (84%) ggc
>  phase last asm          :   0.82 ( 2%) usr   0.05 ( 1%) sys   0.89 (
> 2%) wall   15806 kB ( 1%) ggc
>  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.00 (
> 0%) wall       0 kB ( 0%) ggc
>  |name lookup            :   0.29 ( 1%) usr   0.07 ( 1%) sys   0.36 (
> 1%) wall    4955 kB ( 0%) ggc
>  |overload resolution    :   0.51 ( 1%) usr   0.07 ( 1%) sys   0.50 (
> 1%) wall   27296 kB ( 2%) ggc
>  garbage collection      :   0.79 ( 2%) usr   0.00 ( 0%) sys   0.78 (
> 1%) wall       0 kB ( 0%) ggc
>  TOTAL                 :  51.01             5.29            58.37    
>         1290660 kB
> 
> What's up with that "phase setup" change?  Did I mess up my testing
> somehow?
> 
> 
> ...and a slight increase in GGC usage:
> 
> Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu: ggc
>       control: [1289179.0, 1289189.0, 1289170.0, 1289186.0,
> 1289194.0, 1289172.0, 1289176.0, 1289192.0, 1289189.0, 1289179.0,
> 1289172.0, 1289190.0, 1289169.0, 1289185.0]
>    experiment: [1290654.0, 1290660.0, 1290655.0, 1290659.0,
> 1290631.0, 1290655.0, 1290650.0, 1290652.0, 1290642.0, 1290650.0,
> 1290658.0, 1290662.0, 1290638.0, 1290655.0]
> Mem max: 1289194.000 -> 1290662.000: 1.0011x larger
> 
> (this is with stripped binaries, and --enable-checking=release)
> 
> Testing with a simple file that includes all of the C++ standard
> library
> (but doesn't do anything with it) shows no change in time, and GGC
> usage
> in the parsing phase increasing 50kB from 149954 kB to 150004 kB.
> 
> 
> Next steps?
> ***********
> 
> I'm working on extending the patch kit to add wrapper nodes at all
> constants and uses-of-decls in the C++ parser, but of course this
> could have some effect on time/memory, and require more uses of
> STRIP_ANY_LOCATION_WRAPPER.
> 
> An alternative appoach is:
> 
>   "[PATCH] C++: use an optional vec<location_t> for callsites"
>     https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
> 
> which eschews wrapper nodes in favor of duplicating the C frontend's
> workaround here (though Jason disliked this approach, when we
> discussed
> it at Cauldron).
> 
> Thoughts?
> 
> (I'm keen on getting *some* solution for providing location_t values
> for arguments at C++ callsites into gcc 8)
> 
> 
> David Malcolm (14):
>   C++: preserve locations within build_address
>   Support for adding and stripping location_t wrapper nodes
>   C++: add location_t wrapper nodes during parsing (minimal impl)
>   Update testsuite to show improvements
>   tree.c: strip location wrappers from integer_zerop etc
>   Fix Wsizeof-pointer-memaccess*.c
>   reject_gcc_builtin: strip any location wrappers
>   cp/tree.c: strip location wrappers in lvalue_kind
>   Strip location wrappers in null_ptr_cst_p
>   warn_for_memset: handle location wrappers
>   Handle location wrappers in string_conv_p
>   C++: introduce null_node_p
>   c-format.c: handle location wrappers
>   pp_c_cast_expression: don't print casts for location wrappers
> 
>  gcc/c-family/c-common.c                            |   3 +
>  gcc/c-family/c-common.h                            |   1 +
>  gcc/c-family/c-format.c                            |   9 +-
>  gcc/c-family/c-pretty-print.c                      |  66 +++++-
>  gcc/c-family/c-warn.c                              |   8 +
>  gcc/cp/call.c                                      |   6 +-
>  gcc/cp/cp-tree.h                                   |  13 ++
>  gcc/cp/cvt.c                                       |   2 +-
>  gcc/cp/error.c                                     |   2 +-
>  gcc/cp/except.c                                    |   2 +-
>  gcc/cp/parser.c                                    |  30 ++-
>  gcc/cp/tree.c                                      |   2 +
>  gcc/cp/typeck.c                                    |   6 +-
>  .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
>  .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260
> +++++++++++++--------
>  gcc/tree.c                                         |  59 +++++
>  gcc/tree.h                                         |  26 +++
>  17 files changed, 392 insertions(+), 130 deletions(-)
> 

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

* [PING ^ 2] Re: [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486)
  2017-11-30 20:54         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
@ 2017-12-11 16:08           ` David Malcolm
  0 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-12-11 16:08 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

Ping for this patch kit:
  https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00880.html

(and thanks again for looking at patch 2 earlier)


On Thu, 2017-11-30 at 14:17 -0500, David Malcolm wrote:
> Ping for the rest of this kit:
>   https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00880.html
> 
> (thanks for the review of patch 2 of the kit)
> 
> On Fri, 2017-11-10 at 16:45 -0500, David Malcolm wrote:
> > On Thu, 2017-11-02 at 10:46 -0400, Jason Merrill wrote:
> > > On Tue, Oct 31, 2017 at 5:09 PM, David Malcolm <dmalcolm@redhat.c
> > > om
> > > > 
> > > 
> > > wrote:
> > > > On Tue, 2017-10-24 at 09:53 -0400, Jason Merrill wrote:
> > > > > On Fri, Oct 20, 2017 at 5:53 PM, David Malcolm <dmalcolm@redh
> > > > > at
> > > > > .c
> > > > > om>
> > > > > wrote:
> > > > > > Design questions:
> > > > > > 
> > > > > > * The patch introduces a new kind of tree node, currently
> > > > > > called
> > > > > >   DECL_WRAPPER_EXPR (although it's used for wrapping
> > > > > > constants
> > > > > > as
> > > > > > well
> > > > > >   as decls).  Should wrappers be a new kind of tree node,
> > > > > > or
> > > > > > should
> > > > > > they
> > > > > >   reuse an existing TREE_CODE? (e.g. NOP_EXPR,
> > > > > > CONVERT_EXPR,
> > > > > > etc).
> > > > > >     * NOP_EXPR: seems to be for use as an rvalue
> > > > > >     * CONVERT_EXPR: for type conversions
> > > > > >     * NON_LVALUE_EXPR: "Value is same as argument, but
> > > > > > guaranteed
> > > > > > not an
> > > > > >       lvalue"
> > > > > >       * but we *do* want to support lvalues here
> > > > > 
> > > > > I think using NON_LVALUE_EXPR for constants would be
> > > > > appropriate.
> > > > > 
> > > > > >     * VIEW_CONVERT_EXPR: viewing one thing as of a
> > > > > > different
> > > > > > type
> > > > > >       * can it support lvalues?
> > > > > 
> > > > > Yes, the purpose of VIEW_CONVERT_EXPR is to support lvalues,
> > > > > it
> > > > > seems
> > > > > like the right choice.
> > > > > 
> > > > > Jason
> > > > 
> > > > Thanks.  I've been working on a new version of the patch using
> > > > those
> > > > tree codes, but have run into an issue.
> > > > 
> > > > In g++.dg/conversion/reinterpret1.C:
> > > > 
> > > >   // PR c++/15076
> > > > 
> > > >   struct Y { Y(int &); };
> > > > 
> > > >   int v;
> > > >   Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > > > 
> > > > With trunk, this successfully generates an error:
> > > > 
> > > >   reinterpret1.C:6:6: error: cannot bind non-const lvalue
> > > > reference
> > > > of type ‘int&’ to an rvalue of type ‘int’
> > > >    Y y1(reinterpret_cast<int>(v));  // { dg-error "" }
> > > >         ^~~~~~~~~~~~~~~~~~~~~~~~
> > > >   reinterpret1.C:3:12: note:   initializing argument 1 of
> > > > ‘Y::Y(int&)’
> > > >    struct Y { Y(int &); };
> > > >               ^
> > > > 
> > > > where internally there's a NON_LVALUE_EXPR around a VAR_DECL,
> > > > where
> > > > both have the same type:
> > > > 
> > > > (gdb) call debug_tree (expr)
> > > >  <non_lvalue_expr 0x7ffff145f6e0
> > > >     type <integer_type 0x7ffff132e5e8 int public type_6 SI
> > > >         size <integer_cst 0x7ffff1331120 constant 32>
> > > >         unit-size <integer_cst 0x7ffff1331138 constant 4>
> > > >         align:32 warn_if_not_align:0 symtab:0 alias-set -1
> > > > canonical-type 0x7ffff132e5e8 precision:32 min <integer_cst
> > > > 0x7ffff13310d8 -2147483648> max <integer_cst 0x7ffff13310f0
> > > > 2147483647>
> > > >         pointer_to_this <pointer_type 0x7ffff1336a80>
> > > > reference_to_this <reference_type 0x7ffff144ca80>>
> > > > 
> > > >     arg:0 <var_decl 0x7ffff7ffbd80 v type <integer_type
> > > > 0x7ffff132e5e8 int>
> > > >         used public static tree_1 read SI /home/david/coding-
> > > > 3/gcc-
> > > > git-expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:5:5
> > > > size
> > > > <integer_cst 0x7ffff1331120 32> unit-size <integer_cst
> > > > 0x7ffff1331138 4>
> > > >         align:32 warn_if_not_align:0 context
> > > > <translation_unit_decl
> > > > 0x7ffff131e168 /home/david/coding-3/gcc-git-expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > > >         chain <type_decl 0x7ffff141a720 Y type <record_type
> > > > 0x7ffff144c150 Y>
> > > >             public decl_2 VOID /home/david/coding-3/gcc-git-
> > > > expr-
> > > > vs-decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:3:8
> > > >             align:8 warn_if_not_align:0 context
> > > > <translation_unit_decl 0x7ffff131e168 /home/david/coding-3/gcc-
> > > > git-
> > > > expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C>
> > > > chain <function_decl 0x7ffff144f800 __cxa_call_unexpected>>>
> > > >     /home/david/coding-3/gcc-git-expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > > start:
> > > > /home/david/coding-3/gcc-git-expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:6
> > > > finish:
> > > > /home/david/coding-3/gcc-git-expr-vs-
> > > > decl/src/gcc/testsuite/g++.dg/conversion/reinterpret1.C:6:29>
> > > > 
> > > > The problem is that this reinterpret cast "looks" just like one
> > > > of
> > > > my
> > > > location wrappers.
> > > 
> > > Your code shouldn't strip a NON_LVALUE_EXPR around a VAR_DECL.
> > > > I see a similar issue with constants, where with:
> > > > 
> > > >   struct Y { Y(int &); };
> > > >   Y y1(reinterpret_cast<int>(42));
> > > > 
> > > > trunk generates an error like the above, but my code handles
> > > > the
> > > >   NON_LVALUE_EXPR<int>(INTEGER_CST<int>(42))
> > > > as if it were a location wrapper around the INTEGER_CST, and
> > > > thus
> > > > doesn't emit the error.
> > > 
> > > Why doesn't it emit the error?  We should get the same error
> > > whether
> > > or not we strip the wrapper.
> > 
> > Thanks: my stripping macro was over-zealous: it was stripping any
> > NON_LVALUE_EXPR or VIEW_CONVERT_EXPR where the type matched that of
> > the wrapped node.  I've added the additional condition that a
> > NON_LVALUE_EXPR has to be around a CONSTANT_CLASS_P, and
> > a VIEW_CONVERT_EXPR around a !CONSTANT_CLASS_P.
> > 
> > Here's an updated version of the patch (v2), now a patch kit (on
> > top
> > of r254387).  I split it up thematically for ease of review, but
> > all
> > the patches go together.
> > 
> > This version of the patch kit bootstraps and passes the regression
> > tests (on x86_64-pc-linux-gnu)
> > 
> > To do so, I've made some simplfications to how wrappers nodes are
> > added.
> > 
> > The previous patch added wrappers in the C++ parser around
> > constants
> > and uses-of-declarations, along with some other places in the
> > parser (typeid, alignof, sizeof, offsetof).
> > 
> > This version takes a much more minimal approach: it only adds
> > location wrapper nodes around the arguments at callsites, thus
> > not adding wrapper nodes around uses of constants and decls in
> > other
> > locations.
> > 
> > It keeps them for the other places in the parser (typeid, alignof,
> > sizeof, offsetof).
> > 
> > In addition, for now, each site that adds wrapper nodes is guarded
> > with !processing_template_decl, suppressing the creation of wrapper
> > nodes when processing template declarations.  This is to simplify
> > the patch kit so that we don't have to support wrapper nodes during
> > template expansion.
> > 
> > With this, we get a big usability win: we always have a location_t
> > for every argument at a callsite, and so various errors involving
> > mismatching arguments are much easier to read (as the pertinent
> > argument is underlined).
> > 
> > I marked this as "PR 43486" as it's a big step towards solving that
> > PR (which seeks to preserve locations all the way through to the
> > middle end), but much more would need to be done to solve it:
> > 
> > * this patch kit only adds wrappers to the C++ frontend, not to C
> > 
> > * as noted above, location_t wrapper nodes are only added at
> >   arguments of callsites (and a few other places), with some
> >   restrictions.
> > 
> > * none of the wrapper nodes survive past gimplification;
> >   it's not clear to me how best to preserve them into the
> >   middle-end.  But even without doing so, we get the big usability
> >   win.
> > 
> > The later parts of the patch kit add STRIP_ANY_LOCATION_WRAPPER
> > uses
> > in various places where the tree code of an expression is examined,
> > so that such conditions use the code of the wrapped node, rather
> > than that of the wrapper.  One of the risks of the patch kit is
> > that
> > although the testsuite passes, there are probably places in our
> > code
> > which still need uses of STRIP_ANY_LOCATION_WRAPPER.
> > 
> > 
> > Performance of the patch kit
> > ****************************
> > 
> > Benchmarking shows an apparent 2-3% in cc1plus wallclock compile-
> > time
> > for kdecore.cc -O3 -g:
> > 
> > Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu:
> > wall
> >       control: [56.55, 56.54, 56.68, 56.51, 56.45, 56.5, 56.45,
> > 56.46, 56.49, 56.5, 56.42, 56.37, 56.41, 56.55]
> >    experiment: [57.32, 58.37, 58.17, 58.18, 58.78, 58.48, 57.99,
> > 58.16, 58.14, 57.62, 58.36, 58.1, 57.71, 57.7]
> > Min: 56.370000 -> 57.320000: 1.02x slower
> > Avg: 56.491429 -> 58.077143: 1.03x slower
> > Significant (t=-15.14)
> > Stddev: 0.07655 -> 0.38426: 5.0199x larger
> > 
> > although I'm not quite sure why; the difference is in "phase
> > setup",
> > which
> > gains a large "wall" value (but not in usr or sys), whereas "phase
> > parsing"
> > is unaffected:
> > 
> > unpatched:
> > 
> >  phase setup             :   0.00 ( 0%) usr   0.02 ( 0%) sys   0.02
> > (
> > 0%) wall    1488 kB ( 0%) ggc
> >  phase parsing           :   1.83 ( 4%) usr   0.82 (16%) sys   2.66
> > (
> > 5%) wall  156603 kB (12%) ggc
> >  phase lang. deferred    :   0.30 ( 1%) usr   0.09 ( 2%) sys   0.38
> > (
> > 1%) wall   29861 kB ( 2%) ggc
> >  phase opt and generate  :  48.09 (94%) usr   4.28 (81%) sys  52.55
> > (93%) wall 1085420 kB (84%) ggc
> >  phase last asm          :   0.86 ( 2%) usr   0.05 ( 1%) sys   0.92
> > (
> > 2%) wall   15806 kB ( 1%) ggc
> >  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.01
> > (
> > 0%) wall       0 kB ( 0%) ggc
> >  |name lookup            :   0.30 ( 1%) usr   0.13 ( 2%) sys   0.21
> > (
> > 0%) wall    4955 kB ( 0%) ggc
> >  |overload resolution    :   0.49 ( 1%) usr   0.06 ( 1%) sys   0.68
> > (
> > 1%) wall   27263 kB ( 2%) ggc
> >  garbage collection      :   0.77 ( 2%) usr   0.00 ( 0%) sys   0.77
> > (
> > 1%) wall       0 kB ( 0%) ggc
> >  [...]
> >  TOTAL                 :  51.08             5.27            56.54  
> >   
> >         1289189 kB
> > 
> > patched:
> >  phase setup             :   0.01 ( 0%) usr   0.03 ( 1%) sys   1.91
> > (
> > 3%) wall    1488 kB ( 0%) ggc
> >  phase parsing           :   1.80 ( 4%) usr   0.84 (16%) sys   2.66
> > (
> > 5%) wall  158066 kB (12%) ggc
> >  phase lang. deferred    :   0.29 ( 1%) usr   0.09 ( 2%) sys   0.39
> > (
> > 1%) wall   29861 kB ( 2%) ggc
> >  phase opt and generate  :  48.09 (94%) usr   4.27 (81%) sys  52.52
> > (90%) wall 1085428 kB (84%) ggc
> >  phase last asm          :   0.82 ( 2%) usr   0.05 ( 1%) sys   0.89
> > (
> > 2%) wall   15806 kB ( 1%) ggc
> >  phase finalize          :   0.00 ( 0%) usr   0.01 ( 0%) sys   0.00
> > (
> > 0%) wall       0 kB ( 0%) ggc
> >  |name lookup            :   0.29 ( 1%) usr   0.07 ( 1%) sys   0.36
> > (
> > 1%) wall    4955 kB ( 0%) ggc
> >  |overload resolution    :   0.51 ( 1%) usr   0.07 ( 1%) sys   0.50
> > (
> > 1%) wall   27296 kB ( 2%) ggc
> >  garbage collection      :   0.79 ( 2%) usr   0.00 ( 0%) sys   0.78
> > (
> > 1%) wall       0 kB ( 0%) ggc
> >  TOTAL                 :  51.01             5.29            58.37  
> >   
> >         1290660 kB
> > 
> > What's up with that "phase setup" change?  Did I mess up my testing
> > somehow?
> > 
> > 
> > ...and a slight increase in GGC usage:
> > 
> > Compilation of kdecore.cc at -O3 with -g for x86_64-pc-linux-gnu:
> > ggc
> >       control: [1289179.0, 1289189.0, 1289170.0, 1289186.0,
> > 1289194.0, 1289172.0, 1289176.0, 1289192.0, 1289189.0, 1289179.0,
> > 1289172.0, 1289190.0, 1289169.0, 1289185.0]
> >    experiment: [1290654.0, 1290660.0, 1290655.0, 1290659.0,
> > 1290631.0, 1290655.0, 1290650.0, 1290652.0, 1290642.0, 1290650.0,
> > 1290658.0, 1290662.0, 1290638.0, 1290655.0]
> > Mem max: 1289194.000 -> 1290662.000: 1.0011x larger
> > 
> > (this is with stripped binaries, and --enable-checking=release)
> > 
> > Testing with a simple file that includes all of the C++ standard
> > library
> > (but doesn't do anything with it) shows no change in time, and GGC
> > usage
> > in the parsing phase increasing 50kB from 149954 kB to 150004 kB.
> > 
> > 
> > Next steps?
> > ***********
> > 
> > I'm working on extending the patch kit to add wrapper nodes at all
> > constants and uses-of-decls in the C++ parser, but of course this
> > could have some effect on time/memory, and require more uses of
> > STRIP_ANY_LOCATION_WRAPPER.
> > 
> > An alternative appoach is:
> > 
> >   "[PATCH] C++: use an optional vec<location_t> for callsites"
> >     https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01392.html
> > 
> > which eschews wrapper nodes in favor of duplicating the C
> > frontend's
> > workaround here (though Jason disliked this approach, when we
> > discussed
> > it at Cauldron).
> > 
> > Thoughts?
> > 
> > (I'm keen on getting *some* solution for providing location_t
> > values
> > for arguments at C++ callsites into gcc 8)
> > 
> > 
> > David Malcolm (14):
> >   C++: preserve locations within build_address
> >   Support for adding and stripping location_t wrapper nodes
> >   C++: add location_t wrapper nodes during parsing (minimal impl)
> >   Update testsuite to show improvements
> >   tree.c: strip location wrappers from integer_zerop etc
> >   Fix Wsizeof-pointer-memaccess*.c
> >   reject_gcc_builtin: strip any location wrappers
> >   cp/tree.c: strip location wrappers in lvalue_kind
> >   Strip location wrappers in null_ptr_cst_p
> >   warn_for_memset: handle location wrappers
> >   Handle location wrappers in string_conv_p
> >   C++: introduce null_node_p
> >   c-format.c: handle location wrappers
> >   pp_c_cast_expression: don't print casts for location wrappers
> > 
> >  gcc/c-family/c-common.c                            |   3 +
> >  gcc/c-family/c-common.h                            |   1 +
> >  gcc/c-family/c-format.c                            |   9 +-
> >  gcc/c-family/c-pretty-print.c                      |  66 +++++-
> >  gcc/c-family/c-warn.c                              |   8 +
> >  gcc/cp/call.c                                      |   6 +-
> >  gcc/cp/cp-tree.h                                   |  13 ++
> >  gcc/cp/cvt.c                                       |   2 +-
> >  gcc/cp/error.c                                     |   2 +-
> >  gcc/cp/except.c                                    |   2 +-
> >  gcc/cp/parser.c                                    |  30 ++-
> >  gcc/cp/tree.c                                      |   2 +
> >  gcc/cp/typeck.c                                    |   6 +-
> >  .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
> >  .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 260
> > +++++++++++++--------
> >  gcc/tree.c                                         |  59 +++++
> >  gcc/tree.h                                         |  26 +++
> >  17 files changed, 392 insertions(+), 130 deletions(-)
> > 

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

* Re: [PATCH 01/14] C++: preserve locations within build_address
  2017-11-10 21:43         ` [PATCH 01/14] C++: preserve locations within build_address David Malcolm
@ 2017-12-11 23:25           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:25 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> This is needed for the locations of string literals to be usable,
> otherwise the ADDR_EXPR has UNKNOWN_LOCATION, despite wrapping
> a node with a correct location_t.
> 
> gcc/cp/ChangeLog:
> 	* typeck.c (build_address): Use location of operand when building
> 	address expression.

OK; this one seems obvious.

Jason

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

* Re: [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc
  2017-11-10 21:43         ` [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc David Malcolm
@ 2017-12-11 23:36           ` Jason Merrill
  2017-12-16 13:09             ` [PATCH] C++: handle locations wrappers when calling warn_for_memset David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:36 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> We need to strip away location wrappers in tree.c predicates like
> integer_zerop, otherwise they fail when they're called on
> wrapped INTEGER_CST; an example can be seen for
>    c-c++-common/Wmemset-transposed-args1.c
> in g++.sum, where the warn_for_memset fails to detect integer zero
> if the location wrappers aren't stripped.

These shouldn't be needed; callers should have folded away location 
wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be almost 
never needed.

warn_for_memset may be missing some calls to fold_for_warn.

>   int
>   really_constant_p (const_tree exp)
>   {
> +  STRIP_ANY_LOCATION_WRAPPER (exp);
> +
>     /* This is not quite the same as STRIP_NOPS.  It does more.  */
>     while (CONVERT_EXPR_P (exp)
>   	 || TREE_CODE (exp) == NON_LVALUE_EXPR)

Here we should be able to add VIEW_CONVERT_EXPR to the condition.

Similarly, tree_nop_conversion should treat a VIEW_CONVERT_EXPR to the 
same type as a nop.

Jason

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

* Re: [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c
  2017-11-10 21:43         ` [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c David Malcolm
@ 2017-12-11 23:37           ` Jason Merrill
  2017-12-18  2:04             ` [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:37 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> gcc/c-family/ChangeLog:
> 	* c-warn.c (sizeof_pointer_memaccess_warning): Strip any location
> 	wrappers from src and dest.

Here the existing calls to tree_strip_nop_conversions ought to handle 
the wrappers.

Jason

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

* Re: [PATCH 07/14] reject_gcc_builtin: strip any location wrappers
  2017-11-10 21:43         ` [PATCH 07/14] reject_gcc_builtin: strip any location wrappers David Malcolm
@ 2017-12-11 23:38           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:38 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> Otherwise pr70144-1.c breaks.
> 
> gcc/c-family/ChangeLog:
> 	* c-common.c (reject_gcc_builtin): Strip any location from EXPR.
> ---
>   gcc/c-family/c-common.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 24077c7..739c54e 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -7774,6 +7774,8 @@ pointer_to_zero_sized_aggr_p (tree t)
>   bool
>   reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
>   {
> +  STRIP_ANY_LOCATION_WRAPPER (expr);
> +
>     if (TREE_CODE (expr) == ADDR_EXPR)
>       expr = TREE_OPERAND (expr, 0);

Don't you want to strip the wrapper after we strip the ADDR_EXPR?  OK 
with that change.

Jason

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

* Re: [PATCH 09/14] Strip location wrappers in null_ptr_cst_p
  2017-11-10 21:44         ` [PATCH 09/14] Strip location wrappers in null_ptr_cst_p David Malcolm
@ 2017-12-11 23:39           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:39 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> Without this, "NULL" fails to be usable in C++11 onwards.
> 
> gcc/cp/ChangeLog:
> 	* call.c (null_ptr_cst_p): Strip location wrappers when
> 	converting from '0' to a pointer type in C++11 onwards.

OK.

Jason

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

* Re: [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-11-10 21:44         ` [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind David Malcolm
@ 2017-12-11 23:39           ` Jason Merrill
  2017-12-20 22:11             ` [v2 of PATCH " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:39 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> Without this, then lvalue_p returns false for decls, and hence
> e.g. uses of them for references fail.
> 
> Stripping location wrappers in lvalue_kind restores the correct
> behavior of lvalue_p etc.
> 
> gcc/cp/ChangeLog:
> 	* tree.c (lvalue_kind): Strip any location wrapper.

Rather, lvalue_kind should learn to handle VIEW_CONVERT_EXPR.

Jason

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

* Re: [PATCH 10/14] warn_for_memset: handle location wrappers
  2017-11-10 21:44         ` [PATCH 10/14] warn_for_memset: handle location wrappers David Malcolm
@ 2017-12-11 23:41           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:41 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> gcc/c-family/ChangeLog:
> 	* c-warn.c (warn_for_memset): Strip any location wrappers
> 	from arg0 and arg2.
> 
> gcc/cp/ChangeLog:
> 	* parser.c (cp_parser_postfix_expression): Before warn_for_memset,
> 	strip any wrapper around "arg2" before testing for CONST_DECL.

Despite my earlier comment about fold_for_warn, I guess this is 
specifically interested in literals, so this is OK.

Jason

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

* Re: [PATCH 12/14] C++: introduce null_node_p
  2017-11-10 22:11         ` [PATCH 12/14] C++: introduce null_node_p David Malcolm
@ 2017-12-11 23:42           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:42 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> Eschew comparison with null_node in favor of a new null_node_p
> function, which strips any location wrappers.

OK.

Jason

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

* Re: [PATCH 11/14] Handle location wrappers in string_conv_p
  2017-11-10 21:44         ` [PATCH 11/14] Handle location wrappers in string_conv_p David Malcolm
@ 2017-12-11 23:42           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:42 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> gcc/cp/ChangeLog:
> 	* typeck.c (string_conv_p): Strip any location wrapper from "exp".

OK.

Jason

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

* Re: [PATCH 13/14] c-format.c: handle location wrappers
  2017-11-10 21:44         ` [PATCH 13/14] c-format.c: handle location wrappers David Malcolm
@ 2017-12-11 23:45           ` Jason Merrill
  2017-12-17 16:26             ` [v2 of PATCH " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:45 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> gcc/c-family/ChangeLog:
> 	* c-format.c (check_format_arg): Strip any location wrapper around
> 	format_tree.
> ---
>   gcc/c-family/c-format.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> index 164d035..6b436ec 100644
> --- a/gcc/c-family/c-format.c
> +++ b/gcc/c-family/c-format.c
> @@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree format_tree,
>   
>     location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
>   
> +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> +
>     if (VAR_P (format_tree))
>       {
>         /* Pull out a constant value if the front end didn't.  */

It seems like we want fold_for_warn here instead of the special variable 
handling.  That probably makes sense for the other places you change in 
this patch, too.

Jason

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

* Re: [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers
  2017-11-10 21:44         ` [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers David Malcolm
@ 2017-12-11 23:46           ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-11 23:46 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> This patch suppresses the user-visible printing of location wrappers
> for "%E" (and "%qE"), adding test coverage via selftests.

OK.

Jason

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-11-10 21:43         ` [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) David Malcolm
@ 2017-12-12  2:10           ` Jason Merrill
  2017-12-14 19:25             ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-12  2:10 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 11/10/2017 04:45 PM, David Malcolm wrote:
> The initial version of the patch kit added location wrapper nodes
> around constants and uses-of-declarations, along with some other
> places in the parser (typeid, alignof, sizeof, offsetof).
> 
> This version takes a much more minimal approach: it only adds
> location wrapper nodes around the arguments at callsites, thus
> not adding wrapper nodes around uses of constants and decls in other
> locations.
> 
> It keeps them for the other places in the parser (typeid, alignof,
> sizeof, offsetof).
> 
> In addition, for now, each site that adds wrapper nodes is guarded
> with !processing_template_decl, suppressing the creation of wrapper
> nodes when processing template declarations.  This is to simplify
> the patch kit so that we don't have to support wrapper nodes during
> template expansion.

Hmm, it should be easy to support them, since NON_LVALUE_EXPR and 
VIEW_CONVERT_EXPR don't otherwise appear in template trees.

Jason

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-12  2:10           ` Jason Merrill
@ 2017-12-14 19:25             ` David Malcolm
  2017-12-15 15:02               ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-14 19:25 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 3192 bytes --]

On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > The initial version of the patch kit added location wrapper nodes
> > around constants and uses-of-declarations, along with some other
> > places in the parser (typeid, alignof, sizeof, offsetof).
> > 
> > This version takes a much more minimal approach: it only adds
> > location wrapper nodes around the arguments at callsites, thus
> > not adding wrapper nodes around uses of constants and decls in
> > other
> > locations.
> > 
> > It keeps them for the other places in the parser (typeid, alignof,
> > sizeof, offsetof).
> > 
> > In addition, for now, each site that adds wrapper nodes is guarded
> > with !processing_template_decl, suppressing the creation of wrapper
> > nodes when processing template declarations.  This is to simplify
> > the patch kit so that we don't have to support wrapper nodes during
> > template expansion.
> 
> Hmm, it should be easy to support them, since NON_LVALUE_EXPR and 
> VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> 
> Jason

I don't know if it's "easy"; it's at least non-trivial.

I attempted to support them in the obvious way by adding the two codes
to the switch statement tsubst_copy, reusing the case used by NOP_EXPR
and others, but ran into a issue when dealing with template parameter
packs.

Attached is the reproducer I've been testing with (minimized using
"delta" from a stdlib reproducer); my code was failing with:

../../src/cp-stdlib.ii: In instantiation of ‘struct allocator_traits<allocator<char> >’:
../../src/cp-stdlib.ii:31:8:   required from ‘struct __alloc_traits<allocator<char>, char>’
../../src/cp-stdlib.ii:43:75:   required from ‘class basic_string<char, allocator<char> >’
../../src/cp-stdlib.ii:47:58:   required from here
../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of ‘type_pack_expansion’ in template
     -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
                                                       ^~~~~~

The issue is that normally "__args" would be a PARM_DECL of type
TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on adding a
wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
TYPE_PACK_EXPANSION wrapping the PARM_DECL.

When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached first,
and it attempts to substitute the type TYPE_PACK_EXPANSION, which leads
to the "sorry".

If I understand things right, during substitution, only tsubst_decl on
PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.

The simplest approach seems to be to not create wrapper nodes for decls
of type TYPE_PACK_EXPANSION, and that seems to fix the issue.

Alternatively I can handle TYPE_PACK_EXPANSION for VIEW_CONVERT_EXPR in
tsubst by remapping the type to that of what they wrap after
substitution; doing so also fixes the issue.

Does this sound correct and sane?  Do you have a preferred approach?

On fixing that I'm running into a different issue when testing the
stdlib (again with parameter packs, I think), but I'm still
investigating that one...

Thanks
Dave

[-- Attachment #2: cp-stdlib.ii --]
[-- Type: text/plain, Size: 1545 bytes --]

typedef long unsigned int size_t;

template<typename _Tp>
struct remove_reference {};

template<typename _Tp>
constexpr _Tp&&
forward(typename remove_reference<_Tp>::type& __t) noexcept
{
}

struct __allocator_traits_base {
  template<typename _Tp, typename _Up, typename = void>
  struct __rebind
  {
    using type = typename _Tp::template rebind<_Up>::other;
  };
};

template<typename _Alloc, typename _Up>
using __alloc_rebind = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;

template<typename _Alloc>  struct allocator_traits {
  template<typename _Tp>  using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
  template<typename _Tp, typename... _Args>
  static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
    -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
};

template<typename _Alloc, typename = typename _Alloc::value_type>
struct __alloc_traits    : allocator_traits<_Alloc>    {
  typedef allocator_traits<_Alloc> _Base_type;
  template<typename _Tp>       struct rebind       {   typedef typename _Base_type::template rebind_alloc<_Tp> other;   };
};

template<typename _Tp>     class allocator {
  typedef _Tp value_type;
  template<typename _Tp1>  struct rebind  {   typedef allocator<_Tp1> other;   };
};

template<typename _CharT, typename _Alloc>
class basic_string {
  typedef typename __alloc_traits<_Alloc>::template rebind<_CharT>::other _Char_alloc_type;
};

template<size_t _Nw>  struct _Base_bitset {
  static void foo (basic_string<char, allocator<char> >) {}
};

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-14 19:25             ` David Malcolm
@ 2017-12-15 15:02               ` Jason Merrill
  2017-12-15 16:35                 ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-15 15:02 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > The initial version of the patch kit added location wrapper nodes
>> > around constants and uses-of-declarations, along with some other
>> > places in the parser (typeid, alignof, sizeof, offsetof).
>> >
>> > This version takes a much more minimal approach: it only adds
>> > location wrapper nodes around the arguments at callsites, thus
>> > not adding wrapper nodes around uses of constants and decls in
>> > other
>> > locations.
>> >
>> > It keeps them for the other places in the parser (typeid, alignof,
>> > sizeof, offsetof).
>> >
>> > In addition, for now, each site that adds wrapper nodes is guarded
>> > with !processing_template_decl, suppressing the creation of wrapper
>> > nodes when processing template declarations.  This is to simplify
>> > the patch kit so that we don't have to support wrapper nodes during
>> > template expansion.
>>
>> Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
>> VIEW_CONVERT_EXPR don't otherwise appear in template trees.
>>
>> Jason
>
> I don't know if it's "easy"; it's at least non-trivial.
>
> I attempted to support them in the obvious way by adding the two codes
> to the switch statement tsubst_copy, reusing the case used by NOP_EXPR
> and others, but ran into a issue when dealing with template parameter
> packs.

> Attached is the reproducer I've been testing with (minimized using
> "delta" from a stdlib reproducer); my code was failing with:
>
> ../../src/cp-stdlib.ii: In instantiation of ‘struct allocator_traits<allocator<char> >’:
> ../../src/cp-stdlib.ii:31:8:   required from ‘struct __alloc_traits<allocator<char>, char>’
> ../../src/cp-stdlib.ii:43:75:   required from ‘class basic_string<char, allocator<char> >’
> ../../src/cp-stdlib.ii:47:58:   required from here
> ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of ‘type_pack_expansion’ in template
>      -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
>                                                        ^~~~~~
>
> The issue is that normally "__args" would be a PARM_DECL of type
> TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on adding a
> wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
> TYPE_PACK_EXPANSION wrapping the PARM_DECL.
>
> When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached first,
> and it attempts to substitute the type TYPE_PACK_EXPANSION, which leads
> to the "sorry".
>
> If I understand things right, during substitution, only tsubst_decl on
> PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
>
> The simplest approach seems to be to not create wrapper nodes for decls
> of type TYPE_PACK_EXPANSION, and that seems to fix the issue.

That does seem simplest.

> Alternatively I can handle TYPE_PACK_EXPANSION for VIEW_CONVERT_EXPR in
> tsubst by remapping the type to that of what they wrap after
> substitution; doing so also fixes the issue.

This will be more correct.  For the wrappers you don't need all the
handling that we currently have for NOP_EXPR and such; since we know
they don't change the type, we can substitute what they wrap, and then
rewrap the result.

Jason

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-15 15:02               ` Jason Merrill
@ 2017-12-15 16:35                 ` David Malcolm
  2017-12-15 18:59                   ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-15 16:35 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
> On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > The initial version of the patch kit added location wrapper
> > > > nodes
> > > > around constants and uses-of-declarations, along with some
> > > > other
> > > > places in the parser (typeid, alignof, sizeof, offsetof).
> > > > 
> > > > This version takes a much more minimal approach: it only adds
> > > > location wrapper nodes around the arguments at callsites, thus
> > > > not adding wrapper nodes around uses of constants and decls in
> > > > other
> > > > locations.
> > > > 
> > > > It keeps them for the other places in the parser (typeid,
> > > > alignof,
> > > > sizeof, offsetof).
> > > > 
> > > > In addition, for now, each site that adds wrapper nodes is
> > > > guarded
> > > > with !processing_template_decl, suppressing the creation of
> > > > wrapper
> > > > nodes when processing template declarations.  This is to
> > > > simplify
> > > > the patch kit so that we don't have to support wrapper nodes
> > > > during
> > > > template expansion.
> > > 
> > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
> > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> > > 
> > > Jason
> > 
> > I don't know if it's "easy"; it's at least non-trivial.
> > 
> > I attempted to support them in the obvious way by adding the two
> > codes
> > to the switch statement tsubst_copy, reusing the case used by
> > NOP_EXPR
> > and others, but ran into a issue when dealing with template
> > parameter
> > packs.
> > Attached is the reproducer I've been testing with (minimized using
> > "delta" from a stdlib reproducer); my code was failing with:
> > 
> > ../../src/cp-stdlib.ii: In instantiation of ‘struct
> > allocator_traits<allocator<char> >’:
> > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
> > __alloc_traits<allocator<char>, char>’
> > ../../src/cp-stdlib.ii:43:75:   required from ‘class
> > basic_string<char, allocator<char> >’
> > ../../src/cp-stdlib.ii:47:58:   required from here
> > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
> > ‘type_pack_expansion’ in template
> >      -> decltype(_S_construct(__a, __p,
> > forward<_Args>(__args)...))  {   }
> >                                                        ^~~~~~
> > 
> > The issue is that normally "__args" would be a PARM_DECL of type
> > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
> > adding a
> > wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
> > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
> > 
> > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached
> > first,
> > and it attempts to substitute the type TYPE_PACK_EXPANSION, which
> > leads
> > to the "sorry".
> > 
> > If I understand things right, during substitution, only tsubst_decl
> > on
> > PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
> > 
> > The simplest approach seems to be to not create wrapper nodes for
> > decls
> > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
> 
> That does seem simplest.
> 
> > Alternatively I can handle TYPE_PACK_EXPANSION for
> > VIEW_CONVERT_EXPR in
> > tsubst by remapping the type to that of what they wrap after
> > substitution; doing so also fixes the issue.
> 
> This will be more correct.  For the wrappers you don't need all the
> handling that we currently have for NOP_EXPR and such; since we know
> they don't change the type, we can substitute what they wrap, and
> then
> rewrap the result.

(nods; I have this working)

I've been debugging the other issues that I ran into when removing the
"!processing_template_decl" filter on making wrapper nodes (ICEs and
other errors on valid code).  They turn out to relate to wrappers
around decls of type TEMPLATE_TYPE_PARM; having these wrappers leads to
such VIEW_CONVERT_EXPRs turning up in unexpected places.

I could try to track all those places down, but it seems much simpler
to just add an exclusion to adding wrapper nodes around decls of type
TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++ stdlib
work again.  Does that sound reasonable?

Thanks
Dave

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-15 16:35                 ` David Malcolm
@ 2017-12-15 18:59                   ` Jason Merrill
  2017-12-15 22:49                     ` David Malcolm
  2017-12-29 17:03                     ` [v2 of PATCH " David Malcolm
  0 siblings, 2 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-15 18:59 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, Dec 15, 2017 at 11:35 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
>> On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > The initial version of the patch kit added location wrapper
>> > > > nodes
>> > > > around constants and uses-of-declarations, along with some
>> > > > other
>> > > > places in the parser (typeid, alignof, sizeof, offsetof).
>> > > >
>> > > > This version takes a much more minimal approach: it only adds
>> > > > location wrapper nodes around the arguments at callsites, thus
>> > > > not adding wrapper nodes around uses of constants and decls in
>> > > > other
>> > > > locations.
>> > > >
>> > > > It keeps them for the other places in the parser (typeid,
>> > > > alignof,
>> > > > sizeof, offsetof).
>> > > >
>> > > > In addition, for now, each site that adds wrapper nodes is
>> > > > guarded
>> > > > with !processing_template_decl, suppressing the creation of
>> > > > wrapper
>> > > > nodes when processing template declarations.  This is to
>> > > > simplify
>> > > > the patch kit so that we don't have to support wrapper nodes
>> > > > during
>> > > > template expansion.
>> > >
>> > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
>> > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
>> > >
>> > > Jason
>> >
>> > I don't know if it's "easy"; it's at least non-trivial.
>> >
>> > I attempted to support them in the obvious way by adding the two
>> > codes
>> > to the switch statement tsubst_copy, reusing the case used by
>> > NOP_EXPR
>> > and others, but ran into a issue when dealing with template
>> > parameter
>> > packs.
>> > Attached is the reproducer I've been testing with (minimized using
>> > "delta" from a stdlib reproducer); my code was failing with:
>> >
>> > ../../src/cp-stdlib.ii: In instantiation of ‘struct
>> > allocator_traits<allocator<char> >’:
>> > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
>> > __alloc_traits<allocator<char>, char>’
>> > ../../src/cp-stdlib.ii:43:75:   required from ‘class
>> > basic_string<char, allocator<char> >’
>> > ../../src/cp-stdlib.ii:47:58:   required from here
>> > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
>> > ‘type_pack_expansion’ in template
>> >      -> decltype(_S_construct(__a, __p,
>> > forward<_Args>(__args)...))  {   }
>> >                                                        ^~~~~~
>> >
>> > The issue is that normally "__args" would be a PARM_DECL of type
>> > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
>> > adding a
>> > wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
>> > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
>> >
>> > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached
>> > first,
>> > and it attempts to substitute the type TYPE_PACK_EXPANSION, which
>> > leads
>> > to the "sorry".
>> >
>> > If I understand things right, during substitution, only tsubst_decl
>> > on
>> > PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
>> >
>> > The simplest approach seems to be to not create wrapper nodes for
>> > decls
>> > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
>>
>> That does seem simplest.
>>
>> > Alternatively I can handle TYPE_PACK_EXPANSION for
>> > VIEW_CONVERT_EXPR in
>> > tsubst by remapping the type to that of what they wrap after
>> > substitution; doing so also fixes the issue.
>>
>> This will be more correct.  For the wrappers you don't need all the
>> handling that we currently have for NOP_EXPR and such; since we know
>> they don't change the type, we can substitute what they wrap, and
>> then
>> rewrap the result.
>
> (nods; I have this working)
>
> I've been debugging the other issues that I ran into when removing the
> "!processing_template_decl" filter on making wrapper nodes (ICEs and
> other errors on valid code).  They turn out to relate to wrappers
> around decls of type TEMPLATE_TYPE_PARM; having these wrappers leads to
> such VIEW_CONVERT_EXPRs turning up in unexpected places.

Hmm, that's odd.  What kind of decls?  A variable which happens to
have a template parameter for a type shouldn't be a problem.

> I could try to track all those places down, but it seems much simpler
> to just add an exclusion to adding wrapper nodes around decls of type
> TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++ stdlib
> work again.  Does that sound reasonable?

Jason

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

* Re: [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-15 18:59                   ` Jason Merrill
@ 2017-12-15 22:49                     ` David Malcolm
  2017-12-29 17:03                     ` [v2 of PATCH " David Malcolm
  1 sibling, 0 replies; 111+ messages in thread
From: David Malcolm @ 2017-12-15 22:49 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2017-12-15 at 13:58 -0500, Jason Merrill wrote:
> On Fri, Dec 15, 2017 at 11:35 AM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
> > > On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> > > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > > The initial version of the patch kit added location wrapper
> > > > > > nodes
> > > > > > around constants and uses-of-declarations, along with some
> > > > > > other
> > > > > > places in the parser (typeid, alignof, sizeof, offsetof).
> > > > > > 
> > > > > > This version takes a much more minimal approach: it only
> > > > > > adds
> > > > > > location wrapper nodes around the arguments at callsites,
> > > > > > thus
> > > > > > not adding wrapper nodes around uses of constants and decls
> > > > > > in
> > > > > > other
> > > > > > locations.
> > > > > > 
> > > > > > It keeps them for the other places in the parser (typeid,
> > > > > > alignof,
> > > > > > sizeof, offsetof).
> > > > > > 
> > > > > > In addition, for now, each site that adds wrapper nodes is
> > > > > > guarded
> > > > > > with !processing_template_decl, suppressing the creation of
> > > > > > wrapper
> > > > > > nodes when processing template declarations.  This is to
> > > > > > simplify
> > > > > > the patch kit so that we don't have to support wrapper
> > > > > > nodes
> > > > > > during
> > > > > > template expansion.
> > > > > 
> > > > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR
> > > > > and
> > > > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> > > > > 
> > > > > Jason
> > > > 
> > > > I don't know if it's "easy"; it's at least non-trivial.
> > > > 
> > > > I attempted to support them in the obvious way by adding the
> > > > two
> > > > codes
> > > > to the switch statement tsubst_copy, reusing the case used by
> > > > NOP_EXPR
> > > > and others, but ran into a issue when dealing with template
> > > > parameter
> > > > packs.
> > > > Attached is the reproducer I've been testing with (minimized
> > > > using
> > > > "delta" from a stdlib reproducer); my code was failing with:
> > > > 
> > > > ../../src/cp-stdlib.ii: In instantiation of ‘struct
> > > > allocator_traits<allocator<char> >’:
> > > > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
> > > > __alloc_traits<allocator<char>, char>’
> > > > ../../src/cp-stdlib.ii:43:75:   required from ‘class
> > > > basic_string<char, allocator<char> >’
> > > > ../../src/cp-stdlib.ii:47:58:   required from here
> > > > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
> > > > ‘type_pack_expansion’ in template
> > > >      -> decltype(_S_construct(__a, __p,
> > > > forward<_Args>(__args)...))  {   }
> > > >                                                        ^~~~~~
> > > > 
> > > > The issue is that normally "__args" would be a PARM_DECL of
> > > > type
> > > > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
> > > > adding a
> > > > wrapper node we now have a VIEW_CONVERT_EXPR of the same type
> > > > i.e.
> > > > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
> > > > 
> > > > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is
> > > > reached
> > > > first,
> > > > and it attempts to substitute the type TYPE_PACK_EXPANSION,
> > > > which
> > > > leads
> > > > to the "sorry".
> > > > 
> > > > If I understand things right, during substitution, only
> > > > tsubst_decl
> > > > on
> > > > PARM_DECL can handle nodes with type with code
> > > > TYPE_PACK_EXPANSION.
> > > > 
> > > > The simplest approach seems to be to not create wrapper nodes
> > > > for
> > > > decls
> > > > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
> > > 
> > > That does seem simplest.
> > > 
> > > > Alternatively I can handle TYPE_PACK_EXPANSION for
> > > > VIEW_CONVERT_EXPR in
> > > > tsubst by remapping the type to that of what they wrap after
> > > > substitution; doing so also fixes the issue.
> > > 
> > > This will be more correct.  For the wrappers you don't need all
> > > the
> > > handling that we currently have for NOP_EXPR and such; since we
> > > know
> > > they don't change the type, we can substitute what they wrap, and
> > > then
> > > rewrap the result.
> > 
> > (nods; I have this working)
> > 
> > I've been debugging the other issues that I ran into when removing
> > the
> > "!processing_template_decl" filter on making wrapper nodes (ICEs
> > and
> > other errors on valid code).  They turn out to relate to wrappers
> > around decls of type TEMPLATE_TYPE_PARM; having these wrappers
> > leads to
> > such VIEW_CONVERT_EXPRs turning up in unexpected places.
> 
> Hmm, that's odd.  What kind of decls?  A variable which happens to
> have a template parameter for a type shouldn't be a problem.

That one turned out to be a bug in my changes to tsubst_copy, which
I've fixed.

But I'm still running into various other issues when attempting to
enable the wrappers for when processing_template_decl is true.  Having
spent a fair chunk of the week on it, I'm not finding it "easy to
support them" (though that may be one, of course...).

I'm working on addressing the other issues you raised; I hope to
post some updated patches when I get things bootstrapping again.

Thanks
Dave


> > I could try to track all those places down, but it seems much
> > simpler
> > to just add an exclusion to adding wrapper nodes around decls of
> > type
> > TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++
> > stdlib
> > work again.  Does that sound reasonable?
> 
> Jason

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

* [PATCH] C++: handle locations wrappers when calling warn_for_memset
  2017-12-11 23:36           ` Jason Merrill
@ 2017-12-16 13:09             ` David Malcolm
  2017-12-16 20:01               ` Martin Sebor
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-16 13:09 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Mon, 2017-12-11 at 18:36 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > We need to strip away location wrappers in tree.c predicates like
> > integer_zerop, otherwise they fail when they're called on
> > wrapped INTEGER_CST; an example can be seen for
> >    c-c++-common/Wmemset-transposed-args1.c
> > in g++.sum, where the warn_for_memset fails to detect integer zero
> > if the location wrappers aren't stripped.
> 
> These shouldn't be needed; callers should have folded away location 
> wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be almost 
> never needed.
> 
> warn_for_memset may be missing some calls to fold_for_warn.

It is, thanks.

Here's a revised fix for e.g. Wmemset-transposed-args1.c, replacing
"[PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc"
and
"[PATCH 10/14] warn_for_memset: handle location wrappers"

This version of the patch simply calls fold_for_warn on each of the
arguments before calling warn_for_memset.  This ensures that
warn_for_memset detects integer zero.  It also adds a
literal_integer_zerop to deal with location wrapper nodes when
building "literal_mask" for the call, since this must be called
*before* the fold_for_warn calls.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

Is this OK for trunk, once the rest of the kit is approved?

gcc/cp/ChangeLog:
	* parser.c (literal_integer_zerop): New function.
	(cp_parser_postfix_expression): When calling warn_for_memset,
	replace integer_zerop calls with literal_integer_zerop, and
	call fold_for_warn on the arguments.
---
 gcc/cp/parser.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d15769a..7bca460 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
   return compound_literal_p;
 }
 
+/* Return 1 if EXPR is the integer constant zero or a complex constant
+   of zero, without any folding, but ignoring location wrappers.  */
+
+static int
+literal_integer_zerop (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+  return integer_zerop (expr);
+}
+
 /* Parse a postfix-expression.
 
    postfix-expression:
@@ -7168,8 +7178,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		tree arg0 = (*args)[0];
 		tree arg1 = (*args)[1];
 		tree arg2 = (*args)[2];
-		int literal_mask = ((!!integer_zerop (arg1) << 1)
-				    | (!!integer_zerop (arg2) << 2));
+		/* Handle any location wrapper nodes.  */
+		arg0 = fold_for_warn (arg0);
+		int literal_mask = ((!!literal_integer_zerop (arg1) << 1)
+				    | (!!literal_integer_zerop (arg2) << 2));
+		arg1 = fold_for_warn (arg1);
+		arg2 = fold_for_warn (arg2);
 		if (TREE_CODE (arg2) == CONST_DECL)
 		  arg2 = DECL_INITIAL (arg2);
 		warn_for_memset (input_location, arg0, arg2, literal_mask);
-- 
1.8.5.3

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

* Re: [PATCH] C++: handle locations wrappers when calling warn_for_memset
  2017-12-16 13:09             ` [PATCH] C++: handle locations wrappers when calling warn_for_memset David Malcolm
@ 2017-12-16 20:01               ` Martin Sebor
  2017-12-19 20:02                 ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: Martin Sebor @ 2017-12-16 20:01 UTC (permalink / raw)
  To: David Malcolm, Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/16/2017 06:12 AM, David Malcolm wrote:
> On Mon, 2017-12-11 at 18:36 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>>> We need to strip away location wrappers in tree.c predicates like
>>> integer_zerop, otherwise they fail when they're called on
>>> wrapped INTEGER_CST; an example can be seen for
>>>    c-c++-common/Wmemset-transposed-args1.c
>>> in g++.sum, where the warn_for_memset fails to detect integer zero
>>> if the location wrappers aren't stripped.
>>
>> These shouldn't be needed; callers should have folded away location
>> wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be almost
>> never needed.
>>
>> warn_for_memset may be missing some calls to fold_for_warn.
>
> It is, thanks.
>
> Here's a revised fix for e.g. Wmemset-transposed-args1.c, replacing
> "[PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc"
> and
> "[PATCH 10/14] warn_for_memset: handle location wrappers"
>
> This version of the patch simply calls fold_for_warn on each of the
> arguments before calling warn_for_memset.  This ensures that
> warn_for_memset detects integer zero.  It also adds a
> literal_integer_zerop to deal with location wrapper nodes when
> building "literal_mask" for the call, since this must be called
> *before* the fold_for_warn calls.
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
>
> Is this OK for trunk, once the rest of the kit is approved?
>
> gcc/cp/ChangeLog:
> 	* parser.c (literal_integer_zerop): New function.
> 	(cp_parser_postfix_expression): When calling warn_for_memset,
> 	replace integer_zerop calls with literal_integer_zerop, and
> 	call fold_for_warn on the arguments.
> ---
>  gcc/cp/parser.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index d15769a..7bca460 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
>    return compound_literal_p;
>  }
>
> +/* Return 1 if EXPR is the integer constant zero or a complex constant
> +   of zero, without any folding, but ignoring location wrappers.  */
> +
> +static int
> +literal_integer_zerop (const_tree expr)
> +{
> +  STRIP_ANY_LOCATION_WRAPPER (expr);
> +  return integer_zerop (expr);
> +}
> +
>  /* Parse a postfix-expression.
>
>     postfix-expression:
> @@ -7168,8 +7178,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
>  		tree arg0 = (*args)[0];
>  		tree arg1 = (*args)[1];
>  		tree arg2 = (*args)[2];
> -		int literal_mask = ((!!integer_zerop (arg1) << 1)
> -				    | (!!integer_zerop (arg2) << 2));
> +		/* Handle any location wrapper nodes.  */
> +		arg0 = fold_for_warn (arg0);
> +		int literal_mask = ((!!literal_integer_zerop (arg1) << 1)
> +				    | (!!literal_integer_zerop (arg2) << 2));

The double negation jumped out at me.  The integer_zerop() function
looks like a predicate that hasn't yet been converted to return bool.
It seems that new predicates that are implemented on top of it could
return bool and their callers avoid this conversion.  (At some point
in the future it would also be nice to convert the existing
predicates to return bool).

Martin

> +		arg1 = fold_for_warn (arg1);
> +		arg2 = fold_for_warn (arg2);
>  		if (TREE_CODE (arg2) == CONST_DECL)
>  		  arg2 = DECL_INITIAL (arg2);
>  		warn_for_memset (input_location, arg0, arg2, literal_mask);
>

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

* [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (16 preceding siblings ...)
  2017-11-30 20:54         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
@ 2017-12-17  1:10         ` David Malcolm
  2017-12-19 20:35           ` Jason Merrill
  2018-01-10 19:51         ` [committed] Preserving locations for variable-uses and constants (PR c++/43486) David Malcolm
  18 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-17  1:10 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

I rebased the v2 patchkit; here's an extra patch to fix an issue
with it uncovered by a recently-added testcase (in r254990).

With the patch kit, but without this patch, g++'s
  c-c++-common/pr83059.c
fails to emit the "invalid memory model argument 6" warning.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

Is this OK for trunk, assuming the rest of the kit is approved?

gcc/c-family/ChangeLog:
	* c-common.c (get_atomic_generic_size): Call fold_for_warn on the
	params before checking for INTEGER_CST.
---
 gcc/c-family/c-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3438b87..ab03b7d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc, tree function,
   /* Check memory model parameters for validity.  */
   for (x = n_param - n_model ; x < n_param; x++)
     {
-      tree p = (*params)[x];
+      tree p = fold_for_warn ((*params)[x]);
       if (TREE_CODE (p) == INTEGER_CST)
         {
 	  /* memmodel_base masks the low 16 bits, thus ignore any bits above
-- 
1.8.5.3

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

* [v2 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-11 23:45           ` Jason Merrill
@ 2017-12-17 16:26             ` David Malcolm
  2017-12-19 19:55               ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-17 16:26 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > gcc/c-family/ChangeLog:
> >        * c-format.c (check_format_arg): Strip any location wrapper
> > around
> >        format_tree.
> > ---
> >    gcc/c-family/c-format.c | 9 ++++++++-
> >    1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> > index 164d035..6b436ec 100644
> > --- a/gcc/c-family/c-format.c
> > +++ b/gcc/c-family/c-format.c
> > @@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree
> > format_tree,
> >
> >      location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree,
> > input_location);
> >
> > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > +
> >      if (VAR_P (format_tree))
> >        {
> >          /* Pull out a constant value if the front end didn't.  */
>
> It seems like we want fold_for_warn here instead of the special
> variable
> handling.  That probably makes sense for the other places you change
> in
> this patch, too.
>
> Jason

Here's an updated version of the patch which uses fold_for_warn,
rather than STRIP_ANY_LOCATION_WRAPPER.

In one place it was necessary to add a STRIP_NOPS, since the
fold_for_warn can add a cast around a:
  ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
    STRING_CST)
turning it into a:
  NOP_EXPR<POINTER_TYPE(char))> (
    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
      STRING_CST))
which without a STRIP_NOPS leads to a bail-out here:
  1596	  if (TREE_CODE (format_tree) != ADDR_EXPR)
  1597	    {
  1598	      res->number_non_literal++;
  1599	      return;
  1600	    }
and thus -Wformat-security not recognizing string literals.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

Is this OK for trunk, assuming the rest of the kit is approved?

gcc/c-family/ChangeLog:
	* c-format.c (check_format_arg): Strip any location wrapper around
	format_tree.
---
 gcc/c-family/c-format.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 164d035..47aca55 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
+  format_tree = fold_for_warn (format_tree);
+
   if (VAR_P (format_tree))
     {
       /* Pull out a constant value if the front end didn't.  */
@@ -1591,13 +1593,14 @@ check_format_arg (void *ctx, tree format_tree,
 	}
       offset = int_cst_value (arg1);
     }
+  STRIP_NOPS (format_tree);
   if (TREE_CODE (format_tree) != ADDR_EXPR)
     {
       res->number_non_literal++;
       return;
     }
   res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
-  format_tree = TREE_OPERAND (format_tree, 0);
+  format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
   if (format_types[info->format_type].flags 
       & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
     {
@@ -1634,7 +1637,9 @@ check_format_arg (void *ctx, tree format_tree,
   if (TREE_CODE (format_tree) == ARRAY_REF
       && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
       && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
-    format_tree = TREE_OPERAND (format_tree, 0);
+    {
+      format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
+    }
   if (offset < 0)
     {
       res->number_non_literal++;
-- 
1.8.5.3

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

* [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-11 23:37           ` Jason Merrill
@ 2017-12-18  2:04             ` David Malcolm
  2017-12-18  8:00               ` Jakub Jelinek
  2017-12-19 20:13               ` Jason Merrill
  0 siblings, 2 replies; 111+ messages in thread
From: David Malcolm @ 2017-12-18  2:04 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Mon, 2017-12-11 at 18:37 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > gcc/c-family/ChangeLog:
> > 	* c-warn.c (sizeof_pointer_memaccess_warning): Strip any
> > location
> > 	wrappers from src and dest.
> 
> Here the existing calls to tree_strip_nop_conversions ought to
> handle 
> the wrappers.

They don't; when EXP is a VIEW_CONVERT_EXPR wrapper around a VAR_DECL...

11887	static inline bool
11888	tree_nop_conversion (const_tree exp)
11889	{
11890	  tree outer_type, inner_type;
11891	
11892	  if (!CONVERT_EXPR_P (exp)
11893	      && TREE_CODE (exp) != NON_LVALUE_EXPR)
11894	    return false;

...tree_nop_conversion bails out at this "return false;", and hence
tree_strip_nop_conversions simply returns the wrapper that was passed
in.

I tried adding fold_for_warn on src and dest, but it doesn't do quite
the right thing, as
  FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++98  (test for warnings, line 482)
  FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++98  (test for warnings, line 483)
  FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++98  (test for warnings, line 484)
...due to "src" changing from being a VAR_DECL to being its STRING_CST
value after the fold_for_warn,

So one approach for Wsizeof-pointer-memaccess*.c is the patch I posted
("[PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c"), which ensures that
any wrappers have been stripped before the call to operand_equal_p in
sizeof_pointer_memaccess_warning.

Alternatively, here's a patch which strips wrappers in operand_equal_p.
FWIW I prefer doing it in sizeof_pointer_memaccess_warning, rather than
touching operand_equal_p.

What do you think?

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

gcc/ChangeLog:
	* fold-const.c (operand_equal_p): Strip any location wrappers,
	before computing hashes.
---
 gcc/fold-const.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0f11076..2b938900 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2804,6 +2804,9 @@ combine_comparisons (location_t loc,
 int
 operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 {
+  STRIP_ANY_LOCATION_WRAPPER (arg0);
+  STRIP_ANY_LOCATION_WRAPPER (arg1);
+
   /* When checking, verify at the outermost operand_equal_p call that
      if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
      hash value.  */
-- 
1.8.5.3

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

* Re: [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-18  2:04             ` [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p David Malcolm
@ 2017-12-18  8:00               ` Jakub Jelinek
  2017-12-19 20:13               ` Jason Merrill
  1 sibling, 0 replies; 111+ messages in thread
From: Jakub Jelinek @ 2017-12-18  8:00 UTC (permalink / raw)
  To: David Malcolm
  Cc: Jason Merrill, Nathan Sidwell, Richard Biener, gcc-patches List

On Sun, Dec 17, 2017 at 09:07:54PM -0500, David Malcolm wrote:
> What do you think?
> 
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
> 
> gcc/ChangeLog:
> 	* fold-const.c (operand_equal_p): Strip any location wrappers,
> 	before computing hashes.
> ---
>  gcc/fold-const.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index 0f11076..2b938900 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -2804,6 +2804,9 @@ combine_comparisons (location_t loc,
>  int
>  operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
>  {
> +  STRIP_ANY_LOCATION_WRAPPER (arg0);
> +  STRIP_ANY_LOCATION_WRAPPER (arg1);
> +

Certainly not at this spot.
The checking that hashing ignores the location wrappers needs to be done
first.  And inchash:add_expr needs to ignore those.

	Jakub

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

* Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-17 16:26             ` [v2 of PATCH " David Malcolm
@ 2017-12-19 19:55               ` Jason Merrill
  2017-12-20 17:33                 ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-19 19:55 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/17/2017 11:29 AM, David Malcolm wrote:
> On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>>> +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
>>> +
>>>       if (VAR_P (format_tree))
>>>         {
>>>           /* Pull out a constant value if the front end didn't.  */
>>
>> It seems like we want fold_for_warn here instead of the special variable
>> handling.  That probably makes sense for the other places you change in
>> this patch, too.
> 
> Here's an updated version of the patch which uses fold_for_warn,
> rather than STRIP_ANY_LOCATION_WRAPPER.
> 
> In one place it was necessary to add a STRIP_NOPS, since the
> fold_for_warn can add a cast around a:
>    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
>      STRING_CST)
> turning it into a:
>    NOP_EXPR<POINTER_TYPE(char))> (
>      ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
>        STRING_CST))

Hmm, that seems like a bug.  fold_for_warn shouldn't change the type of 
the result.

> +  format_tree = fold_for_warn (format_tree);
> +
>     if (VAR_P (format_tree))
>       {
>         /* Pull out a constant value if the front end didn't.  */

I was suggesting dropping the if (VAR_P... block, since pulling out the 
constant value should now be covered by fold_for_warn.

> -    format_tree = TREE_OPERAND (format_tree, 0);
> +    {
> +      format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
> +    }

Why the added braces?

Jason

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

* Re: [PATCH] C++: handle locations wrappers when calling warn_for_memset
  2017-12-16 20:01               ` Martin Sebor
@ 2017-12-19 20:02                 ` Jason Merrill
  2017-12-20 19:23                   ` [v3 of 05/14] " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-19 20:02 UTC (permalink / raw)
  To: Martin Sebor, David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/16/2017 03:01 PM, Martin Sebor wrote:
> On 12/16/2017 06:12 AM, David Malcolm wrote:
>> On Mon, 2017-12-11 at 18:36 -0500, Jason Merrill wrote:
>>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>>>> We need to strip away location wrappers in tree.c predicates like
>>>> integer_zerop, otherwise they fail when they're called on
>>>> wrapped INTEGER_CST; an example can be seen for
>>>>    c-c++-common/Wmemset-transposed-args1.c
>>>> in g++.sum, where the warn_for_memset fails to detect integer zero
>>>> if the location wrappers aren't stripped.
>>>
>>> These shouldn't be needed; callers should have folded away location
>>> wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be almost
>>> never needed.
>>>
>>> warn_for_memset may be missing some calls to fold_for_warn.
>>
>> It is, thanks.
>>
>> Here's a revised fix for e.g. Wmemset-transposed-args1.c, replacing
>> "[PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc"
>> and
>> "[PATCH 10/14] warn_for_memset: handle location wrappers"
>>
>> This version of the patch simply calls fold_for_warn on each of the
>> arguments before calling warn_for_memset.  This ensures that
>> warn_for_memset detects integer zero.  It also adds a
>> literal_integer_zerop to deal with location wrapper nodes when
>> building "literal_mask" for the call, since this must be called
>> *before* the fold_for_warn calls.
>>
>> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
>> part of the kit.
>>
>> Is this OK for trunk, once the rest of the kit is approved?
>>
>> gcc/cp/ChangeLog:
>>     * parser.c (literal_integer_zerop): New function.
>>     (cp_parser_postfix_expression): When calling warn_for_memset,
>>     replace integer_zerop calls with literal_integer_zerop, and
>>     call fold_for_warn on the arguments.
>> ---
>>  gcc/cp/parser.c | 18 ++++++++++++++++--
>>  1 file changed, 16 insertions(+), 2 deletions(-)
>>
>> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>> index d15769a..7bca460 100644
>> --- a/gcc/cp/parser.c
>> +++ b/gcc/cp/parser.c
>> @@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
>>    return compound_literal_p;
>>  }
>>
>> +/* Return 1 if EXPR is the integer constant zero or a complex constant
>> +   of zero, without any folding, but ignoring location wrappers.  */
>> +
>> +static int
>> +literal_integer_zerop (const_tree expr)
>> +{
>> +  STRIP_ANY_LOCATION_WRAPPER (expr);
>> +  return integer_zerop (expr);
>> +}
>> +
>>  /* Parse a postfix-expression.
>>
>>     postfix-expression:
>> @@ -7168,8 +7178,12 @@ cp_parser_postfix_expression (cp_parser 
>> *parser, bool address_p, bool cast_p,
>>          tree arg0 = (*args)[0];
>>          tree arg1 = (*args)[1];
>>          tree arg2 = (*args)[2];
>> -        int literal_mask = ((!!integer_zerop (arg1) << 1)
>> -                    | (!!integer_zerop (arg2) << 2));
>> +        /* Handle any location wrapper nodes.  */
>> +        arg0 = fold_for_warn (arg0);
>> +        int literal_mask = ((!!literal_integer_zerop (arg1) << 1)
>> +                    | (!!literal_integer_zerop (arg2) << 2));
> 
> The double negation jumped out at me.  The integer_zerop() function
> looks like a predicate that hasn't yet been converted to return bool.
> It seems that new predicates that are implemented on top of it could
> return bool and their callers avoid this conversion.  (At some point
> in the future it would also be nice to convert the existing
> predicates to return bool).

Agreed.  And since integer_zerop in fact returns boolean values, there 
seems to be no need for the double negative in the first place.

So, please make the new function return bool and remove the !!s.

And I think the fold_for_warn call should be in warn_for_memset, and it 
should be called for arg2 as well instead of specifically handling 
CONST_DECL Here.

Jason


Jason

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

* Re: [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-18  2:04             ` [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p David Malcolm
  2017-12-18  8:00               ` Jakub Jelinek
@ 2017-12-19 20:13               ` Jason Merrill
  2017-12-19 20:49                 ` Jakub Jelinek
  1 sibling, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-19 20:13 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/17/2017 09:07 PM, David Malcolm wrote:
> On Mon, 2017-12-11 at 18:37 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>>> gcc/c-family/ChangeLog:
>>> 	* c-warn.c (sizeof_pointer_memaccess_warning): Strip any
>>> location
>>> 	wrappers from src and dest.
>>
>> Here the existing calls to tree_strip_nop_conversions ought to
>> handle
>> the wrappers.
> 
> They don't; when EXP is a VIEW_CONVERT_EXPR wrapper around a VAR_DECL...
> 
> 11887	static inline bool
> 11888	tree_nop_conversion (const_tree exp)
> 11889	{
> 11890	  tree outer_type, inner_type;
> 11891	
> 11892	  if (!CONVERT_EXPR_P (exp)
> 11893	      && TREE_CODE (exp) != NON_LVALUE_EXPR)
> 11894	    return false;
> 
> ...tree_nop_conversion bails out at this "return false;", and hence
> tree_strip_nop_conversions simply returns the wrapper that was passed
> in.

Right.  So let's change tree_nop_conversion to return true.

Jason

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

* Re: [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-12-17  1:10         ` [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size David Malcolm
@ 2017-12-19 20:35           ` Jason Merrill
  2017-12-20  0:50             ` [v2 of PATCH " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-19 20:35 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Sat, Dec 16, 2017 at 8:12 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> I rebased the v2 patchkit; here's an extra patch to fix an issue
> with it uncovered by a recently-added testcase (in r254990).
>
> With the patch kit, but without this patch, g++'s
>   c-c++-common/pr83059.c
> fails to emit the "invalid memory model argument 6" warning.
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
>
> Is this OK for trunk, assuming the rest of the kit is approved?
>
> gcc/c-family/ChangeLog:
>         * c-common.c (get_atomic_generic_size): Call fold_for_warn on the
>         params before checking for INTEGER_CST.
> ---
>  gcc/c-family/c-common.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 3438b87..ab03b7d 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc, tree function,
>    /* Check memory model parameters for validity.  */
>    for (x = n_param - n_model ; x < n_param; x++)
>      {
> -      tree p = (*params)[x];
> +      tree p = fold_for_warn ((*params)[x]);
>        if (TREE_CODE (p) == INTEGER_CST)
>          {
>           /* memmodel_base masks the low 16 bits, thus ignore any bits above

Let's check the error case before we call fold_for_warn.

Jason

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

* Re: [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-19 20:13               ` Jason Merrill
@ 2017-12-19 20:49                 ` Jakub Jelinek
  2017-12-19 21:59                   ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: Jakub Jelinek @ 2017-12-19 20:49 UTC (permalink / raw)
  To: Jason Merrill
  Cc: David Malcolm, Nathan Sidwell, Richard Biener, gcc-patches List

On Tue, Dec 19, 2017 at 03:13:13PM -0500, Jason Merrill wrote:
> On 12/17/2017 09:07 PM, David Malcolm wrote:
> > On Mon, 2017-12-11 at 18:37 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > gcc/c-family/ChangeLog:
> > > > 	* c-warn.c (sizeof_pointer_memaccess_warning): Strip any
> > > > location
> > > > 	wrappers from src and dest.
> > > 
> > > Here the existing calls to tree_strip_nop_conversions ought to
> > > handle
> > > the wrappers.
> > 
> > They don't; when EXP is a VIEW_CONVERT_EXPR wrapper around a VAR_DECL...
> > 
> > 11887	static inline bool
> > 11888	tree_nop_conversion (const_tree exp)
> > 11889	{
> > 11890	  tree outer_type, inner_type;
> > 11891	
> > 11892	  if (!CONVERT_EXPR_P (exp)
> > 11893	      && TREE_CODE (exp) != NON_LVALUE_EXPR)
> > 11894	    return false;
> > 
> > ...tree_nop_conversion bails out at this "return false;", and hence
> > tree_strip_nop_conversions simply returns the wrapper that was passed
> > in.
> 
> Right.  So let's change tree_nop_conversion to return true.

I'd fear that would break too much stuff, VIEW_CONVERT_EXPR is not
a normal conversion, but reinterpretation of the bits.

Or do you mean it should strip just the special VIEW_CONVERT_EXPR
that has type identical to the operand's type?

	Jakub

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

* Re: [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-19 20:49                 ` Jakub Jelinek
@ 2017-12-19 21:59                   ` Jason Merrill
  2017-12-19 22:03                     ` Jakub Jelinek
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-19 21:59 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: David Malcolm, Nathan Sidwell, Richard Biener, gcc-patches List

On Tue, Dec 19, 2017 at 3:49 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Dec 19, 2017 at 03:13:13PM -0500, Jason Merrill wrote:
>> On 12/17/2017 09:07 PM, David Malcolm wrote:
>> > On Mon, 2017-12-11 at 18:37 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > gcc/c-family/ChangeLog:
>> > > >         * c-warn.c (sizeof_pointer_memaccess_warning): Strip any
>> > > > location
>> > > >         wrappers from src and dest.
>> > >
>> > > Here the existing calls to tree_strip_nop_conversions ought to
>> > > handle
>> > > the wrappers.
>> >
>> > They don't; when EXP is a VIEW_CONVERT_EXPR wrapper around a VAR_DECL...
>> >
>> > 11887       static inline bool
>> > 11888       tree_nop_conversion (const_tree exp)
>> > 11889       {
>> > 11890         tree outer_type, inner_type;
>> > 11891
>> > 11892         if (!CONVERT_EXPR_P (exp)
>> > 11893             && TREE_CODE (exp) != NON_LVALUE_EXPR)
>> > 11894           return false;
>> >
>> > ...tree_nop_conversion bails out at this "return false;", and hence
>> > tree_strip_nop_conversions simply returns the wrapper that was passed
>> > in.
>>
>> Right.  So let's change tree_nop_conversion to return true.
>
> I'd fear that would break too much stuff, VIEW_CONVERT_EXPR is not
> a normal conversion, but reinterpretation of the bits.
>
> Or do you mean it should strip just the special VIEW_CONVERT_EXPR
> that has type identical to the operand's type?

That; interpreting something as the same type seems like a nop.

Jason

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

* Re: [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p
  2017-12-19 21:59                   ` Jason Merrill
@ 2017-12-19 22:03                     ` Jakub Jelinek
  2017-12-20  0:41                       ` [PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jakub Jelinek @ 2017-12-19 22:03 UTC (permalink / raw)
  To: Jason Merrill
  Cc: David Malcolm, Nathan Sidwell, Richard Biener, gcc-patches List

On Tue, Dec 19, 2017 at 04:59:34PM -0500, Jason Merrill wrote:
> > Or do you mean it should strip just the special VIEW_CONVERT_EXPR
> > that has type identical to the operand's type?
> 
> That; interpreting something as the same type seems like a nop.

Ok, that makes sense.

	Jakub

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

* [PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS
  2017-12-19 22:03                     ` Jakub Jelinek
@ 2017-12-20  0:41                       ` David Malcolm
  2017-12-20  4:27                         ` Jeff Law
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20  0:41 UTC (permalink / raw)
  To: Jakub Jelinek, Jason Merrill
  Cc: Nathan Sidwell, Richard Biener, gcc-patches List, David Malcolm

On Tue, 2017-12-19 at 23:03 +0100, Jakub Jelinek wrote:
> On Tue, Dec 19, 2017 at 04:59:34PM -0500, Jason Merrill wrote:
> > > Or do you mean it should strip just the special VIEW_CONVERT_EXPR
> > > that has type identical to the operand's type?
> > 
> > That; interpreting something as the same type seems like a nop.
> 
> Ok, that makes sense.
> 
> 	Jakub

Thanks.

How does the following look?

Bootstrap&regrtest in progress; OK for trunk if it passes? (once the rest of
the kit is approved, of course)

gcc/ChangeLog:
	* tree.c (tree_nop_conversion): Return true for location wrapper
	nodes.
	(selftest::check_strip_nops): New function.
	(selftest::test_location_wrappers): Verify that STRIP_NOPS removes
	wrappers.
---
 gcc/tree.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/gcc/tree.c b/gcc/tree.c
index 2d14916..9c9bb77 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11889,6 +11889,8 @@ tree_nop_conversion (const_tree exp)
 {
   tree outer_type, inner_type;
 
+  if (location_wrapper_p (exp))
+    return true;
   if (!CONVERT_EXPR_P (exp)
       && TREE_CODE (exp) != NON_LVALUE_EXPR)
     return false;
@@ -14208,6 +14210,17 @@ test_vector_cst_patterns ()
   check_vector_cst_fill (elements, build_vector (vector_type, elements), 4);
 }
 
+/* Verify that STRIP_NOPS (NODE) is EXPECTED.
+   Helper function for test_location_wrappers, to deal with STRIP_NOPS
+   modifying its argument in-place.  */
+
+static void
+check_strip_nops (tree node, tree expected)
+{
+  STRIP_NOPS (node);
+  ASSERT_EQ (expected, node);
+}
+
 /* Verify location wrappers.  */
 
 static void
@@ -14242,6 +14255,10 @@ test_location_wrappers ()
   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));
+
+  /* Verify that STRIP_NOPS removes wrappers.  */
+  check_strip_nops (wrapped_int_cst, int_cst);
+  check_strip_nops (wrapped_int_var, int_var);
 }
 
 /* Run all of the selftests within this file.  */
-- 
1.8.5.3

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

* [v2 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-12-19 20:35           ` Jason Merrill
@ 2017-12-20  0:50             ` David Malcolm
  2017-12-20  4:22               ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20  0:50 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Tue, 2017-12-19 at 15:35 -0500, Jason Merrill wrote:
> On Sat, Dec 16, 2017 at 8:12 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > I rebased the v2 patchkit; here's an extra patch to fix an issue
> > with it uncovered by a recently-added testcase (in r254990).
> > 
> > With the patch kit, but without this patch, g++'s
> >   c-c++-common/pr83059.c
> > fails to emit the "invalid memory model argument 6" warning.
> > 
> > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> > part of the kit.
> > 
> > Is this OK for trunk, assuming the rest of the kit is approved?
> > 
> > gcc/c-family/ChangeLog:
> >         * c-common.c (get_atomic_generic_size): Call fold_for_warn
> > on the
> >         params before checking for INTEGER_CST.
> > ---
> >  gcc/c-family/c-common.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> > index 3438b87..ab03b7d 100644
> > --- a/gcc/c-family/c-common.c
> > +++ b/gcc/c-family/c-common.c
> > @@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc, tree
> > function,
> >    /* Check memory model parameters for validity.  */
> >    for (x = n_param - n_model ; x < n_param; x++)
> >      {
> > -      tree p = (*params)[x];
> > +      tree p = fold_for_warn ((*params)[x]);
> >        if (TREE_CODE (p) == INTEGER_CST)
> >          {
> >           /* memmodel_base masks the low 16 bits, thus ignore any
> > bits above
> 
> Let's check the error case before we call fold_for_warn.
> 
> Jason

Do you mean like this?  (bootstrapped; regrtest in progress)

Thanks
Dave

gcc/c-family/ChangeLog:
	* c-common.c (get_atomic_generic_size): Call fold_for_warn on the
	params before checking for INTEGER_CST.
---
 gcc/c-family/c-common.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3438b87..9d43aaa 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6721,6 +6721,9 @@ get_atomic_generic_size (location_t loc, tree function,
   for (x = n_param - n_model ; x < n_param; x++)
     {
       tree p = (*params)[x];
+      if (p == error_mark_node)
+	return 0;
+      p = fold_for_warn (p);
       if (TREE_CODE (p) == INTEGER_CST)
         {
 	  /* memmodel_base masks the low 16 bits, thus ignore any bits above
-- 
1.8.5.3

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

* Re: [v2 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-12-20  0:50             ` [v2 of PATCH " David Malcolm
@ 2017-12-20  4:22               ` Jason Merrill
  2017-12-20 19:33                 ` [v3 " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-20  4:22 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Tue, Dec 19, 2017 at 7:53 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2017-12-19 at 15:35 -0500, Jason Merrill wrote:
>> On Sat, Dec 16, 2017 at 8:12 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > I rebased the v2 patchkit; here's an extra patch to fix an issue
>> > with it uncovered by a recently-added testcase (in r254990).
>> >
>> > With the patch kit, but without this patch, g++'s
>> >   c-c++-common/pr83059.c
>> > fails to emit the "invalid memory model argument 6" warning.
>> >
>> > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
>> > part of the kit.
>> >
>> > Is this OK for trunk, assuming the rest of the kit is approved?
>> >
>> > gcc/c-family/ChangeLog:
>> >         * c-common.c (get_atomic_generic_size): Call fold_for_warn
>> > on the
>> >         params before checking for INTEGER_CST.
>> > ---
>> >  gcc/c-family/c-common.c | 2 +-
>> >  1 file changed, 1 insertion(+), 1 deletion(-)
>> >
>> > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
>> > index 3438b87..ab03b7d 100644
>> > --- a/gcc/c-family/c-common.c
>> > +++ b/gcc/c-family/c-common.c
>> > @@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc, tree
>> > function,
>> >    /* Check memory model parameters for validity.  */
>> >    for (x = n_param - n_model ; x < n_param; x++)
>> >      {
>> > -      tree p = (*params)[x];
>> > +      tree p = fold_for_warn ((*params)[x]);
>> >        if (TREE_CODE (p) == INTEGER_CST)
>> >          {
>> >           /* memmodel_base masks the low 16 bits, thus ignore any
>> > bits above
>>
>> Let's check the error case before we call fold_for_warn.
>>
>> Jason
>
> Do you mean like this?  (bootstrapped; regrtest in progress)

Ah, no, sorry I wasn't clear.  I meant to reorder the if/else there,
so we check for INTEGER_TYPE first and potentially give an error, then
fold, and then potentially warn.

Jason

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

* Re: [PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS
  2017-12-20  0:41                       ` [PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS David Malcolm
@ 2017-12-20  4:27                         ` Jeff Law
  0 siblings, 0 replies; 111+ messages in thread
From: Jeff Law @ 2017-12-20  4:27 UTC (permalink / raw)
  To: David Malcolm, Jakub Jelinek, Jason Merrill
  Cc: Nathan Sidwell, Richard Biener, gcc-patches List

On 12/19/2017 05:44 PM, David Malcolm wrote:
> On Tue, 2017-12-19 at 23:03 +0100, Jakub Jelinek wrote:
>> On Tue, Dec 19, 2017 at 04:59:34PM -0500, Jason Merrill wrote:
>>>> Or do you mean it should strip just the special VIEW_CONVERT_EXPR
>>>> that has type identical to the operand's type?
>>>
>>> That; interpreting something as the same type seems like a nop.
>>
>> Ok, that makes sense.
>>
>> 	Jakub
> 
> Thanks.
> 
> How does the following look?
> 
> Bootstrap&regrtest in progress; OK for trunk if it passes? (once the rest of
> the kit is approved, of course)
> 
> gcc/ChangeLog:
> 	* tree.c (tree_nop_conversion): Return true for location wrapper
> 	nodes.
> 	(selftest::check_strip_nops): New function.
> 	(selftest::test_location_wrappers): Verify that STRIP_NOPS removes
> 	wrappers.
OK.
jeff

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

* Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-19 19:55               ` Jason Merrill
@ 2017-12-20 17:33                 ` David Malcolm
  2017-12-21  5:03                   ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20 17:33 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
> On 12/17/2017 11:29 AM, David Malcolm wrote:
> > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > > > +
> > > >       if (VAR_P (format_tree))
> > > >         {
> > > >           /* Pull out a constant value if the front end
> > > > didn't.  */
> > > 
> > > It seems like we want fold_for_warn here instead of the special
> > > variable
> > > handling.  That probably makes sense for the other places you
> > > change in
> > > this patch, too.
> > 
> > Here's an updated version of the patch which uses fold_for_warn,
> > rather than STRIP_ANY_LOCATION_WRAPPER.
> > 
> > In one place it was necessary to add a STRIP_NOPS, since the
> > fold_for_warn can add a cast around a:
> >    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> >      STRING_CST)
> > turning it into a:
> >    NOP_EXPR<POINTER_TYPE(char))> (
> >      ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> >        STRING_CST))
> 
> Hmm, that seems like a bug.  fold_for_warn shouldn't change the type
> of 
> the result.

In a similar vein, is the result of decl_constant_value (decl) required
to be the same type as that of the decl?

What's happening for this testcase (g++.dg/warn/Wformat-1.C) is that we
have a VAR_DECL with a DECL_INITIAL, but the types of the two don't
quite match up.

decl_constant_value returns an unshare_expr clone of the DECL_INITIAL,
and this is what's returned from fold_for_warn.

Am I right in thinking

(a) that the bug here is that a DECL_INITIAL ought to have the same
    type as its decl, and so there's a missing cast where that gets
    set up, or

(b) should decl_constant_value handle such cases, and introduce a cast
    if it uncovers them?

Thanks
Dave



> > +  format_tree = fold_for_warn (format_tree);
> > +
> >     if (VAR_P (format_tree))
> >       {
> >         /* Pull out a constant value if the front end didn't.  */
> 
> I was suggesting dropping the if (VAR_P... block, since pulling out
> the 
> constant value should now be covered by fold_for_warn.
> 
> > -    format_tree = TREE_OPERAND (format_tree, 0);
> > +    {
> > +      format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
> > +    }
> 
> Why the added braces?

(I messed up; will be fixed in the next version)

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

* [v3 of 05/14] C++: handle locations wrappers when calling warn_for_memset
  2017-12-19 20:02                 ` Jason Merrill
@ 2017-12-20 19:23                   ` David Malcolm
  2017-12-21  4:58                     ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20 19:23 UTC (permalink / raw)
  To: Jason Merrill, Martin Sebor
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Tue, 2017-12-19 at 15:02 -0500, Jason Merrill wrote:
> On 12/16/2017 03:01 PM, Martin Sebor wrote:
> > On 12/16/2017 06:12 AM, David Malcolm wrote:
> > > On Mon, 2017-12-11 at 18:36 -0500, Jason Merrill wrote:
> > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > We need to strip away location wrappers in tree.c predicates
> > > > > like
> > > > > integer_zerop, otherwise they fail when they're called on
> > > > > wrapped INTEGER_CST; an example can be seen for
> > > > >    c-c++-common/Wmemset-transposed-args1.c
> > > > > in g++.sum, where the warn_for_memset fails to detect integer
> > > > > zero
> > > > > if the location wrappers aren't stripped.
> > > > 
> > > > These shouldn't be needed; callers should have folded away
> > > > location
> > > > wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be
> > > > almost
> > > > never needed.
> > > > 
> > > > warn_for_memset may be missing some calls to fold_for_warn.
> > > 
> > > It is, thanks.
> > > 
> > > Here's a revised fix for e.g. Wmemset-transposed-args1.c,
> > > replacing
> > > "[PATCH 05/14] tree.c: strip location wrappers from integer_zerop
> > > etc"
> > > and
> > > "[PATCH 10/14] warn_for_memset: handle location wrappers"
> > > 
> > > This version of the patch simply calls fold_for_warn on each of
> > > the
> > > arguments before calling warn_for_memset.  This ensures that
> > > warn_for_memset detects integer zero.  It also adds a
> > > literal_integer_zerop to deal with location wrapper nodes when
> > > building "literal_mask" for the call, since this must be called
> > > *before* the fold_for_warn calls.
> > > 
> > > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> > > part of the kit.
> > > 
> > > Is this OK for trunk, once the rest of the kit is approved?
> > > 
> > > gcc/cp/ChangeLog:
> > >     * parser.c (literal_integer_zerop): New function.
> > >     (cp_parser_postfix_expression): When calling warn_for_memset,
> > >     replace integer_zerop calls with literal_integer_zerop, and
> > >     call fold_for_warn on the arguments.
> > > ---
> > >  gcc/cp/parser.c | 18 ++++++++++++++++--
> > >  1 file changed, 16 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > > index d15769a..7bca460 100644
> > > --- a/gcc/cp/parser.c
> > > +++ b/gcc/cp/parser.c
> > > @@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser
> > > *parser)
> > >    return compound_literal_p;
> > >  }
> > > 
> > > +/* Return 1 if EXPR is the integer constant zero or a complex
> > > constant
> > > +   of zero, without any folding, but ignoring location
> > > wrappers.  */
> > > +
> > > +static int
> > > +literal_integer_zerop (const_tree expr)
> > > +{
> > > +  STRIP_ANY_LOCATION_WRAPPER (expr);
> > > +  return integer_zerop (expr);
> > > +}
> > > +
> > >  /* Parse a postfix-expression.
> > > 
> > >     postfix-expression:
> > > @@ -7168,8 +7178,12 @@ cp_parser_postfix_expression (cp_parser 
> > > *parser, bool address_p, bool cast_p,
> > >          tree arg0 = (*args)[0];
> > >          tree arg1 = (*args)[1];
> > >          tree arg2 = (*args)[2];
> > > -        int literal_mask = ((!!integer_zerop (arg1) << 1)
> > > -                    | (!!integer_zerop (arg2) << 2));
> > > +        /* Handle any location wrapper nodes.  */
> > > +        arg0 = fold_for_warn (arg0);
> > > +        int literal_mask = ((!!literal_integer_zerop (arg1) <<
> > > 1)
> > > +                    | (!!literal_integer_zerop (arg2) << 2));
> > 
> > The double negation jumped out at me.  The integer_zerop() function
> > looks like a predicate that hasn't yet been converted to return
> > bool.
> > It seems that new predicates that are implemented on top of it
> > could
> > return bool and their callers avoid this conversion.  (At some
> > point
> > in the future it would also be nice to convert the existing
> > predicates to return bool).
> 
> Agreed.  And since integer_zerop in fact returns boolean values,
> there 
> seems to be no need for the double negative in the first place.
> 
> So, please make the new function return bool and remove the !!s.
> 
> And I think the fold_for_warn call should be in warn_for_memset, and
> it 
> should be called for arg2 as well instead of specifically handling 
> CONST_DECL Here.

Thanks.

Here's an updated version of the patch which I believe covers all
of the above.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

OK for trunk once the rest of the kit is approved?

gcc/c-family/ChangeLog:
	* c-warn.c (warn_for_memset): Call fold_for_warn on the arguments.

gcc/cp/ChangeLog:
	* parser.c (literal_integer_zerop): New function.
	(cp_parser_postfix_expression): When calling warn_for_memset,
	replace integer_zerop calls with literal_integer_zerop,
	eliminating the double logical negation cast to bool.
	Eliminate the special-casing for CONST_DECL in favor of the
	fold_for_warn within warn_for_memset.
---
 gcc/c-family/c-warn.c |  3 +++
 gcc/cp/parser.c       | 16 ++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 6045d6e..baaf37e 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -1865,6 +1865,9 @@ void
 warn_for_memset (location_t loc, tree arg0, tree arg2,
 		 int literal_zero_mask)
 {
+  arg0 = fold_for_warn (arg0);
+  arg2 = fold_for_warn (arg2);
+
   if (warn_memset_transposed_args
       && integer_zerop (arg2)
       && (literal_zero_mask & (1 << 2)) != 0
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d15769a..adfca60 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
   return compound_literal_p;
 }
 
+/* Return true if EXPR is the integer constant zero or a complex constant
+   of zero, without any folding, but ignoring location wrappers.  */
+
+static bool
+literal_integer_zerop (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+  return integer_zerop (expr);
+}
+
 /* Parse a postfix-expression.
 
    postfix-expression:
@@ -7168,10 +7178,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		tree arg0 = (*args)[0];
 		tree arg1 = (*args)[1];
 		tree arg2 = (*args)[2];
-		int literal_mask = ((!!integer_zerop (arg1) << 1)
-				    | (!!integer_zerop (arg2) << 2));
-		if (TREE_CODE (arg2) == CONST_DECL)
-		  arg2 = DECL_INITIAL (arg2);
+		int literal_mask = ((literal_integer_zerop (arg1) << 1)
+				    | (literal_integer_zerop (arg2) << 2));
 		warn_for_memset (input_location, arg0, arg2, literal_mask);
 	      }
 
-- 
1.8.5.3

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

* [v3 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-12-20  4:22               ` Jason Merrill
@ 2017-12-20 19:33                 ` David Malcolm
  2017-12-21  4:57                   ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20 19:33 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Tue, 2017-12-19 at 23:22 -0500, Jason Merrill wrote:
> On Tue, Dec 19, 2017 at 7:53 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Tue, 2017-12-19 at 15:35 -0500, Jason Merrill wrote:
> > > On Sat, Dec 16, 2017 at 8:12 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > I rebased the v2 patchkit; here's an extra patch to fix an
> > > > issue
> > > > with it uncovered by a recently-added testcase (in r254990).
> > > > 
> > > > With the patch kit, but without this patch, g++'s
> > > >   c-c++-common/pr83059.c
> > > > fails to emit the "invalid memory model argument 6" warning.
> > > > 
> > > > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> > > > part of the kit.
> > > > 
> > > > Is this OK for trunk, assuming the rest of the kit is approved?
> > > > 
> > > > gcc/c-family/ChangeLog:
> > > >         * c-common.c (get_atomic_generic_size): Call
> > > > fold_for_warn
> > > > on the
> > > >         params before checking for INTEGER_CST.
> > > > ---
> > > >  gcc/c-family/c-common.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > 
> > > > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> > > > index 3438b87..ab03b7d 100644
> > > > --- a/gcc/c-family/c-common.c
> > > > +++ b/gcc/c-family/c-common.c
> > > > @@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc,
> > > > tree
> > > > function,
> > > >    /* Check memory model parameters for validity.  */
> > > >    for (x = n_param - n_model ; x < n_param; x++)
> > > >      {
> > > > -      tree p = (*params)[x];
> > > > +      tree p = fold_for_warn ((*params)[x]);
> > > >        if (TREE_CODE (p) == INTEGER_CST)
> > > >          {
> > > >           /* memmodel_base masks the low 16 bits, thus ignore
> > > > any
> > > > bits above
> > > 
> > > Let's check the error case before we call fold_for_warn.
> > > 
> > > Jason
> > 
> > Do you mean like this?  (bootstrapped; regrtest in progress)
> 
> Ah, no, sorry I wasn't clear.  I meant to reorder the if/else there,
> so we check for INTEGER_TYPE first and potentially give an error,
> then
> fold, and then potentially warn.
> 
> Jason

Aha - thanks!

Here's an updated version of the patch.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

OK for trunk once the rest of the kit is approved?

gcc/c-family/ChangeLog:
	* c-common.c (get_atomic_generic_size): Perform the test for
	integral type before the range test for any integer constant,
	fixing indentation of braces.  Call fold_for_warn before
	testing for an INTEGER_CST.
---
 gcc/c-family/c-common.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3438b87..7cc749b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6721,8 +6721,15 @@ get_atomic_generic_size (location_t loc, tree function,
   for (x = n_param - n_model ; x < n_param; x++)
     {
       tree p = (*params)[x];
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
+	{
+	  error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
+		    function);
+	  return 0;
+	}
+      p = fold_for_warn (p);
       if (TREE_CODE (p) == INTEGER_CST)
-        {
+	{
 	  /* memmodel_base masks the low 16 bits, thus ignore any bits above
 	     it by using TREE_INT_CST_LOW instead of tree_to_*hwi.  Those high
 	     bits will be checked later during expansion in target specific
@@ -6732,14 +6739,7 @@ get_atomic_generic_size (location_t loc, tree function,
 			"invalid memory model argument %d of %qE", x + 1,
 			function);
 	}
-      else
-	if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
-	  {
-	    error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
-		   function);
-	    return 0;
-	  }
-      }
+    }
 
   return size_0;
 }
-- 
1.8.5.3

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

* [v2 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-12-11 23:39           ` Jason Merrill
@ 2017-12-20 22:11             ` David Malcolm
  2017-12-21  4:56               ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-20 22:11 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Mon, 2017-12-11 at 18:39 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > Without this, then lvalue_p returns false for decls, and hence
> > e.g. uses of them for references fail.
> > 
> > Stripping location wrappers in lvalue_kind restores the correct
> > behavior of lvalue_p etc.
> > 
> > gcc/cp/ChangeLog:
> > 	* tree.c (lvalue_kind): Strip any location wrapper.
> 
> Rather, lvalue_kind should learn to handle VIEW_CONVERT_EXPR.
> 
> Jason

Thanks.

This patch does so, using:

    case NON_LVALUE_EXPR:
    case VIEW_CONVERT_EXPR:
      if (location_wrapper_p (ref))
	return lvalue_kind (TREE_OPERAND (ref, 0));

As well as the VIEW_CONVERT_EXPR, lvalue_kind needs to handle
NON_LVALUE_EXPR, otherwise a location-wrapped string literal
hits this clause in the "default" case:

      if (CLASS_TYPE_P (TREE_TYPE (ref))
	  || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
	return clk_class;

when it should have hit this one (after removing the
location wrapper):

    case STRING_CST:
    case COMPOUND_LITERAL_EXPR:
      return clk_ordinary;

The patch adds selftest coverage for this case (and others).

Seen in e.g. libstdc++.sum's 21_strings/basic_string/cons/char/8.cc, which
would otherwise fail with this bogus error:

8.cc: In instantiation of 'std::size_t construct(Args&& ...)
  [with Args = {const char [9], int}; std::size_t = long unsigned int]':
8.cc:63:   required from here
8.cc:38: error: invalid static_cast from type 'const char [9]' to type 'const char [9]'
   TestBaseObjCtor as_base_obj( static_cast<Args>(args)... );
                                ^~~~~~~~~~~~~~~~~~~~~~~

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 once the rest of the kit is approved?

gcc/cp/ChangeLog:
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_tree_c_tests.
	* cp-tree.h (selftest::cp_tree_c_tests): New decl.
	* tree.c: Include "selftest.h".
	(lvalue_kind): Handle location wrapper nodes.
	(selftest::test_lvalue_kind): New function.
	(selftest::cp_tree_c_tests): New function.
---
 gcc/cp/cp-lang.c |  1 +
 gcc/cp/cp-tree.h |  8 +++++++
 gcc/cp/tree.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 805319a..9bb4ce7 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,7 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_tree_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9879e16..6d4a2b8a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7451,6 +7451,14 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+#if CHECKING_P
+namespace selftest {
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_tree_c_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 0ae2eff..ad8884c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "flags.h"
+#include "selftest.h"
 
 static tree bot_manip (tree *, int *, void *);
 static tree bot_replace (tree *, int *, void *);
@@ -240,6 +241,12 @@ lvalue_kind (const_tree ref)
     case NON_DEPENDENT_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (ref))
+	return lvalue_kind (TREE_OPERAND (ref, 0));
+      /* Fallthrough.  */
+
     default:
       if (!TREE_TYPE (ref))
 	return clk_none;
@@ -5339,4 +5346,64 @@ lang_check_failed (const char* file, int line, const char* function)
 }
 #endif /* ENABLE_TREE_CHECKING */
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that lvalue_kind () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_lvalue_kind ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants and parameters, without and with
+     location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
+
+  tree string_lit = build_string (3, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit));
+
+  tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
+			  get_identifier ("some_parm"),
+			  integer_type_node);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
+
+  tree wrapped_parm = maybe_wrap_with_location (parm, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_parm));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
+
+  /* Verify that lvalue_kind of std::move on a parm isn't
+     affected by location wrappers.  */
+  tree rvalue_ref_of_parm = move (parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
+  tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_tree_c_tests ()
+{
+  test_lvalue_kind ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+
 #include "gt-cp-tree.h"
-- 
1.8.5.3

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

* Re: [v2 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-12-20 22:11             ` [v2 of PATCH " David Malcolm
@ 2017-12-21  4:56               ` Jason Merrill
  2017-12-21 17:47                 ` [v3 " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-21  4:56 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Wed, Dec 20, 2017 at 5:14 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Mon, 2017-12-11 at 18:39 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > Without this, then lvalue_p returns false for decls, and hence
>> > e.g. uses of them for references fail.
>> >
>> > Stripping location wrappers in lvalue_kind restores the correct
>> > behavior of lvalue_p etc.
>> >
>> > gcc/cp/ChangeLog:
>> >     * tree.c (lvalue_kind): Strip any location wrapper.
>>
>> Rather, lvalue_kind should learn to handle VIEW_CONVERT_EXPR.

> This patch does so, using:
>
>     case NON_LVALUE_EXPR:
>     case VIEW_CONVERT_EXPR:
>       if (location_wrapper_p (ref))
>         return lvalue_kind (TREE_OPERAND (ref, 0));
>
> As well as the VIEW_CONVERT_EXPR, lvalue_kind needs to handle
> NON_LVALUE_EXPR, otherwise a location-wrapped string literal
> hits this clause in the "default" case:
>
>       if (CLASS_TYPE_P (TREE_TYPE (ref))
>           || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
>         return clk_class;
>
> when it should have hit this one (after removing the
> location wrapper):
>
>     case STRING_CST:
>     case COMPOUND_LITERAL_EXPR:
>       return clk_ordinary;

Ah, the issue is that string literals should use VIEW_CONVERT_EXPR
rather than NON_LVALUE_EXPR, since they are lvalues.  With that
change, we shouldn't need to handle NON_LVALUE_EXPR specifically.

Jason

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

* Re: [v3 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size
  2017-12-20 19:33                 ` [v3 " David Malcolm
@ 2017-12-21  4:57                   ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-21  4:57 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Wed, Dec 20, 2017 at 2:36 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2017-12-19 at 23:22 -0500, Jason Merrill wrote:
>> On Tue, Dec 19, 2017 at 7:53 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > On Tue, 2017-12-19 at 15:35 -0500, Jason Merrill wrote:
>> > > On Sat, Dec 16, 2017 at 8:12 PM, David Malcolm <dmalcolm@redhat.c
>> > > om>
>> > > wrote:
>> > > > I rebased the v2 patchkit; here's an extra patch to fix an
>> > > > issue
>> > > > with it uncovered by a recently-added testcase (in r254990).
>> > > >
>> > > > With the patch kit, but without this patch, g++'s
>> > > >   c-c++-common/pr83059.c
>> > > > fails to emit the "invalid memory model argument 6" warning.
>> > > >
>> > > > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
>> > > > part of the kit.
>> > > >
>> > > > Is this OK for trunk, assuming the rest of the kit is approved?
>> > > >
>> > > > gcc/c-family/ChangeLog:
>> > > >         * c-common.c (get_atomic_generic_size): Call
>> > > > fold_for_warn
>> > > > on the
>> > > >         params before checking for INTEGER_CST.
>> > > > ---
>> > > >  gcc/c-family/c-common.c | 2 +-
>> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
>> > > >
>> > > > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
>> > > > index 3438b87..ab03b7d 100644
>> > > > --- a/gcc/c-family/c-common.c
>> > > > +++ b/gcc/c-family/c-common.c
>> > > > @@ -6720,7 +6720,7 @@ get_atomic_generic_size (location_t loc,
>> > > > tree
>> > > > function,
>> > > >    /* Check memory model parameters for validity.  */
>> > > >    for (x = n_param - n_model ; x < n_param; x++)
>> > > >      {
>> > > > -      tree p = (*params)[x];
>> > > > +      tree p = fold_for_warn ((*params)[x]);
>> > > >        if (TREE_CODE (p) == INTEGER_CST)
>> > > >          {
>> > > >           /* memmodel_base masks the low 16 bits, thus ignore
>> > > > any
>> > > > bits above
>> > >
>> > > Let's check the error case before we call fold_for_warn.
>> > >
>> > > Jason
>> >
>> > Do you mean like this?  (bootstrapped; regrtest in progress)
>>
>> Ah, no, sorry I wasn't clear.  I meant to reorder the if/else there,
>> so we check for INTEGER_TYPE first and potentially give an error,
>> then
>> fold, and then potentially warn.
>>
>> Jason
>
> Aha - thanks!
>
> Here's an updated version of the patch.
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
>
> OK for trunk once the rest of the kit is approved?

OK.

Jason

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

* Re: [v3 of 05/14] C++: handle locations wrappers when calling warn_for_memset
  2017-12-20 19:23                   ` [v3 of 05/14] " David Malcolm
@ 2017-12-21  4:58                     ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-21  4:58 UTC (permalink / raw)
  To: David Malcolm
  Cc: Martin Sebor, Nathan Sidwell, Jakub Jelinek, Richard Biener,
	gcc-patches List

On Wed, Dec 20, 2017 at 2:26 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2017-12-19 at 15:02 -0500, Jason Merrill wrote:
>> On 12/16/2017 03:01 PM, Martin Sebor wrote:
>> > On 12/16/2017 06:12 AM, David Malcolm wrote:
>> > > On Mon, 2017-12-11 at 18:36 -0500, Jason Merrill wrote:
>> > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > > We need to strip away location wrappers in tree.c predicates
>> > > > > like
>> > > > > integer_zerop, otherwise they fail when they're called on
>> > > > > wrapped INTEGER_CST; an example can be seen for
>> > > > >    c-c++-common/Wmemset-transposed-args1.c
>> > > > > in g++.sum, where the warn_for_memset fails to detect integer
>> > > > > zero
>> > > > > if the location wrappers aren't stripped.
>> > > >
>> > > > These shouldn't be needed; callers should have folded away
>> > > > location
>> > > > wrappers.  I would hope for STRIP_ANY_LOCATION_WRAPPER to be
>> > > > almost
>> > > > never needed.
>> > > >
>> > > > warn_for_memset may be missing some calls to fold_for_warn.
>> > >
>> > > It is, thanks.
>> > >
>> > > Here's a revised fix for e.g. Wmemset-transposed-args1.c,
>> > > replacing
>> > > "[PATCH 05/14] tree.c: strip location wrappers from integer_zerop
>> > > etc"
>> > > and
>> > > "[PATCH 10/14] warn_for_memset: handle location wrappers"
>> > >
>> > > This version of the patch simply calls fold_for_warn on each of
>> > > the
>> > > arguments before calling warn_for_memset.  This ensures that
>> > > warn_for_memset detects integer zero.  It also adds a
>> > > literal_integer_zerop to deal with location wrapper nodes when
>> > > building "literal_mask" for the call, since this must be called
>> > > *before* the fold_for_warn calls.
>> > >
>> > > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
>> > > part of the kit.
>> > >
>> > > Is this OK for trunk, once the rest of the kit is approved?
>> > >
>> > > gcc/cp/ChangeLog:
>> > >     * parser.c (literal_integer_zerop): New function.
>> > >     (cp_parser_postfix_expression): When calling warn_for_memset,
>> > >     replace integer_zerop calls with literal_integer_zerop, and
>> > >     call fold_for_warn on the arguments.
>> > > ---
>> > >  gcc/cp/parser.c | 18 ++++++++++++++++--
>> > >  1 file changed, 16 insertions(+), 2 deletions(-)
>> > >
>> > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>> > > index d15769a..7bca460 100644
>> > > --- a/gcc/cp/parser.c
>> > > +++ b/gcc/cp/parser.c
>> > > @@ -6621,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser
>> > > *parser)
>> > >    return compound_literal_p;
>> > >  }
>> > >
>> > > +/* Return 1 if EXPR is the integer constant zero or a complex
>> > > constant
>> > > +   of zero, without any folding, but ignoring location
>> > > wrappers.  */
>> > > +
>> > > +static int
>> > > +literal_integer_zerop (const_tree expr)
>> > > +{
>> > > +  STRIP_ANY_LOCATION_WRAPPER (expr);
>> > > +  return integer_zerop (expr);
>> > > +}
>> > > +
>> > >  /* Parse a postfix-expression.
>> > >
>> > >     postfix-expression:
>> > > @@ -7168,8 +7178,12 @@ cp_parser_postfix_expression (cp_parser
>> > > *parser, bool address_p, bool cast_p,
>> > >          tree arg0 = (*args)[0];
>> > >          tree arg1 = (*args)[1];
>> > >          tree arg2 = (*args)[2];
>> > > -        int literal_mask = ((!!integer_zerop (arg1) << 1)
>> > > -                    | (!!integer_zerop (arg2) << 2));
>> > > +        /* Handle any location wrapper nodes.  */
>> > > +        arg0 = fold_for_warn (arg0);
>> > > +        int literal_mask = ((!!literal_integer_zerop (arg1) <<
>> > > 1)
>> > > +                    | (!!literal_integer_zerop (arg2) << 2));
>> >
>> > The double negation jumped out at me.  The integer_zerop() function
>> > looks like a predicate that hasn't yet been converted to return
>> > bool.
>> > It seems that new predicates that are implemented on top of it
>> > could
>> > return bool and their callers avoid this conversion.  (At some
>> > point
>> > in the future it would also be nice to convert the existing
>> > predicates to return bool).
>>
>> Agreed.  And since integer_zerop in fact returns boolean values,
>> there
>> seems to be no need for the double negative in the first place.
>>
>> So, please make the new function return bool and remove the !!s.
>>
>> And I think the fold_for_warn call should be in warn_for_memset, and
>> it
>> should be called for arg2 as well instead of specifically handling
>> CONST_DECL Here.
>
> Thanks.
>
> Here's an updated version of the patch which I believe covers all
> of the above.
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
>
> OK for trunk once the rest of the kit is approved?

OK.

Jason

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

* Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-20 17:33                 ` David Malcolm
@ 2017-12-21  5:03                   ` Jason Merrill
  2017-12-22 19:07                     ` [v3 " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2017-12-21  5:03 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Wed, Dec 20, 2017 at 12:33 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
>> On 12/17/2017 11:29 AM, David Malcolm wrote:
>> > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
>> > > > +
>> > > >       if (VAR_P (format_tree))
>> > > >         {
>> > > >           /* Pull out a constant value if the front end
>> > > > didn't.  */
>> > >
>> > > It seems like we want fold_for_warn here instead of the special
>> > > variable
>> > > handling.  That probably makes sense for the other places you
>> > > change in
>> > > this patch, too.
>> >
>> > Here's an updated version of the patch which uses fold_for_warn,
>> > rather than STRIP_ANY_LOCATION_WRAPPER.
>> >
>> > In one place it was necessary to add a STRIP_NOPS, since the
>> > fold_for_warn can add a cast around a:
>> >    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
>> >      STRING_CST)
>> > turning it into a:
>> >    NOP_EXPR<POINTER_TYPE(char))> (
>> >      ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
>> >        STRING_CST))
>>
>> Hmm, that seems like a bug.  fold_for_warn shouldn't change the type of
>> the result.
>
> In a similar vein, is the result of decl_constant_value (decl) required
> to be the same type as that of the decl?
>
> What's happening for this testcase (g++.dg/warn/Wformat-1.C) is that we
> have a VAR_DECL with a DECL_INITIAL, but the types of the two don't
> quite match up.
>
> decl_constant_value returns an unshare_expr clone of the DECL_INITIAL,
> and this is what's returned from fold_for_warn.
>
> Am I right in thinking
>
> (a) that the bug here is that a DECL_INITIAL ought to have the same
>     type as its decl, and so there's a missing cast where that gets
>     set up, or

This seems right.

> (b) should decl_constant_value handle such cases, and introduce a cast
>     if it uncovers them?

decl_constant_value should probably assert that the types match closely enough.

Jason

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

* [v3 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-12-21  4:56               ` Jason Merrill
@ 2017-12-21 17:47                 ` David Malcolm
  2017-12-21 22:44                   ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-21 17:47 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Wed, 2017-12-20 at 23:56 -0500, Jason Merrill wrote:
> On Wed, Dec 20, 2017 at 5:14 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Mon, 2017-12-11 at 18:39 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > Without this, then lvalue_p returns false for decls, and hence
> > > > e.g. uses of them for references fail.
> > > > 
> > > > Stripping location wrappers in lvalue_kind restores the correct
> > > > behavior of lvalue_p etc.
> > > > 
> > > > gcc/cp/ChangeLog:
> > > >     * tree.c (lvalue_kind): Strip any location wrapper.
> > > 
> > > Rather, lvalue_kind should learn to handle VIEW_CONVERT_EXPR.
> > This patch does so, using:
> > 
> >     case NON_LVALUE_EXPR:
> >     case VIEW_CONVERT_EXPR:
> >       if (location_wrapper_p (ref))
> >         return lvalue_kind (TREE_OPERAND (ref, 0));
> > 
> > As well as the VIEW_CONVERT_EXPR, lvalue_kind needs to handle
> > NON_LVALUE_EXPR, otherwise a location-wrapped string literal
> > hits this clause in the "default" case:
> > 
> >       if (CLASS_TYPE_P (TREE_TYPE (ref))
> >           || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
> >         return clk_class;
> > 
> > when it should have hit this one (after removing the
> > location wrapper):
> > 
> >     case STRING_CST:
> >     case COMPOUND_LITERAL_EXPR:
> >       return clk_ordinary;
> 
> Ah, the issue is that string literals should use VIEW_CONVERT_EXPR
> rather than NON_LVALUE_EXPR, since they are lvalues.  With that
> change, we shouldn't need to handle NON_LVALUE_EXPR specifically.
> 
> Jason

Thanks.  Here's an updated version of the patch which tweaks
maybe_wrap_with_location (from patch 02/14 [1]) for STRING_CST to do so,
also adding some more test coverage to selftest::test_location_wrappers
for the STRING_CST case.  With that, it only adds the VIEW_CONVERT_EXPR
case to lvalue_kind.

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

OK for trunk once the rest of the kit is approved?

[1] https://gcc.gnu.org/ml/gcc-patches/2017-11/msg02611.html

gcc/cp/ChangeLog:
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_tree_c_tests.
	* cp-tree.h (selftest::run_cp_tests): Move decl to bottom of file.
	(selftest::cp_tree_c_tests): New decl.
	* tree.c: Include "selftest.h".
	(lvalue_kind): Handle VIEW_CONVERT_EXPR location wrapper nodes.
	(selftest::test_lvalue_kind): New function.
	(selftest::cp_tree_c_tests): New function.

gcc/ChangeLog:
	* tree.c (maybe_wrap_with_location): Use VIEW_CONVERT_EXPR for
	STRING_CST.
	(selftest::test_location_wrappers): Add coverage for STRING_CST.
	* tree.h (location_wrapper_p): Update comment to reflect change to
	STRING_CST.
---
 gcc/cp/cp-lang.c |  1 +
 gcc/cp/cp-tree.h | 16 ++++++++------
 gcc/cp/tree.c    | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/tree.c       | 19 +++++++++++++---
 gcc/tree.h       |  4 ++--
 5 files changed, 95 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 805319a..9bb4ce7 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,7 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_tree_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9879e16..bb405f2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7415,12 +7415,6 @@ extern tree cp_ubsan_maybe_instrument_downcast	(location_t, tree, tree, tree);
 extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
 extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
 
-#if CHECKING_P
-namespace selftest {
-  extern void run_cp_tests (void);
-} // namespace selftest
-#endif /* #if CHECKING_P */
-
 /* Inline bodies.  */
 
 inline tree
@@ -7451,6 +7445,16 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+#if CHECKING_P
+namespace selftest {
+  extern void run_cp_tests (void);
+
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_tree_c_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 0ae2eff..6900bc7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "flags.h"
+#include "selftest.h"
 
 static tree bot_manip (tree *, int *, void *);
 static tree bot_replace (tree *, int *, void *);
@@ -240,6 +241,11 @@ lvalue_kind (const_tree ref)
     case NON_DEPENDENT_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (ref))
+	return lvalue_kind (TREE_OPERAND (ref, 0));
+      /* Fallthrough.  */
+
     default:
       if (!TREE_TYPE (ref))
 	return clk_none;
@@ -5339,4 +5345,64 @@ lang_check_failed (const char* file, int line, const char* function)
 }
 #endif /* ENABLE_TREE_CHECKING */
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that lvalue_kind () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_lvalue_kind ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants and parameters, without and with
+     location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit));
+
+  tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
+			  get_identifier ("some_parm"),
+			  integer_type_node);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
+
+  tree wrapped_parm = maybe_wrap_with_location (parm, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_parm));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
+
+  /* Verify that lvalue_kind of std::move on a parm isn't
+     affected by location wrappers.  */
+  tree rvalue_ref_of_parm = move (parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
+  tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_tree_c_tests ()
+{
+  test_lvalue_kind ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+
 #include "gt-cp-tree.h"
diff --git a/gcc/tree.c b/gcc/tree.c
index b72f963..517f4a4 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13811,8 +13811,8 @@ set_source_range (tree expr, source_range src_range)
 /* Return EXPR, potentially wrapped with a node expression LOC,
    if !CAN_HAVE_LOCATION_P (expr).
 
-   NON_LVALUE_EXPR is used for wrapping constants.
-   VIEW_CONVERT_EXPR is used for wrapping non-constants.
+   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.  */
 
@@ -13834,7 +13834,7 @@ maybe_wrap_with_location (tree expr, location_t loc)
   if (EXCEPTIONAL_CLASS_P (expr))
     return expr;
 
-  if (CONSTANT_CLASS_P (expr))
+  if (CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
     return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (expr), expr);
   else
     return build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
@@ -14238,6 +14238,18 @@ test_location_wrappers ()
   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"),
@@ -14258,6 +14270,7 @@ test_location_wrappers ()
 
   /* Verify that STRIP_NOPS removes wrappers.  */
   check_strip_nops (wrapped_int_cst, int_cst);
+  check_strip_nops (wrapped_string_cst, string_cst);
   check_strip_nops (wrapped_int_var, int_var);
 
   /* operand_equal_p should "see through" any location wrapper...  */
diff --git a/gcc/tree.h b/gcc/tree.h
index de085ca..7f4ea5e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3679,8 +3679,8 @@ location_wrapper_p (const_tree exp)
   /* A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and the
      same type as its operand.
 
-     NON_LVALUE_EXPR is used for wrapping constants.
-     VIEW_CONVERT_EXPR is used for wrapping non-constants.
+     NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
+     VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.
 
      A subtlety is that we may have to test whether we have the correct
      TREE_CODE for the wrapped TREE_CODE.  Otherwise, e.g. the C++ expression:
-- 
1.8.5.3

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

* Re: [v3 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind
  2017-12-21 17:47                 ` [v3 " David Malcolm
@ 2017-12-21 22:44                   ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2017-12-21 22:44 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

OK.

On Thu, Dec 21, 2017 at 12:50 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Wed, 2017-12-20 at 23:56 -0500, Jason Merrill wrote:
>> On Wed, Dec 20, 2017 at 5:14 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > On Mon, 2017-12-11 at 18:39 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > Without this, then lvalue_p returns false for decls, and hence
>> > > > e.g. uses of them for references fail.
>> > > >
>> > > > Stripping location wrappers in lvalue_kind restores the correct
>> > > > behavior of lvalue_p etc.
>> > > >
>> > > > gcc/cp/ChangeLog:
>> > > >     * tree.c (lvalue_kind): Strip any location wrapper.
>> > >
>> > > Rather, lvalue_kind should learn to handle VIEW_CONVERT_EXPR.
>> > This patch does so, using:
>> >
>> >     case NON_LVALUE_EXPR:
>> >     case VIEW_CONVERT_EXPR:
>> >       if (location_wrapper_p (ref))
>> >         return lvalue_kind (TREE_OPERAND (ref, 0));
>> >
>> > As well as the VIEW_CONVERT_EXPR, lvalue_kind needs to handle
>> > NON_LVALUE_EXPR, otherwise a location-wrapped string literal
>> > hits this clause in the "default" case:
>> >
>> >       if (CLASS_TYPE_P (TREE_TYPE (ref))
>> >           || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
>> >         return clk_class;
>> >
>> > when it should have hit this one (after removing the
>> > location wrapper):
>> >
>> >     case STRING_CST:
>> >     case COMPOUND_LITERAL_EXPR:
>> >       return clk_ordinary;
>>
>> Ah, the issue is that string literals should use VIEW_CONVERT_EXPR
>> rather than NON_LVALUE_EXPR, since they are lvalues.  With that
>> change, we shouldn't need to handle NON_LVALUE_EXPR specifically.
>>
>> Jason
>
> Thanks.  Here's an updated version of the patch which tweaks
> maybe_wrap_with_location (from patch 02/14 [1]) for STRING_CST to do so,
> also adding some more test coverage to selftest::test_location_wrappers
> for the STRING_CST case.  With that, it only adds the VIEW_CONVERT_EXPR
> case to lvalue_kind.
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
> Manually tested with "make s-selftest-c++" (since we don't run
> the selftests for cc1plus by default).
>
> OK for trunk once the rest of the kit is approved?
>
> [1] https://gcc.gnu.org/ml/gcc-patches/2017-11/msg02611.html
>
> gcc/cp/ChangeLog:
>         * cp-lang.c (selftest::run_cp_tests): Call
>         selftest::cp_tree_c_tests.
>         * cp-tree.h (selftest::run_cp_tests): Move decl to bottom of file.
>         (selftest::cp_tree_c_tests): New decl.
>         * tree.c: Include "selftest.h".
>         (lvalue_kind): Handle VIEW_CONVERT_EXPR location wrapper nodes.
>         (selftest::test_lvalue_kind): New function.
>         (selftest::cp_tree_c_tests): New function.
>
> gcc/ChangeLog:
>         * tree.c (maybe_wrap_with_location): Use VIEW_CONVERT_EXPR for
>         STRING_CST.
>         (selftest::test_location_wrappers): Add coverage for STRING_CST.
>         * tree.h (location_wrapper_p): Update comment to reflect change to
>         STRING_CST.
> ---
>  gcc/cp/cp-lang.c |  1 +
>  gcc/cp/cp-tree.h | 16 ++++++++------
>  gcc/cp/tree.c    | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  gcc/tree.c       | 19 +++++++++++++---
>  gcc/tree.h       |  4 ++--
>  5 files changed, 95 insertions(+), 11 deletions(-)
>
> diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
> index 805319a..9bb4ce7 100644
> --- a/gcc/cp/cp-lang.c
> +++ b/gcc/cp/cp-lang.c
> @@ -247,6 +247,7 @@ run_cp_tests (void)
>    c_family_tests ();
>
>    /* Additional C++-specific tests.  */
> +  cp_tree_c_tests ();
>  }
>
>  } // namespace selftest
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 9879e16..bb405f2 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7415,12 +7415,6 @@ extern tree cp_ubsan_maybe_instrument_downcast   (location_t, tree, tree, tree);
>  extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
>  extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
>
> -#if CHECKING_P
> -namespace selftest {
> -  extern void run_cp_tests (void);
> -} // namespace selftest
> -#endif /* #if CHECKING_P */
> -
>  /* Inline bodies.  */
>
>  inline tree
> @@ -7451,6 +7445,16 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
>    return candidate == name;
>  }
>
> +#if CHECKING_P
> +namespace selftest {
> +  extern void run_cp_tests (void);
> +
> +  /* Declarations for specific families of tests within cp,
> +     by source file, in alphabetical order.  */
> +  extern void cp_tree_c_tests (void);
> +} // namespace selftest
> +#endif /* #if CHECKING_P */
> +
>  /* -- end of C++ */
>
>  #endif /* ! GCC_CP_TREE_H */
> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> index 0ae2eff..6900bc7 100644
> --- a/gcc/cp/tree.c
> +++ b/gcc/cp/tree.c
> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "stringpool.h"
>  #include "attribs.h"
>  #include "flags.h"
> +#include "selftest.h"
>
>  static tree bot_manip (tree *, int *, void *);
>  static tree bot_replace (tree *, int *, void *);
> @@ -240,6 +241,11 @@ lvalue_kind (const_tree ref)
>      case NON_DEPENDENT_EXPR:
>        return lvalue_kind (TREE_OPERAND (ref, 0));
>
> +    case VIEW_CONVERT_EXPR:
> +      if (location_wrapper_p (ref))
> +       return lvalue_kind (TREE_OPERAND (ref, 0));
> +      /* Fallthrough.  */
> +
>      default:
>        if (!TREE_TYPE (ref))
>         return clk_none;
> @@ -5339,4 +5345,64 @@ lang_check_failed (const char* file, int line, const char* function)
>  }
>  #endif /* ENABLE_TREE_CHECKING */
>
> +#if CHECKING_P
> +
> +namespace selftest {
> +
> +/* Verify that lvalue_kind () works, for various expressions,
> +   and that location wrappers don't affect the results.  */
> +
> +static void
> +test_lvalue_kind ()
> +{
> +  location_t loc = BUILTINS_LOCATION;
> +
> +  /* Verify constants and parameters, without and with
> +     location wrappers.  */
> +  tree int_cst = build_int_cst (integer_type_node, 42);
> +  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
> +
> +  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
> +  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
> +  ASSERT_EQ (clk_none, lvalue_kind (integer_zero_node));
> +
> +  tree string_lit = build_string (4, "foo");
> +  TREE_TYPE (string_lit) = char_array_type_node;
> +  string_lit = fix_string_type (string_lit);
> +  ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit));
> +
> +  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
> +  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
> +  ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit));
> +
> +  tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
> +                         get_identifier ("some_parm"),
> +                         integer_type_node);
> +  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
> +
> +  tree wrapped_parm = maybe_wrap_with_location (parm, loc);
> +  ASSERT_TRUE (location_wrapper_p (wrapped_parm));
> +  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
> +
> +  /* Verify that lvalue_kind of std::move on a parm isn't
> +     affected by location wrappers.  */
> +  tree rvalue_ref_of_parm = move (parm);
> +  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
> +  tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
> +  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
> +}
> +
> +/* Run all of the selftests within this file.  */
> +
> +void
> +cp_tree_c_tests ()
> +{
> +  test_lvalue_kind ();
> +}
> +
> +} // namespace selftest
> +
> +#endif /* #if CHECKING_P */
> +
> +
>  #include "gt-cp-tree.h"
> diff --git a/gcc/tree.c b/gcc/tree.c
> index b72f963..517f4a4 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -13811,8 +13811,8 @@ set_source_range (tree expr, source_range src_range)
>  /* Return EXPR, potentially wrapped with a node expression LOC,
>     if !CAN_HAVE_LOCATION_P (expr).
>
> -   NON_LVALUE_EXPR is used for wrapping constants.
> -   VIEW_CONVERT_EXPR is used for wrapping non-constants.
> +   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.  */
>
> @@ -13834,7 +13834,7 @@ maybe_wrap_with_location (tree expr, location_t loc)
>    if (EXCEPTIONAL_CLASS_P (expr))
>      return expr;
>
> -  if (CONSTANT_CLASS_P (expr))
> +  if (CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
>      return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (expr), expr);
>    else
>      return build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
> @@ -14238,6 +14238,18 @@ test_location_wrappers ()
>    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"),
> @@ -14258,6 +14270,7 @@ test_location_wrappers ()
>
>    /* Verify that STRIP_NOPS removes wrappers.  */
>    check_strip_nops (wrapped_int_cst, int_cst);
> +  check_strip_nops (wrapped_string_cst, string_cst);
>    check_strip_nops (wrapped_int_var, int_var);
>
>    /* operand_equal_p should "see through" any location wrapper...  */
> diff --git a/gcc/tree.h b/gcc/tree.h
> index de085ca..7f4ea5e 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -3679,8 +3679,8 @@ location_wrapper_p (const_tree exp)
>    /* A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and the
>       same type as its operand.
>
> -     NON_LVALUE_EXPR is used for wrapping constants.
> -     VIEW_CONVERT_EXPR is used for wrapping non-constants.
> +     NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
> +     VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST.
>
>       A subtlety is that we may have to test whether we have the correct
>       TREE_CODE for the wrapped TREE_CODE.  Otherwise, e.g. the C++ expression:
> --
> 1.8.5.3
>

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

* [v3 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-21  5:03                   ` Jason Merrill
@ 2017-12-22 19:07                     ` David Malcolm
  2018-01-05 17:35                       ` PING " David Malcolm
  2018-01-05 20:21                       ` Jason Merrill
  0 siblings, 2 replies; 111+ messages in thread
From: David Malcolm @ 2017-12-22 19:07 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Thu, 2017-12-21 at 00:00 -0500, Jason Merrill wrote:
> On Wed, Dec 20, 2017 at 12:33 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
> > > On 12/17/2017 11:29 AM, David Malcolm wrote:
> > > > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> > > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > > > > > +
> > > > > >       if (VAR_P (format_tree))
> > > > > >         {
> > > > > >           /* Pull out a constant value if the front end
> > > > > > didn't.  */
> > > > > 
> > > > > It seems like we want fold_for_warn here instead of the
> > > > > special
> > > > > variable
> > > > > handling.  That probably makes sense for the other places you
> > > > > change in
> > > > > this patch, too.
> > > > 
> > > > Here's an updated version of the patch which uses
> > > > fold_for_warn,
> > > > rather than STRIP_ANY_LOCATION_WRAPPER.
> > > > 
> > > > In one place it was necessary to add a STRIP_NOPS, since the
> > > > fold_for_warn can add a cast around a:
> > > >    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> > > >      STRING_CST)
> > > > turning it into a:
> > > >    NOP_EXPR<POINTER_TYPE(char))> (
> > > >      ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> > > >        STRING_CST))
> > > 
> > > Hmm, that seems like a bug.  fold_for_warn shouldn't change the
> > > type of
> > > the result.
> > 
> > In a similar vein, is the result of decl_constant_value (decl)
> > required
> > to be the same type as that of the decl?
> > 
> > What's happening for this testcase (g++.dg/warn/Wformat-1.C) is
> > that we
> > have a VAR_DECL with a DECL_INITIAL, but the types of the two don't
> > quite match up.
> > 
> > decl_constant_value returns an unshare_expr clone of the
> > DECL_INITIAL,
> > and this is what's returned from fold_for_warn.
> > 
> > Am I right in thinking
> > 
> > (a) that the bug here is that a DECL_INITIAL ought to have the same
> >     type as its decl, and so there's a missing cast where that gets
> >     set up, or
> 
> This seems right.
> 
> > (b) should decl_constant_value handle such cases, and introduce a
> > cast
> >     if it uncovers them?
> 
> decl_constant_value should probably assert that the types match
> closely enough.

Thanks.

You describe the types needing to match "closely enough" (as opposed
to *exactly*), and that may be the key here: what I didn't say in my
message above is that the decl is "const" whereas the value isn't.

To identify where a DECL_INITIAL can have a different type to its decl
(and thus fold_for_warn "changing type"), I tried adding this assertion:

  --- a/gcc/cp/typeck2.c
  +++ b/gcc/cp/typeck2.c
  @@ -857,6 +857,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
     /* If the value is a constant, just put it in DECL_INITIAL.  If DECL
        is an automatic variable, the middle end will turn this into a
        dynamic initialization later.  */
  +  gcc_assert (TREE_TYPE (value) == TREE_TYPE (decl));
     DECL_INITIAL (decl) = value;
     return NULL_TREE;
   }

The assertion fires when a "const" decl is initialized with a value of
a non-const type; e.g. in g++.dg/warn/Wformat-1.C:

  const char *const msg = "abc";

but I can also reproduce it with:

  const int i = 42;

What happens is that the type of the decl has the "readonly_flag" set,
whereas the type of the value has that flag clear.

For the string case, convert_for_initialization finishes here:

8894	  return convert_for_assignment (type, rhs, errtype, fndecl, parmnum,
8895					 complain, flags);

and convert_for_assignment finishes by calling:

8801	  return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
8802						    complain, flags);

The "strip_top_quals" in that latter call strips away the
"readonly_flag" from type (the decl's type), giving the type of the
rhs, and hence this does nothing.

So we end up with a decl of type
  const char * const
being initialized with a value of type
  const char *
(or a decl of type "const int" being initialized with a value of
type "int").

So the types are slightly inconsistent (const vs non-const), but given
your wording of types needing to match "closely enough" it's not clear
to me that it's a problem - if I'm reading things right, it's coming from
that strip_top_quals in the implicit conversion in convert_for_assignment.

This also happens with a pristine build of trunk.

Rather than attempting to change decl_constant_value or the folding code,
the following patch simply updates the:

  if (VAR_P (format_tree))
    {
      /* Pull out a constant value if the front end didn't.  */
      format_tree = decl_constant_value (format_tree);
      STRIP_NOPS (format_tree);
    }

that you added in r219964 to fix PR c++/64629 to instead be:

  format_tree = fold_for_warn (format_tree);
  STRIP_NOPS (format_tree);

and adds a little test coverage for the pointer addition case.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
part of the kit.

OK for trunk once the rest of the kit is approved?


gcc/c-family/ChangeLog:
	* c-format.c (check_format_arg): Convert VAR_P check to a
	fold_for_warn.

gcc/testsuite/ChangeLog:
	* g++.dg/warn/Wformat-1.C: Add tests of pointer arithmetic on
	format strings.
---
 gcc/c-family/c-format.c               | 10 ++++------
 gcc/testsuite/g++.dg/warn/Wformat-1.C |  2 ++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 164d035..1fcac2f 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,12 +1536,10 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
-  if (VAR_P (format_tree))
-    {
-      /* Pull out a constant value if the front end didn't.  */
-      format_tree = decl_constant_value (format_tree);
-      STRIP_NOPS (format_tree);
-    }
+  /* Pull out a constant value if the front end didn't, and handle location
+     wrappers.  */
+  format_tree = fold_for_warn (format_tree);
+  STRIP_NOPS (format_tree);
 
   if (integer_zerop (format_tree))
     {
diff --git a/gcc/testsuite/g++.dg/warn/Wformat-1.C b/gcc/testsuite/g++.dg/warn/Wformat-1.C
index 6094a9c..f2e772a 100644
--- a/gcc/testsuite/g++.dg/warn/Wformat-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wformat-1.C
@@ -7,4 +7,6 @@ foo (void)
 {
   const char *const msg = "abc";
   bar (1, msg);
+  bar (1, msg + 1);
+  bar (1, 1 + msg);
 }
-- 
1.8.5.3

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

* [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-15 18:59                   ` Jason Merrill
  2017-12-15 22:49                     ` David Malcolm
@ 2017-12-29 17:03                     ` David Malcolm
  2018-01-05 20:29                       ` Jason Merrill
  1 sibling, 1 reply; 111+ messages in thread
From: David Malcolm @ 2017-12-29 17:03 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Fri, 2017-12-15 at 13:58 -0500, Jason Merrill wrote:
> On Fri, Dec 15, 2017 at 11:35 AM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
> > > On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> > > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > > The initial version of the patch kit added location wrapper
> > > > > > nodes
> > > > > > around constants and uses-of-declarations, along with some
> > > > > > other
> > > > > > places in the parser (typeid, alignof, sizeof, offsetof).
> > > > > > 
> > > > > > This version takes a much more minimal approach: it only
> > > > > > adds
> > > > > > location wrapper nodes around the arguments at callsites,
> > > > > > thus
> > > > > > not adding wrapper nodes around uses of constants and decls
> > > > > > in
> > > > > > other
> > > > > > locations.
> > > > > > 
> > > > > > It keeps them for the other places in the parser (typeid,
> > > > > > alignof,
> > > > > > sizeof, offsetof).
> > > > > > 
> > > > > > In addition, for now, each site that adds wrapper nodes is
> > > > > > guarded
> > > > > > with !processing_template_decl, suppressing the creation of
> > > > > > wrapper
> > > > > > nodes when processing template declarations.  This is to
> > > > > > simplify
> > > > > > the patch kit so that we don't have to support wrapper
> > > > > > nodes
> > > > > > during
> > > > > > template expansion.
> > > > > 
> > > > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR
> > > > > and
> > > > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> > > > > 
> > > > > Jason
> > > > 
> > > > I don't know if it's "easy"; it's at least non-trivial.
> > > > 
> > > > I attempted to support them in the obvious way by adding the
> > > > two
> > > > codes
> > > > to the switch statement tsubst_copy, reusing the case used by
> > > > NOP_EXPR
> > > > and others, but ran into a issue when dealing with template
> > > > parameter
> > > > packs.
> > > > Attached is the reproducer I've been testing with (minimized
> > > > using
> > > > "delta" from a stdlib reproducer); my code was failing with:
> > > > 
> > > > ../../src/cp-stdlib.ii: In instantiation of ‘struct
> > > > allocator_traits<allocator<char> >’:
> > > > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
> > > > __alloc_traits<allocator<char>, char>’
> > > > ../../src/cp-stdlib.ii:43:75:   required from ‘class
> > > > basic_string<char, allocator<char> >’
> > > > ../../src/cp-stdlib.ii:47:58:   required from here
> > > > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
> > > > ‘type_pack_expansion’ in template
> > > >      -> decltype(_S_construct(__a, __p,
> > > > forward<_Args>(__args)...))  {   }
> > > >                                                        ^~~~~~
> > > > 
> > > > The issue is that normally "__args" would be a PARM_DECL of
> > > > type
> > > > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
> > > > adding a
> > > > wrapper node we now have a VIEW_CONVERT_EXPR of the same type
> > > > i.e.
> > > > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
> > > > 
> > > > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is
> > > > reached
> > > > first,
> > > > and it attempts to substitute the type TYPE_PACK_EXPANSION,
> > > > which
> > > > leads
> > > > to the "sorry".
> > > > 
> > > > If I understand things right, during substitution, only
> > > > tsubst_decl
> > > > on
> > > > PARM_DECL can handle nodes with type with code
> > > > TYPE_PACK_EXPANSION.
> > > > 
> > > > The simplest approach seems to be to not create wrapper nodes
> > > > for
> > > > decls
> > > > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
> > > 
> > > That does seem simplest.
> > > 
> > > > Alternatively I can handle TYPE_PACK_EXPANSION for
> > > > VIEW_CONVERT_EXPR in
> > > > tsubst by remapping the type to that of what they wrap after
> > > > substitution; doing so also fixes the issue.
> > > 
> > > This will be more correct.  For the wrappers you don't need all
> > > the
> > > handling that we currently have for NOP_EXPR and such; since we
> > > know
> > > they don't change the type, we can substitute what they wrap, and
> > > then
> > > rewrap the result.
> > 
> > (nods; I have this working)
> > 
> > I've been debugging the other issues that I ran into when removing
> > the
> > "!processing_template_decl" filter on making wrapper nodes (ICEs
> > and
> > other errors on valid code).  They turn out to relate to wrappers
> > around decls of type TEMPLATE_TYPE_PARM; having these wrappers
> > leads to
> > such VIEW_CONVERT_EXPRs turning up in unexpected places.
> 
> Hmm, that's odd.  What kind of decls?  A variable which happens to
> have a template parameter for a type shouldn't be a problem.

Sorry.  This turned out to be a bug in my implementation of tsubst_*.

> > I could try to track all those places down, but it seems much
> > simpler
> > to just add an exclusion to adding wrapper nodes around decls of
> > type
> > TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++
> > stdlib
> > work again.  Does that sound reasonable?
> 
> Jason

Here's an updated version of the patch which fixes the issues above.

As before, it adds locations wrapper nodes around the arguments at
callsites, along with some other places in the C++ parser (typeid,
alignof, sizeof, offsetof).

It removes the guard on !processing_template_decl when creating
wrapper nodes that was present in the earlier version of the
patch.  Doing so required fixes for handling location wrapper nodes
to tsubst_copy, tsubst_copy_and_build, build_non_dependent_expr, and
to name-mangling.

One issue I ran into was that fold_for_warn doesn't eliminate
location wrappers when processing_template_decl, leading to
failures of the template-based cases in
g++.dg/warn/Wmemset-transposed-args-1.C.

This is due to the early bailout when processing_template_decl
within cp_fold:

2078	  if (processing_template_decl
2079	      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
2080	    return x;

which dates back to the merger of the C++ delayed folding branch.

I've fixed that in this version of the patch by removing that
"processing_template_decl ||" condition from that cp_fold early
bailout.  It's not clear to me that that's the right fix - but if
we're going to add location wrapper nodes for such templated code,
presumably we need some way to look through the wrappers for these
warnings, and it seems like you favor fold_for_warn as the way to
do this.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

OK for trunk in conjunction with the rest of the kit?

BTW, apart from this patch, the only other part of the kit that still
needs review is:
 
  "[v3 of PATCH 13/14] c-format.c: handle location wrappers"
     https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01494.html

Thanks
Dave

gcc/cp/ChangeLog:
	* cp-gimplify.c (cp_fold): Remove the early bailout when
	processing_template_decl.
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_pt_c_tests.
	* cp-tree.h (selftest::cp_pt_c_tests): New decl.
	* mangle.c (write_expression): Skip location wrapper nodes.
	* parser.c (cp_parser_postfix_expression): Call
	maybe_add_location_wrapper on the result for RID_TYPEID. Pass true
	for new "wrap_locations_p" param of
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.
	* pt.c: Include "selftest.h".
	(tsubst_copy): Handle location wrappers.
	(tsubst_copy_and_build): Likewise.
	(build_non_dependent_expr): Likewise.
	(selftest::test_build_non_dependent_expr): New function.
	(selftest::cp_pt_c_tests): New function.
---
 gcc/cp/cp-gimplify.c |  5 ++--
 gcc/cp/cp-lang.c     |  1 +
 gcc/cp/cp-tree.h     | 10 ++++++++
 gcc/cp/mangle.c      |  1 +
 gcc/cp/parser.c      | 25 +++++++++++++++-----
 gcc/cp/pt.c          | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 97 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 934f674..9bdaafc 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2058,7 +2058,7 @@ clear_fold_cache (void)
 
 /*  This function tries to fold an expression X.
     To avoid combinatorial explosion, folding results are kept in fold_cache.
-    If we are processing a template or X is invalid, we don't fold at all.
+    If X is invalid, we don't fold at all.
     For performance reasons we don't cache expressions representing a
     declaration or constant.
     Function returns X or its folded variant.  */
@@ -2075,8 +2075,7 @@ cp_fold (tree x)
   if (!x || x == error_mark_node)
     return x;
 
-  if (processing_template_decl
-      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
+  if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
     return x;
 
   /* Don't bother to cache DECLs or constants.  */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 805319a..2c53740 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,7 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_pt_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9879e16..43a4eab 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7451,6 +7451,16 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+#if CHECKING_P
+namespace selftest {
+  extern void run_cp_tests (void);
+
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_pt_c_tests ();
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 6d4e591..837796b 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2834,6 +2834,7 @@ write_expression (tree expr)
   /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
      argument is converted (via qualification conversions) to another type.  */
   while (CONVERT_EXPR_CODE_P (code)
+	 || location_wrapper_p (expr)
 	 /* Parentheses aren't mangled.  */
 	 || code == PAREN_EXPR
 	 || code == NON_LVALUE_EXPR)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 891f742..359572c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2047,7 +2047,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6831,6 +6832,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7088,7 +7090,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7621,6 +7624,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7640,7 +7647,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7663,12 +7671,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7722,11 +7730,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -7992,6 +8003,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9831,6 +9843,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  expr = expr.maybe_add_location_wrapper ();
   return expr;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 252712e..2266e1d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "type-utils.h"
 #include "gimplify.h"
 #include "gcc-rich-location.h"
+#include "selftest.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -14928,6 +14929,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* Ordinary template template argument.  */
 	return t;
 
+    case VIEW_CONVERT_EXPR:
+    case NON_LVALUE_EXPR:
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case CONVERT_EXPR:
     case NOP_EXPR:
       {
+	if (location_wrapper_p (t))
+	  {
+	    /* Handle location wrappers by substituting the wrapped node
+	       first, *then* reusing the resulting type.  Doing the type
+	       first ensures that we handle template parameters and
+	       parameter pack expansions.  */
+	    tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	    return build1 (code, TREE_TYPE (op0), op0);
+	  }
 	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
 	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
 	return build1 (code, type, op0);
@@ -18282,6 +18294,14 @@ tsubst_copy_and_build (tree t,
     case REQUIRES_EXPR:
       RETURN (tsubst_requires_expr (t, args, complain, in_decl));
 
+    case VIEW_CONVERT_EXPR:
+    case NON_LVALUE_EXPR:
+      if (location_wrapper_p (t))
+	{
+	  RETURN (RECUR (TREE_OPERAND (t, 0)));
+	}
+      /* fallthrough.  */
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
       && !expanding_concept ())
     fold_non_dependent_expr (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* Preserve OVERLOADs; the functions must be available to resolve
      types.  */
   inner_expr = expr;
@@ -26601,4 +26623,46 @@ print_template_statistics (void)
 	   type_specializations->collisions ());
 }
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that build_non_dependent_expr () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_build_non_dependent_expr ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants, without and with location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (int_cst, build_non_dependent_expr (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (int_cst, build_non_dependent_expr (wrapped_int_cst));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (string_lit, build_non_dependent_expr (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (string_lit, build_non_dependent_expr (wrapped_string_lit));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_pt_c_tests ()
+{
+  test_build_non_dependent_expr ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
 #include "gt-cp-pt.h"
-- 
1.8.5.3

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

* PING Re: [v3 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-22 19:07                     ` [v3 " David Malcolm
@ 2018-01-05 17:35                       ` David Malcolm
  2018-01-05 17:48                         ` Joseph Myers
  2018-01-05 20:21                       ` Jason Merrill
  1 sibling, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-05 17:35 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

Ping:
  https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01494.html


(FWIW, the only other patch still needing review in the kit is:
  "[v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing
(minimal impl)"
     https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01594.html  )

On Fri, 2017-12-22 at 14:10 -0500, David Malcolm wrote:
> On Thu, 2017-12-21 at 00:00 -0500, Jason Merrill wrote:
> > On Wed, Dec 20, 2017 at 12:33 PM, David Malcolm <dmalcolm@redhat.co
> > m>
> > wrote:
> > > On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
> > > > On 12/17/2017 11:29 AM, David Malcolm wrote:
> > > > > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> > > > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > > > > > > +
> > > > > > >       if (VAR_P (format_tree))
> > > > > > >         {
> > > > > > >           /* Pull out a constant value if the front end
> > > > > > > didn't.  */
> > > > > > 
> > > > > > It seems like we want fold_for_warn here instead of the
> > > > > > special
> > > > > > variable
> > > > > > handling.  That probably makes sense for the other places
> > > > > > you
> > > > > > change in
> > > > > > this patch, too.
> > > > > 
> > > > > Here's an updated version of the patch which uses
> > > > > fold_for_warn,
> > > > > rather than STRIP_ANY_LOCATION_WRAPPER.
> > > > > 
> > > > > In one place it was necessary to add a STRIP_NOPS, since the
> > > > > fold_for_warn can add a cast around a:
> > > > >    ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> > > > >      STRING_CST)
> > > > > turning it into a:
> > > > >    NOP_EXPR<POINTER_TYPE(char))> (
> > > > >      ADDR_EXPR <POINTER_TYPE(ARRAY_TYPE(char))> (
> > > > >        STRING_CST))
> > > > 
> > > > Hmm, that seems like a bug.  fold_for_warn shouldn't change the
> > > > type of
> > > > the result.
> > > 
> > > In a similar vein, is the result of decl_constant_value (decl)
> > > required
> > > to be the same type as that of the decl?
> > > 
> > > What's happening for this testcase (g++.dg/warn/Wformat-1.C) is
> > > that we
> > > have a VAR_DECL with a DECL_INITIAL, but the types of the two
> > > don't
> > > quite match up.
> > > 
> > > decl_constant_value returns an unshare_expr clone of the
> > > DECL_INITIAL,
> > > and this is what's returned from fold_for_warn.
> > > 
> > > Am I right in thinking
> > > 
> > > (a) that the bug here is that a DECL_INITIAL ought to have the
> > > same
> > >     type as its decl, and so there's a missing cast where that
> > > gets
> > >     set up, or
> > 
> > This seems right.
> > 
> > > (b) should decl_constant_value handle such cases, and introduce a
> > > cast
> > >     if it uncovers them?
> > 
> > decl_constant_value should probably assert that the types match
> > closely enough.
> 
> Thanks.
> 
> You describe the types needing to match "closely enough" (as opposed
> to *exactly*), and that may be the key here: what I didn't say in my
> message above is that the decl is "const" whereas the value isn't.
> 
> To identify where a DECL_INITIAL can have a different type to its
> decl
> (and thus fold_for_warn "changing type"), I tried adding this
> assertion:
> 
>   --- a/gcc/cp/typeck2.c
>   +++ b/gcc/cp/typeck2.c
>   @@ -857,6 +857,7 @@ store_init_value (tree decl, tree init,
> vec<tree, va_gc>** cleanups, int flags)
>      /* If the value is a constant, just put it in DECL_INITIAL.  If
> DECL
>         is an automatic variable, the middle end will turn this into
> a
>         dynamic initialization later.  */
>   +  gcc_assert (TREE_TYPE (value) == TREE_TYPE (decl));
>      DECL_INITIAL (decl) = value;
>      return NULL_TREE;
>    }
> 
> The assertion fires when a "const" decl is initialized with a value
> of
> a non-const type; e.g. in g++.dg/warn/Wformat-1.C:
> 
>   const char *const msg = "abc";
> 
> but I can also reproduce it with:
> 
>   const int i = 42;
> 
> What happens is that the type of the decl has the "readonly_flag"
> set,
> whereas the type of the value has that flag clear.
> 
> For the string case, convert_for_initialization finishes here:
> 
> 8894	  return convert_for_assignment (type, rhs, errtype,
> fndecl, parmnum,
> 8895					 complain, flags);
> 
> and convert_for_assignment finishes by calling:
> 
> 8801	  return perform_implicit_conversion_flags
> (strip_top_quals (type), rhs,
> 8802						    complain,
> flags);
> 
> The "strip_top_quals" in that latter call strips away the
> "readonly_flag" from type (the decl's type), giving the type of the
> rhs, and hence this does nothing.
> 
> So we end up with a decl of type
>   const char * const
> being initialized with a value of type
>   const char *
> (or a decl of type "const int" being initialized with a value of
> type "int").
> 
> So the types are slightly inconsistent (const vs non-const), but
> given
> your wording of types needing to match "closely enough" it's not
> clear
> to me that it's a problem - if I'm reading things right, it's coming
> from
> that strip_top_quals in the implicit conversion in
> convert_for_assignment.
> 
> This also happens with a pristine build of trunk.
> 
> Rather than attempting to change decl_constant_value or the folding
> code,
> the following patch simply updates the:
> 
>   if (VAR_P (format_tree))
>     {
>       /* Pull out a constant value if the front end didn't.  */
>       format_tree = decl_constant_value (format_tree);
>       STRIP_NOPS (format_tree);
>     }
> 
> that you added in r219964 to fix PR c++/64629 to instead be:
> 
>   format_tree = fold_for_warn (format_tree);
>   STRIP_NOPS (format_tree);
> 
> and adds a little test coverage for the pointer addition case.
> 
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu, as
> part of the kit.
> 
> OK for trunk once the rest of the kit is approved?
> 
> 
> gcc/c-family/ChangeLog:
> 	* c-format.c (check_format_arg): Convert VAR_P check to a
> 	fold_for_warn.
> 
> gcc/testsuite/ChangeLog:
> 	* g++.dg/warn/Wformat-1.C: Add tests of pointer arithmetic on
> 	format strings.
> ---
>  gcc/c-family/c-format.c               | 10 ++++------
>  gcc/testsuite/g++.dg/warn/Wformat-1.C |  2 ++
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> index 164d035..1fcac2f 100644
> --- a/gcc/c-family/c-format.c
> +++ b/gcc/c-family/c-format.c
> @@ -1536,12 +1536,10 @@ check_format_arg (void *ctx, tree
> format_tree,
>  
>    location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree,
> input_location);
>  
> -  if (VAR_P (format_tree))
> -    {
> -      /* Pull out a constant value if the front end didn't.  */
> -      format_tree = decl_constant_value (format_tree);
> -      STRIP_NOPS (format_tree);
> -    }
> +  /* Pull out a constant value if the front end didn't, and handle
> location
> +     wrappers.  */
> +  format_tree = fold_for_warn (format_tree);
> +  STRIP_NOPS (format_tree);
>  
>    if (integer_zerop (format_tree))
>      {
> diff --git a/gcc/testsuite/g++.dg/warn/Wformat-1.C
> b/gcc/testsuite/g++.dg/warn/Wformat-1.C
> index 6094a9c..f2e772a 100644
> --- a/gcc/testsuite/g++.dg/warn/Wformat-1.C
> +++ b/gcc/testsuite/g++.dg/warn/Wformat-1.C
> @@ -7,4 +7,6 @@ foo (void)
>  {
>    const char *const msg = "abc";
>    bar (1, msg);
> +  bar (1, msg + 1);
> +  bar (1, 1 + msg);
>  }

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

* Re: PING Re: [v3 of PATCH 13/14] c-format.c: handle location wrappers
  2018-01-05 17:35                       ` PING " David Malcolm
@ 2018-01-05 17:48                         ` Joseph Myers
  0 siblings, 0 replies; 111+ messages in thread
From: Joseph Myers @ 2018-01-05 17:48 UTC (permalink / raw)
  To: David Malcolm
  Cc: Jason Merrill, Nathan Sidwell, Jakub Jelinek, Richard Biener,
	gcc-patches List

On Fri, 5 Jan 2018, David Malcolm wrote:

> Ping:
>   https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01494.html

OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [v3 of PATCH 13/14] c-format.c: handle location wrappers
  2017-12-22 19:07                     ` [v3 " David Malcolm
  2018-01-05 17:35                       ` PING " David Malcolm
@ 2018-01-05 20:21                       ` Jason Merrill
  1 sibling, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2018-01-05 20:21 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/22/2017 02:10 PM, David Malcolm wrote:
> You describe the types needing to match "closely enough" (as opposed
> to *exactly*), and that may be the key here: what I didn't say in my
> message above is that the decl is "const" whereas the value isn't.

Right, differences in top-level qualifiers don't matter.  A scalar 
prvalue can't be const.

Jason

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2017-12-29 17:03                     ` [v2 of PATCH " David Malcolm
@ 2018-01-05 20:29                       ` Jason Merrill
  2018-01-05 22:20                         ` David Malcolm
  2018-01-08 21:03                         ` David Malcolm
  0 siblings, 2 replies; 111+ messages in thread
From: Jason Merrill @ 2018-01-05 20:29 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 12/29/2017 12:06 PM, David Malcolm wrote:
> One issue I ran into was that fold_for_warn doesn't eliminate
> location wrappers when processing_template_decl, leading to
> failures of the template-based cases in
> g++.dg/warn/Wmemset-transposed-args-1.C.
> 
> This is due to the early bailout when processing_template_decl
> within cp_fold:
> 
> 2078	  if (processing_template_decl
> 2079	      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
> 2080	    return x;
> 
> which dates back to the merger of the C++ delayed folding branch.
> 
> I've fixed that in this version of the patch by removing that
> "processing_template_decl ||" condition from that cp_fold early
> bailout.

Hmm, that makes me nervous.  We might want to fold in templates when 
called from fold_for_warn, but not for other occurrences.  But I see 
that we check processing_template_decl in cp_fully_fold and in the call 
to cp_fold_function, so I guess this is fine.

> +    case VIEW_CONVERT_EXPR:
> +    case NON_LVALUE_EXPR:
>      case CAST_EXPR:
>      case REINTERPRET_CAST_EXPR:
>      case CONST_CAST_EXPR:
> @@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>      case CONVERT_EXPR:
>      case NOP_EXPR:
>        {
> +	if (location_wrapper_p (t))
> +	  {
> +	    /* Handle location wrappers by substituting the wrapped node
> +	       first, *then* reusing the resulting type.  Doing the type
> +	       first ensures that we handle template parameters and
> +	       parameter pack expansions.  */
> +	    tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
> +	    return build1 (code, TREE_TYPE (op0), op0);
> +	  }

I'd rather handle location wrappers separately, and abort if 
VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.

> @@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
>        && !expanding_concept ())
>      fold_non_dependent_expr (expr);
>  
> +  STRIP_ANY_LOCATION_WRAPPER (expr);

Why is this needed?

Jason

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-05 20:29                       ` Jason Merrill
@ 2018-01-05 22:20                         ` David Malcolm
  2018-01-08 17:10                           ` Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)) David Malcolm
  2018-01-08 21:48                           ` [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) Jason Merrill
  2018-01-08 21:03                         ` David Malcolm
  1 sibling, 2 replies; 111+ messages in thread
From: David Malcolm @ 2018-01-05 22:20 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
> On 12/29/2017 12:06 PM, David Malcolm wrote:
> > One issue I ran into was that fold_for_warn doesn't eliminate
> > location wrappers when processing_template_decl, leading to
> > failures of the template-based cases in
> > g++.dg/warn/Wmemset-transposed-args-1.C.
> > 
> > This is due to the early bailout when processing_template_decl
> > within cp_fold:
> > 
> > 2078	  if (processing_template_decl
> > 2079	      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE
> > (x) == error_mark_node)))
> > 2080	    return x;
> > 
> > which dates back to the merger of the C++ delayed folding branch.
> > 
> > I've fixed that in this version of the patch by removing that
> > "processing_template_decl ||" condition from that cp_fold early
> > bailout.
> 
> Hmm, that makes me nervous.  We might want to fold in templates when 
> called from fold_for_warn, but not for other occurrences.  But I see 
> that we check processing_template_decl in cp_fully_fold and in the
> call 
> to cp_fold_function, so I guess this is fine.

(I wondered if it would be possible to add a new flag to the various
fold* calls to request folding in templates, but given that the API is
partially shared with C doing so doesn't seem to make sense)

> > +    case VIEW_CONVERT_EXPR:
> > +    case NON_LVALUE_EXPR:
> >      case CAST_EXPR:
> >      case REINTERPRET_CAST_EXPR:
> >      case CONST_CAST_EXPR:
> > @@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args,
> > tsubst_flags_t complain, tree in_decl)
> >      case CONVERT_EXPR:
> >      case NOP_EXPR:
> >        {
> > +	if (location_wrapper_p (t))
> > +	  {
> > +	    /* Handle location wrappers by substituting the
> > wrapped node
> > +	       first, *then* reusing the resulting type.  Doing
> > the type
> > +	       first ensures that we handle template parameters
> > and
> > +	       parameter pack expansions.  */
> > +	    tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
> > complain, in_decl);
> > +	    return build1 (code, TREE_TYPE (op0), op0);
> > +	  }
> 
> I'd rather handle location wrappers separately, and abort if 
> VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.

OK.  I'm testing an updated version which does so.

> > @@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
> >        && !expanding_concept ())
> >      fold_non_dependent_expr (expr);
> >  
> > +  STRIP_ANY_LOCATION_WRAPPER (expr);
> 
> Why is this needed?

I added this to fix a failure:

template argument deduction/substitution failed:
note:   cannot convert ‘0’ (type ‘int’) to type ‘char**’

seen building the precompiled header, where build_non_dependent_expr
adds a NON_DEPENDENT_EXPR around a location wrapper around an
INTEGER_CST, whereas without location wrappers we'd just have an
INTEGER_CST.

build_non_dependent_expr performs various tests for exact TREE_CODEs,
special-casing constants; without the stripping these TREE_CODE tests
don't match when the constants have location wrappers, leading to the
failure.

Here are the gory details:

In file included from ./src/libstdc++-
v3/include/precompiled/extc++.h:82:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h: In member function ‘virtual
std::codecvt_base::result std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::do_unshift(std::codecvt<_InternT,
_ExternT, __gnu_cxx::__cxx11::encoding_state>::state_type&,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*&) const’:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:392:58: error: no matching
function for call to ‘__iconv_adaptor(size_t (&)(iconv_t, char**,
size_t*, char**, size_t*), void* const&, int, int, char**,
std::size_t*)’
                                           &__cto, &__tlen);
                                                          ^
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:301:5: note: candidate:
‘template<class _Tp> std::size_t std::__iconv_adaptor(std::size_t
(*)(iconv_t, _Tp, std::size_t*, char**, std::size_t*), iconv_t, char**,
std::size_t*, char**, std::size_t*)’
     __iconv_adaptor(size_t(*__func)(iconv_t, _Tp, size_t*, char**,
size_t*),
     ^~~~~~~~~~~~~~~
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:301:5: note:   template
argument deduction/substitution failed:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:392:58: note:   cannot convert
‘0’ (type ‘int’) to type ‘char**’
                                           &__cto, &__tlen);
                                                          ^



(gdb) call debug_tree (arg)
 <non_dependent_expr 0x7fffe7402820
    type <integer_type 0x7ffff0e4f5e8 int asm_written public type_6 SI
        size <integer_cst 0x7ffff0e520c0 constant 32>
        unit-size <integer_cst 0x7ffff0e520d8 constant 4>
        align:32 warn_if_not_align:0 symtab:-291372496 alias-set -1
canonical-type 0x7ffff0e4f5e8 precision:32 min <integer_cst
0x7ffff0e52078 -2147483648> max <integer_cst 0x7ffff0e52090 2147483647>
        pointer_to_this <pointer_type 0x7ffff0e57a80> reference_to_this
<reference_type 0x7fffee916e70>>
   
    arg:0 <non_lvalue_expr 0x7fffe7402720 type <integer_type
0x7ffff0e4f5e8 int>
        constant
        arg:0 <integer_cst 0x7ffff0e52210 constant 0>
        ./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:391:50 start: ./build/x86_64-
pc-linux-gnu/libstdc++-v3/include/ext/codecvt_specializations.h:391:50
finish: ./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:391:50>>


...when for a unpatched build we'd just have an INTEGER_CST.

Given the various TREE_CODE comparisons, using the
STRIP_ANY_LOCATION_WRAPPER macro seemed most appropriate; I put it
before the first TREE_CODE test.

I also added selftest::test_build_non_dependent_expr for this, to
verify that location wrappers don't affect the result of
build_non_dependent_expr (for integer constants and on string
literals).

Thanks
Dave

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

* Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-05 22:20                         ` David Malcolm
@ 2018-01-08 17:10                           ` David Malcolm
  2018-01-08 17:14                             ` Nathan Sidwell
  2018-01-08 21:48                           ` [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) Jason Merrill
  1 sibling, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-08 17:10 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2018-01-05 at 17:20 -0500, David Malcolm wrote:
> On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
> > On 12/29/2017 12:06 PM, David Malcolm wrote:
> > > One issue I ran into was that fold_for_warn doesn't eliminate
> > > location wrappers when processing_template_decl, leading to
> > > failures of the template-based cases in
> > > g++.dg/warn/Wmemset-transposed-args-1.C.
> > > 
> > > This is due to the early bailout when processing_template_decl
> > > within cp_fold:
> > > 
> > > 2078	  if (processing_template_decl
> > > 2079	      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE
> > > (x) == error_mark_node)))
> > > 2080	    return x;
> > > 
> > > which dates back to the merger of the C++ delayed folding branch.
> > > 
> > > I've fixed that in this version of the patch by removing that
> > > "processing_template_decl ||" condition from that cp_fold early
> > > bailout.
> > 
> > Hmm, that makes me nervous.  We might want to fold in templates
> > when 
> > called from fold_for_warn, but not for other occurrences.  But I
> > see 
> > that we check processing_template_decl in cp_fully_fold and in the
> > call 
> > to cp_fold_function, so I guess this is fine.
> 
> (I wondered if it would be possible to add a new flag to the various
> fold* calls to request folding in templates, but given that the API
> is
> partially shared with C doing so doesn't seem to make sense)
> 
> > > +    case VIEW_CONVERT_EXPR:
> > > +    case NON_LVALUE_EXPR:
> > >      case CAST_EXPR:
> > >      case REINTERPRET_CAST_EXPR:
> > >      case CONST_CAST_EXPR:
> > > @@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args,
> > > tsubst_flags_t complain, tree in_decl)
> > >      case CONVERT_EXPR:
> > >      case NOP_EXPR:
> > >        {
> > > +	if (location_wrapper_p (t))
> > > +	  {
> > > +	    /* Handle location wrappers by substituting the
> > > wrapped node
> > > +	       first, *then* reusing the resulting type.  Doing
> > > the type
> > > +	       first ensures that we handle template parameters
> > > and
> > > +	       parameter pack expansions.  */
> > > +	    tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
> > > complain, in_decl);
> > > +	    return build1 (code, TREE_TYPE (op0), op0);
> > > +	  }
> > 
> > I'd rather handle location wrappers separately, and abort if 
> > VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.
> 
> OK.  I'm testing an updated version which does so.

Doing so uncovered an issue which I'm not sure how to resolve: it's
possible for a decl to change type during parsing, after location
wrappers may have been created, which changes location_wrapper_p on
those wrappers from true to false.

Here's the most minimal reproducer I've generated so far:

     1  template<typename _CharT>
     2  struct basic_string {
     3    static const _CharT _S_terminal;
     4    static void assign(const _CharT& __c2);
     5    void _M_set_length_and_sharable() {
     6      assign(_S_terminal);
     7    }
     8  };
     9
    10  template<typename _CharT>
    11  const _CharT basic_string<_CharT>::_S_terminal = _CharT();
    12
    13  void getline(basic_string<char>& __str) {
    14    __str._M_set_length_and_sharable();
    15  }

Asserting that the only VIEW_CONVERT_EXPR or NON_LVALUE_EXPR seen in
tsubst_copy and tsubst_copy_and_build are location_wrapper_p leads to
an ICE on the above code.

What's happening is as follows.  First, in the call:

     6      assign(_S_terminal);
                   ^~~~~~~~~~~

the VAR_DECL "_S_terminal" gains a VIEW_CONVERT_EXPR location wrapper
node to express the underline shown above.

Later, during parsing of this init-declarator:

    10  template<typename _CharT>
    11  const _CharT basic_string<_CharT>::_S_terminal = _CharT();
                                           ^~~~~~~~~~~


...cp_parser_init_declarator calls start_decl, which calls
duplicate_decls, merging the "_S_terminal" seen here:

     1  template<typename _CharT>
     2  struct basic_string {
     3    static const _CharT _S_terminal;
                              ^~~~~~~~~~~

with that seen here:

    10  template<typename _CharT>
    11  const _CharT basic_string<_CharT>::_S_terminal = _CharT();
                                            ^~~~~~~~~~~

Both "_S_terminal" VAR_DECLs have a "_CharT" TEMPLATE_TYPE_PARM, but
these types are different tree nodes.

Hence the type of the first VAR_DECL changes in duplicate_decls here:

2152	      TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;

...changing type to the TEMPLATE_TYPE_PARM of the second VAR_DECL.

At this point, the location wrapper node at the callsite still has the
*old* type, and hence location_wrapper_p (wrapper) changes from true to
false, as its type no longer matches that of the decl it's wrapping.

Hence my rewritten code in tsubst_copy_and_build fails the assertion
here:

18306	    case VIEW_CONVERT_EXPR:
18307	    case NON_LVALUE_EXPR:
18308	      gcc_assert (location_wrapper_p (t));
18309	      RETURN (RECUR (TREE_OPERAND (t, 0)));

Assuming I'm correctly understanding the above, I'm not sure what the
best solution is.

Some ideas:

* accept that this is a rare case, and either:
  * don't assert, or
  * also allow nodes here that are "nearly" location wrappers (i.e. of
type TEMPLATE_TYPE_PARM)

* some kind of fixup of location wrapper node types when changing the
type of a decl (ugh)

* don't add location wrappers if processing a template

* introduce a new tree node for location wrappers (gah)

* something I haven't thought of

Thoughts?  Thanks
Dave

[...snipped discussion of the other up-thread issue, relating
build_non_dependent_expr...]

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

* Re: Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-08 17:10                           ` Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)) David Malcolm
@ 2018-01-08 17:14                             ` Nathan Sidwell
  2018-01-08 17:18                               ` Jakub Jelinek
  0 siblings, 1 reply; 111+ messages in thread
From: Nathan Sidwell @ 2018-01-08 17:14 UTC (permalink / raw)
  To: David Malcolm, Jason Merrill
  Cc: Jakub Jelinek, Richard Biener, gcc-patches List

On 01/08/2018 12:02 PM, David Malcolm wrote:
> On Fri, 2018-01-05 at 17:20 -0500, David Malcolm wrote:

> Doing so uncovered an issue which I'm not sure how to resolve: it's
> possible for a decl to change type during parsing, after location
> wrappers may have been created, which changes location_wrapper_p on
> those wrappers from true to false.

> Asserting that the only VIEW_CONVERT_EXPR or NON_LVALUE_EXPR seen in
> tsubst_copy and tsubst_copy_and_build are location_wrapper_p leads to
> an ICE on the above code.
> 
> What's happening is as follows.  First, in the call:
> 
>       6      assign(_S_terminal);
>                     ^~~~~~~~~~~
> 
> the VAR_DECL "_S_terminal" gains a VIEW_CONVERT_EXPR location wrapper
> node to express the underline shown above.
> 
> Later, during parsing of this init-declarator:
> 
>      10  template<typename _CharT>
>      11  const _CharT basic_string<_CharT>::_S_terminal = _CharT();
>                                             ^~~~~~~~~~~
> 
> 
> ...cp_parser_init_declarator calls start_decl, which calls
> duplicate_decls, merging the "_S_terminal" seen here:
...
> Both "_S_terminal" VAR_DECLs have a "_CharT" TEMPLATE_TYPE_PARM, but
> these types are different tree nodes.

correct. they are not EQ but are EQUAL (same_type_p will be true).

> Hence the type of the first VAR_DECL changes in duplicate_decls here:
> 
> 2152	      TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
> 
> ...changing type to the TEMPLATE_TYPE_PARM of the second VAR_DECL.

> 18306	    case VIEW_CONVERT_EXPR:
> 18307	    case NON_LVALUE_EXPR:
> 18308	      gcc_assert (location_wrapper_p (t));
> 18309	      RETURN (RECUR (TREE_OPERAND (t, 0)));
> 
> Assuming I'm correctly understanding the above, I'm not sure what the
> best solution is.
> 
> Some ideas:

> * don't add location wrappers if processing a template
> 
> * introduce a new tree node for location wrappers (gah)
> 
> * something I haven't thought of

Add a flag on the VIEW_CONVERT/NON_LVALUE expr explicitly noting its 
wrapperness (rather than infer it from TREE_TYPE == TREE_TYPE 
(TREE_OPERAND)).  TREE_LANG_FLAG_0 looks available?

nathan


-- 
Nathan Sidwell

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

* Re: Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-08 17:14                             ` Nathan Sidwell
@ 2018-01-08 17:18                               ` Jakub Jelinek
  2018-01-08 17:28                                 ` Nathan Sidwell
  0 siblings, 1 reply; 111+ messages in thread
From: Jakub Jelinek @ 2018-01-08 17:18 UTC (permalink / raw)
  To: Nathan Sidwell
  Cc: David Malcolm, Jason Merrill, Richard Biener, gcc-patches List

On Mon, Jan 08, 2018 at 12:10:50PM -0500, Nathan Sidwell wrote:
> > Both "_S_terminal" VAR_DECLs have a "_CharT" TEMPLATE_TYPE_PARM, but
> > these types are different tree nodes.
> 
> correct. they are not EQ but are EQUAL (same_type_p will be true).

So perhaps location_wrapper_p could use that instead of pointer comparison.
Though it would be expensive.

> > Some ideas:
> 
> > * don't add location wrappers if processing a template
> > 
> > * introduce a new tree node for location wrappers (gah)
> > 
> > * something I haven't thought of
> 
> Add a flag on the VIEW_CONVERT/NON_LVALUE expr explicitly noting its
> wrapperness (rather than infer it from TREE_TYPE == TREE_TYPE
> (TREE_OPERAND)).  TREE_LANG_FLAG_0 looks available?

Yeah, I think most if not all lang flags are still available for those two
tree codes and checking that should be quite cheap.

	Jakub

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

* Re: Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-08 17:18                               ` Jakub Jelinek
@ 2018-01-08 17:28                                 ` Nathan Sidwell
  2018-01-08 18:08                                   ` David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Nathan Sidwell @ 2018-01-08 17:28 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: David Malcolm, Jason Merrill, Richard Biener, gcc-patches List

On 01/08/2018 12:14 PM, Jakub Jelinek wrote:
> On Mon, Jan 08, 2018 at 12:10:50PM -0500, Nathan Sidwell wrote:
>>> Both "_S_terminal" VAR_DECLs have a "_CharT" TEMPLATE_TYPE_PARM, but
>>> these types are different tree nodes.
>>
>> correct. they are not EQ but are EQUAL (same_type_p will be true).
> 
> So perhaps location_wrapper_p could use that instead of pointer comparison.
> Though it would be expensive.

If TYPE_STRUCTURAL_COMPARISON_P (or however it's spelt) is true, it'll 
be expensive.  Otherwise it's a function call, a couple of indirections 
and a pointer compare.  But still more expensive than ...

>> Add a flag on the VIEW_CONVERT/NON_LVALUE expr explicitly noting its
>> wrapperness (rather than infer it from TREE_TYPE == TREE_TYPE
>> (TREE_OPERAND)).  TREE_LANG_FLAG_0 looks available?
> 
> Yeah, I think most if not all lang flags are still available for those two
> tree codes and checking that should be quite cheap.

... a bit test on the node itself.

location_wrapper_p could contain something like
   bool result = TREE_LANG_FLAG_$FOO (t);
   gcc_checking_assert (result == same_type_p (TREE_TYPE (t), TREE_TYPE 
(TREE_OPERAND (t, 0)));
   return result;

for the paranoid.

nathan
-- 
Nathan Sidwell

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

* Re: Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-08 17:28                                 ` Nathan Sidwell
@ 2018-01-08 18:08                                   ` David Malcolm
  2018-01-08 18:23                                     ` Jakub Jelinek
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-08 18:08 UTC (permalink / raw)
  To: Nathan Sidwell, Jakub Jelinek
  Cc: Jason Merrill, Richard Biener, gcc-patches List

On Mon, 2018-01-08 at 12:25 -0500, Nathan Sidwell wrote:
> On 01/08/2018 12:14 PM, Jakub Jelinek wrote:
> > On Mon, Jan 08, 2018 at 12:10:50PM -0500, Nathan Sidwell wrote:
> > > > Both "_S_terminal" VAR_DECLs have a "_CharT"
> > > > TEMPLATE_TYPE_PARM, but
> > > > these types are different tree nodes.
> > > 
> > > correct. they are not EQ but are EQUAL (same_type_p will be
> > > true).
> > 
> > So perhaps location_wrapper_p could use that instead of pointer
> > comparison.
> > Though it would be expensive.
> 
> If TYPE_STRUCTURAL_COMPARISON_P (or however it's spelt) is true,
> it'll 
> be expensive.  Otherwise it's a function call, a couple of
> indirections 
> and a pointer compare.  But still more expensive than ...
> 
> > > Add a flag on the VIEW_CONVERT/NON_LVALUE expr explicitly noting
> > > its
> > > wrapperness (rather than infer it from TREE_TYPE == TREE_TYPE
> > > (TREE_OPERAND)).  TREE_LANG_FLAG_0 looks available?
> > 
> > Yeah, I think most if not all lang flags are still available for
> > those two
> > tree codes and checking that should be quite cheap.
> 
> ... a bit test on the node itself.
> 
> location_wrapper_p could contain something like
>    bool result = TREE_LANG_FLAG_$FOO (t);
>    gcc_checking_assert (result == same_type_p (TREE_TYPE (t),
> TREE_TYPE 
> (TREE_OPERAND (t, 0)));
>    return result;
> 
> for the paranoid.
> 
> nathan

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).

Dave

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

* Re: Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl))
  2018-01-08 18:08                                   ` David Malcolm
@ 2018-01-08 18:23                                     ` Jakub Jelinek
  2018-01-09 11:34                                       ` [PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jakub Jelinek @ 2018-01-08 18:23 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jason Merrill, Richard Biener, gcc-patches List

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

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-05 20:29                       ` Jason Merrill
  2018-01-05 22:20                         ` David Malcolm
@ 2018-01-08 21:03                         ` David Malcolm
  2018-01-08 21:59                           ` Jason Merrill
  1 sibling, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-08 21:03 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
> On 12/29/2017 12:06 PM, David Malcolm wrote:
> > One issue I ran into was that fold_for_warn doesn't eliminate
> > location wrappers when processing_template_decl, leading to
> > failures of the template-based cases in
> > g++.dg/warn/Wmemset-transposed-args-1.C.
> > 
> > This is due to the early bailout when processing_template_decl
> > within cp_fold:
> > 
> > 2078	  if (processing_template_decl
> > 2079	      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE
> > (x) == error_mark_node)))
> > 2080	    return x;
> > 
> > which dates back to the merger of the C++ delayed folding branch.
> > 
> > I've fixed that in this version of the patch by removing that
> > "processing_template_decl ||" condition from that cp_fold early
> > bailout.
> 
> Hmm, that makes me nervous.  We might want to fold in templates when 
> called from fold_for_warn, but not for other occurrences.  But I see 
> that we check processing_template_decl in cp_fully_fold and in the
> call 
> to cp_fold_function, so I guess this is fine.
> 
> > +    case VIEW_CONVERT_EXPR:
> > +    case NON_LVALUE_EXPR:
> >      case CAST_EXPR:
> >      case REINTERPRET_CAST_EXPR:
> >      case CONST_CAST_EXPR:
> > @@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args,
> > tsubst_flags_t complain, tree in_decl)
> >      case CONVERT_EXPR:
> >      case NOP_EXPR:
> >        {
> > +	if (location_wrapper_p (t))
> > +	  {
> > +	    /* Handle location wrappers by substituting the
> > wrapped node
> > +	       first, *then* reusing the resulting type.  Doing
> > the type
> > +	       first ensures that we handle template parameters
> > and
> > +	       parameter pack expansions.  */
> > +	    tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
> > complain, in_decl);
> > +	    return build1 (code, TREE_TYPE (op0), op0);
> > +	  }
> 
> I'd rather handle location wrappers separately, and abort if 
> VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.

Once I fixed the issue with location_wrapper_p with decls changing
type, it turns out that trunk is already passing VIEW_CONVERT_EXPR to
tsubst_copy_and_build for non-wrapper nodes (and from there to
tsubst_copy), where the default case currently handles them.  Adding an
assert turns this into an ICE.

g++.dg/delayedfold/builtin1.C is the only instance of it I found in our
test suite, where it's used here:

class RegionLock {
  template <unsigned long> void m_fn1();
  int spinlock;
} acquire_zero;
int acquire_one;
template <unsigned long> void RegionLock::m_fn1() {
  __atomic_compare_exchange(&spinlock, &acquire_zero, &acquire_one, false, 2, 2);
                                       ^~~~~~~~~~~~~
}

(gdb) call debug_tree (t)
 <view_convert_expr 0x7ffff1a15b40
    type <pointer_type 0x7ffff18d93f0
        type <integer_type 0x7ffff18c9690 unsigned int public unsigned
type_6 SI
            size <integer_cst 0x7ffff18cc0c0 constant 32>
            unit-size <integer_cst 0x7ffff18cc0d8 constant 4>
            align:32 warn_if_not_align:0 symtab:0 alias-set -1
canonical-type 0x7ffff18c9690 precision:32 min <integer_cst
0x7ffff18cc0f0 0> max <integer_cst 0x7ffff18cc0a8 4294967295>
            pointer_to_this <pointer_type 0x7ffff18d93f0>>
        unsigned type_6 DI
        size <integer_cst 0x7ffff18ace70 constant 64>
        unit-size <integer_cst 0x7ffff18ace88 constant 8>
        align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-
type 0x7ffff18d93f0>
   
    arg:0 <non_dependent_expr 0x7ffff1a15aa0
        type <pointer_type 0x7ffff1a18150 type <record_type
0x7ffff1a039d8 RegionLock>
            unsigned type_6 DI size <integer_cst 0x7ffff18ace70 64>
unit-size <integer_cst 0x7ffff18ace88 8>
            align:64 warn_if_not_align:0 symtab:0 alias-set -1
canonical-type 0x7ffff1a18150>
       
        arg:0 <addr_expr 0x7ffff1a159e0 type <pointer_type
0x7ffff1a18150>
            arg:0 <var_decl 0x7ffff7ffbd80 acquire_zero>
            ../../src/gcc/testsuite/g++.dg/delayedfold/builtin1.C:10:40
start: ../../src/gcc/testsuite/g++.dg/delayedfold/builtin1.C:10:40
finish: ../../src/gcc/testsuite/g++.dg/delayedfold/builtin1.C:10:52>>>

(This one is just for VIEW_CONVERT_EXPR; I don't yet know of any
existing places where NON_LVALUE_EXPR can be passed to tsubst_*).

Given that, is it OK to go with the approach in this (v2) patch? 
(presumably requiring the fix to location_wrapper_p to use a flag
rather than a matching type).


> > @@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
> >        && !expanding_concept ())
> >      fold_non_dependent_expr (expr);
> >  
> > +  STRIP_ANY_LOCATION_WRAPPER (expr);
> 
> Why is this needed?

https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00349.html

> Jason

Thanks
Dave

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-05 22:20                         ` David Malcolm
  2018-01-08 17:10                           ` Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)) David Malcolm
@ 2018-01-08 21:48                           ` Jason Merrill
  1 sibling, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2018-01-08 21:48 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 01/05/2018 05:20 PM, David Malcolm wrote:
> On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
>> On 12/29/2017 12:06 PM, David Malcolm wrote:
>>> @@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
>>>         && !expanding_concept ())
>>>       fold_non_dependent_expr (expr);
>>>   
>>> +  STRIP_ANY_LOCATION_WRAPPER (expr);
>>
>> Why is this needed?
> 
> I added this to fix a failure:
> 
> template argument deduction/substitution failed:
> note:   cannot convert ‘0’ (type ‘int’) to type ‘char**’
> 
> seen building the precompiled header, where build_non_dependent_expr
> adds a NON_DEPENDENT_EXPR around a location wrapper around an
> INTEGER_CST, whereas without location wrappers we'd just have an
> INTEGER_CST.
> 
> build_non_dependent_expr performs various tests for exact TREE_CODEs,
> special-casing constants; without the stripping these TREE_CODE tests
> don't match when the constants have location wrappers, leading to the
> failure.

Makes sense.  But we're losing the location information here; in cases 
where we return the expression unchanged we ought to return the 
expression with its location wrapper intact.

Jason

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-08 21:03                         ` David Malcolm
@ 2018-01-08 21:59                           ` Jason Merrill
  2018-01-08 22:27                             ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2018-01-08 21:59 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 01/08/2018 04:01 PM, David Malcolm wrote:
> On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
>>
>> I'd rather handle location wrappers separately, and abort if
>> VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.
> 
> Once I fixed the issue with location_wrapper_p with decls changing
> type, it turns out that trunk is already passing VIEW_CONVERT_EXPR to
> tsubst_copy_and_build for non-wrapper nodes (and from there to
> tsubst_copy), where the default case currently handles them.  Adding an
> assert turns this into an ICE.
> 
> g++.dg/delayedfold/builtin1.C is the only instance of it I found in our
> test suite, where it's used here:
> 
> class RegionLock {
>    template <unsigned long> void m_fn1();
>    int spinlock;
> } acquire_zero;
> int acquire_one;
> template <unsigned long> void RegionLock::m_fn1() {
>    __atomic_compare_exchange(&spinlock, &acquire_zero, &acquire_one, false, 2, 2);
>                                         ^~~~~~~~~~~~~
> }
> 
> (gdb) call debug_tree (t)
>   <view_convert_expr 0x7ffff1a15b40
...
>      arg:0 <non_dependent_expr 0x7ffff1a15aa0
...
>          arg:0 <addr_expr 0x7ffff1a159e0 type <pointer_type
> 0x7ffff1a18150>
>              arg:0 <var_decl 0x7ffff7ffbd80 acquire_zero>
> 
> (This one is just for VIEW_CONVERT_EXPR; I don't yet know of any
> existing places where NON_LVALUE_EXPR can be passed to tsubst_*).

Hmm, a NON_DEPENDENT_EXPR also shouldn't make it into the saved trees 
for a template.  I'll take a look.

Jason

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

* Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-08 21:59                           ` Jason Merrill
@ 2018-01-08 22:27                             ` Jason Merrill
  2018-01-09 12:03                               ` [PATCH v3 of " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2018-01-08 22:27 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 01/08/2018 04:49 PM, Jason Merrill wrote:
> On 01/08/2018 04:01 PM, David Malcolm wrote:
>> On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
>>>
>>> I'd rather handle location wrappers separately, and abort if
>>> VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.
>>
>> Once I fixed the issue with location_wrapper_p with decls changing
>> type, it turns out that trunk is already passing VIEW_CONVERT_EXPR to
>> tsubst_copy_and_build for non-wrapper nodes (and from there to
>> tsubst_copy), where the default case currently handles them.  Adding an
>> assert turns this into an ICE.
>>
>> g++.dg/delayedfold/builtin1.C is the only instance of it I found in our
>> test suite, where it's used here:
>>
>> class RegionLock {
>>    template <unsigned long> void m_fn1();
>>    int spinlock;
>> } acquire_zero;
>> int acquire_one;
>> template <unsigned long> void RegionLock::m_fn1() {
>>    __atomic_compare_exchange(&spinlock, &acquire_zero, &acquire_one, 
>> false, 2, 2);
>>                                         ^~~~~~~~~~~~~
>> }
>>
>> (gdb) call debug_tree (t)
>>   <view_convert_expr 0x7ffff1a15b40
> ...
>>      arg:0 <non_dependent_expr 0x7ffff1a15aa0
> ...
>>          arg:0 <addr_expr 0x7ffff1a159e0 type <pointer_type
>> 0x7ffff1a18150>
>>              arg:0 <var_decl 0x7ffff7ffbd80 acquire_zero>
>>
>> (This one is just for VIEW_CONVERT_EXPR; I don't yet know of any
>> existing places where NON_LVALUE_EXPR can be passed to tsubst_*).
> 
> Hmm, a NON_DEPENDENT_EXPR also shouldn't make it into the saved trees 
> for a template.  I'll take a look.

OK, we're only seeing this when args is NULL_TREE (i.e. under 
instantiate_non_dependent_expr), so tsubst_copy immediately returns. 
The assert should come after that.

Jason

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

* [PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes
  2018-01-08 18:23                                     ` Jakub Jelinek
@ 2018-01-09 11:34                                       ` David Malcolm
  2018-01-09 14:59                                         ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-09 11:34 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Nathan Sidwell, Jason Merrill, Richard Biener, gcc-patches List,
	David Malcolm

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

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

* [PATCH v3 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-08 22:27                             ` Jason Merrill
@ 2018-01-09 12:03                               ` David Malcolm
  2018-01-09 14:39                                 ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-09 12:03 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List,
	David Malcolm

On Mon, 2018-01-08 at 16:59 -0500, Jason Merrill wrote:
> On 01/08/2018 04:49 PM, Jason Merrill wrote:
> > On 01/08/2018 04:01 PM, David Malcolm wrote:
> > > On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
> > > > 
> > > > I'd rather handle location wrappers separately, and abort if
> > > > VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as
> > > > wrappers.
> > > 
> > > Once I fixed the issue with location_wrapper_p with decls
> > > changing
> > > type, it turns out that trunk is already passing
> > > VIEW_CONVERT_EXPR to
> > > tsubst_copy_and_build for non-wrapper nodes (and from there to
> > > tsubst_copy), where the default case currently handles them. 
> > > Adding an
> > > assert turns this into an ICE.
> > > 
> > > g++.dg/delayedfold/builtin1.C is the only instance of it I found
> > > in our
> > > test suite, where it's used here:
> > > 
> > > class RegionLock {
> > >    template <unsigned long> void m_fn1();
> > >    int spinlock;
> > > } acquire_zero;
> > > int acquire_one;
> > > template <unsigned long> void RegionLock::m_fn1() {
> > >    __atomic_compare_exchange(&spinlock, &acquire_zero,
> > > &acquire_one, 
> > > false, 2, 2);
> > >                                         ^~~~~~~~~~~~~
> > > }
> > > 
> > > (gdb) call debug_tree (t)
> > >   <view_convert_expr 0x7ffff1a15b40
> > 
> > ...
> > >      arg:0 <non_dependent_expr 0x7ffff1a15aa0
> > 
> > ...
> > >          arg:0 <addr_expr 0x7ffff1a159e0 type <pointer_type
> > > 0x7ffff1a18150>
> > >              arg:0 <var_decl 0x7ffff7ffbd80 acquire_zero>
> > > 
> > > (This one is just for VIEW_CONVERT_EXPR; I don't yet know of any
> > > existing places where NON_LVALUE_EXPR can be passed to tsubst_*).
> > 
> > Hmm, a NON_DEPENDENT_EXPR also shouldn't make it into the saved
> > trees 
> > for a template.  I'll take a look.
> 
> OK, we're only seeing this when args is NULL_TREE (i.e. under 
> instantiate_non_dependent_expr), so tsubst_copy immediately returns. 
> The assert should come after that.
> 
> Jason

Aha - thanks!

Here's an updated version of the patch.  It adds VIEW_CONVERT_EXPR and
NON_LVALUE_EXPR to tsubst_copy, but only supports them there for location
wrapper nodes, with an assertion.  It also adds them to
tsubst_copy_and_build, with a suitable assertion to handle the case
described above.

I also updated build_non_dependent_expr to avoid losing location wrappers
(by capturing the "orig_expr" and return it rather than "expr").

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?

(this version of the patch requires the updated version of the [02/14]
patch I posted here:
  https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00591.html
to handle the types of decls from changing under a wrapper,
which is the only other part of the kit still needing review).

Dave

gcc/cp/ChangeLog:
	* cp-gimplify.c (cp_fold): Remove the early bailout when
	processing_template_decl.
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_pt_c_tests.
	* cp-tree.h (selftest::cp_pt_c_tests): New decl.
	* mangle.c (write_expression): Skip location wrapper nodes.
	* parser.c (cp_parser_postfix_expression): Call
	maybe_add_location_wrapper on the result for RID_TYPEID. Pass true
	for new "wrap_locations_p" param of
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.
	* pt.c: Include "selftest.h".
	(tsubst_copy): Handle location wrappers.
	(tsubst_copy_and_build): Likewise.
	(build_non_dependent_expr): Likewise.
	(selftest::test_build_non_dependent_expr): New function.
	(selftest::cp_pt_c_tests): New function.
---
 gcc/cp/cp-gimplify.c |  5 ++--
 gcc/cp/cp-lang.c     |  1 +
 gcc/cp/cp-tree.h     | 10 +++++++
 gcc/cp/mangle.c      |  1 +
 gcc/cp/parser.c      | 25 ++++++++++++----
 gcc/cp/pt.c          | 85 +++++++++++++++++++++++++++++++++++++++++++++++-----
 6 files changed, 111 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 934f674..9bdaafc 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2058,7 +2058,7 @@ clear_fold_cache (void)
 
 /*  This function tries to fold an expression X.
     To avoid combinatorial explosion, folding results are kept in fold_cache.
-    If we are processing a template or X is invalid, we don't fold at all.
+    If X is invalid, we don't fold at all.
     For performance reasons we don't cache expressions representing a
     declaration or constant.
     Function returns X or its folded variant.  */
@@ -2075,8 +2075,7 @@ cp_fold (tree x)
   if (!x || x == error_mark_node)
     return x;
 
-  if (processing_template_decl
-      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
+  if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
     return x;
 
   /* Don't bother to cache DECLs or constants.  */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 805319a..2c53740 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,7 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_pt_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d4b45a4..afb4813 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7464,6 +7464,16 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+#if CHECKING_P
+namespace selftest {
+  extern void run_cp_tests (void);
+
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_pt_c_tests ();
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index ffd2b4c..895269a 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2889,6 +2889,7 @@ write_expression (tree expr)
   /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
      argument is converted (via qualification conversions) to another type.  */
   while (CONVERT_EXPR_CODE_P (code)
+	 || location_wrapper_p (expr)
 	 /* Parentheses aren't mangled.  */
 	 || code == PAREN_EXPR
 	 || code == NON_LVALUE_EXPR)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b04ed9a..1506ea4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2047,7 +2047,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6831,6 +6832,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7088,7 +7090,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7621,6 +7624,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7640,7 +7647,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7663,12 +7671,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7722,11 +7730,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -7992,6 +8003,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9831,6 +9843,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  expr = expr.maybe_add_location_wrapper ();
   return expr;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a8144e8..392fd7f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "type-utils.h"
 #include "gimplify.h"
 #include "gcc-rich-location.h"
+#include "selftest.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -14924,6 +14925,18 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* Ordinary template template argument.  */
 	return t;
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+	{
+	  /* Handle location wrappers by substituting the wrapped node
+	     first, *then* reusing the resulting type.  Doing the type
+	     first ensures that we handle template parameters and
+	     parameter pack expansions.  */
+	  gcc_assert (location_wrapper_p (t));
+	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	  return build1 (code, TREE_TYPE (op0), op0);
+	}
+
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -18290,6 +18303,18 @@ tsubst_copy_and_build (tree t,
     case REQUIRES_EXPR:
       RETURN (tsubst_requires_expr (t, args, complain, in_decl));
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      /* We should only see these for location wrapper nodes, or for
+	 VIEW_CONVERT_EXPRs within instantiate_non_dependent_expr (when
+	 args is NULL_TREE).  */
+      gcc_assert (location_wrapper_p (t)
+		  || (TREE_CODE (t) == VIEW_CONVERT_EXPR
+		      && args == NULL_TREE));
+      if (location_wrapper_p (t))
+	RETURN (RECUR (TREE_OPERAND (t, 0)));
+      /* fallthrough.  */
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -24981,6 +25006,7 @@ resolve_typename_type (tree type, bool only_current_p)
 tree
 build_non_dependent_expr (tree expr)
 {
+  tree orig_expr = expr;
   tree inner_expr;
 
   /* When checking, try to get a constant value for all non-dependent
@@ -24997,6 +25023,8 @@ build_non_dependent_expr (tree expr)
       && !expanding_concept ())
     fold_non_dependent_expr (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* Preserve OVERLOADs; the functions must be available to resolve
      types.  */
   inner_expr = expr;
@@ -25008,36 +25036,36 @@ build_non_dependent_expr (tree expr)
     inner_expr = TREE_OPERAND (inner_expr, 1);
   if (is_overloaded_fn (inner_expr)
       || TREE_CODE (inner_expr) == OFFSET_REF)
-    return expr;
+    return orig_expr;
   /* There is no need to return a proxy for a variable.  */
   if (VAR_P (expr))
-    return expr;
+    return orig_expr;
   /* Preserve string constants; conversions from string constants to
      "char *" are allowed, even though normally a "const char *"
      cannot be used to initialize a "char *".  */
   if (TREE_CODE (expr) == STRING_CST)
-    return expr;
+    return orig_expr;
   /* Preserve void and arithmetic constants, as an optimization -- there is no
      reason to create a new node.  */
   if (TREE_CODE (expr) == VOID_CST
       || TREE_CODE (expr) == INTEGER_CST
       || TREE_CODE (expr) == REAL_CST)
-    return expr;
+    return orig_expr;
   /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
      There is at least one place where we want to know that a
      particular expression is a throw-expression: when checking a ?:
      expression, there are special rules if the second or third
      argument is a throw-expression.  */
   if (TREE_CODE (expr) == THROW_EXPR)
-    return expr;
+    return orig_expr;
 
   /* Don't wrap an initializer list, we need to be able to look inside.  */
   if (BRACE_ENCLOSED_INITIALIZER_P (expr))
-    return expr;
+    return orig_expr;
 
   /* Don't wrap a dummy object, we need to be able to test for it.  */
   if (is_dummy_object (expr))
-    return expr;
+    return orig_expr;
 
   if (TREE_CODE (expr) == COND_EXPR)
     return build3 (COND_EXPR,
@@ -26600,4 +26628,47 @@ print_template_statistics (void)
 	   type_specializations->collisions ());
 }
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that build_non_dependent_expr () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_build_non_dependent_expr ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants, without and with location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (int_cst, build_non_dependent_expr (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (wrapped_int_cst, build_non_dependent_expr (wrapped_int_cst));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (string_lit, build_non_dependent_expr (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (wrapped_string_lit,
+	     build_non_dependent_expr (wrapped_string_lit));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_pt_c_tests ()
+{
+  test_build_non_dependent_expr ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
 #include "gt-cp-pt.h"
-- 
1.8.5.3

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

* Re: [PATCH v3 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-09 12:03                               ` [PATCH v3 of " David Malcolm
@ 2018-01-09 14:39                                 ` Jason Merrill
  2018-01-09 14:39                                   ` Jakub Jelinek
  0 siblings, 1 reply; 111+ messages in thread
From: Jason Merrill @ 2018-01-09 14:39 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Jakub Jelinek, Richard Biener, gcc-patches List

On 01/09/2018 06:53 AM, David Malcolm wrote:
> +    case NON_LVALUE_EXPR:
> +    case VIEW_CONVERT_EXPR:
> +	{
> +	  /* Handle location wrappers by substituting the wrapped node
> +	     first,*then*  reusing the resulting type.  Doing the type
> +	     first ensures that we handle template parameters and
> +	     parameter pack expansions.  */
> +	  gcc_assert (location_wrapper_p (t));
> +	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
> +	  return build1 (code, TREE_TYPE (op0), op0);
> +	}

Doesn't this lose the location information?

> +      /* We should only see these for location wrapper nodes, or for
> +	 VIEW_CONVERT_EXPRs within instantiate_non_dependent_expr (when
> +	 args is NULL_TREE).  */
> +      gcc_assert (location_wrapper_p (t)
> +		  || (TREE_CODE (t) == VIEW_CONVERT_EXPR
> +		      && args == NULL_TREE));

Let's just say "|| args == NULL_TREE", it might be possible to see a 
NON_LVALUE_EXPR in that context as well.

Jason

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

* Re: [PATCH v3 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-09 14:39                                 ` Jason Merrill
@ 2018-01-09 14:39                                   ` Jakub Jelinek
  2018-01-09 18:32                                     ` [PATCH v4 " David Malcolm
  0 siblings, 1 reply; 111+ messages in thread
From: Jakub Jelinek @ 2018-01-09 14:39 UTC (permalink / raw)
  To: Jason Merrill
  Cc: David Malcolm, Nathan Sidwell, Richard Biener, gcc-patches List

On Tue, Jan 09, 2018 at 09:36:58AM -0500, Jason Merrill wrote:
> On 01/09/2018 06:53 AM, David Malcolm wrote:
> > +    case NON_LVALUE_EXPR:
> > +    case VIEW_CONVERT_EXPR:
> > +	{
> > +	  /* Handle location wrappers by substituting the wrapped node
> > +	     first,*then*  reusing the resulting type.  Doing the type
> > +	     first ensures that we handle template parameters and
> > +	     parameter pack expansions.  */
> > +	  gcc_assert (location_wrapper_p (t));
> > +	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
> > +	  return build1 (code, TREE_TYPE (op0), op0);
> > +	}
> 
> Doesn't this lose the location information?

And the public_flag...

	Jakub

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

* Re: [PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes
  2018-01-09 11:34                                       ` [PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
@ 2018-01-09 14:59                                         ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2018-01-09 14:59 UTC (permalink / raw)
  To: David Malcolm, Jakub Jelinek
  Cc: Nathan Sidwell, Richard Biener, gcc-patches List

On 01/09/2018 06:37 AM, David Malcolm wrote:
> +  /* 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;

This seems like it could use a comment about why we don't actually wrap 
BASELINK as suggested by the previous comment.

OK with that change.

Jason

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

* [PATCH v4 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-09 14:39                                   ` Jakub Jelinek
@ 2018-01-09 18:32                                     ` David Malcolm
  2018-01-09 19:45                                       ` Jason Merrill
  0 siblings, 1 reply; 111+ messages in thread
From: David Malcolm @ 2018-01-09 18:32 UTC (permalink / raw)
  To: Jakub Jelinek, Jason Merrill
  Cc: Nathan Sidwell, Richard Biener, gcc-patches List, David Malcolm

On Tue, 2018-01-09 at 15:39 +0100, Jakub Jelinek wrote:
> On Tue, Jan 09, 2018 at 09:36:58AM -0500, Jason Merrill wrote:
> > On 01/09/2018 06:53 AM, David Malcolm wrote:
> > > +    case NON_LVALUE_EXPR:
> > > +    case VIEW_CONVERT_EXPR:
> > > +	{
> > > +	  /* Handle location wrappers by substituting the
> > > wrapped node
> > > +	     first,*then*  reusing the resulting type.  Doing
> > > the type
> > > +	     first ensures that we handle template parameters
> > > and
> > > +	     parameter pack expansions.  */
> > > +	  gcc_assert (location_wrapper_p (t));
> > > +	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
> > > complain, in_decl);
> > > +	  return build1 (code, TREE_TYPE (op0), op0);
> > > +	}
> > 
> > Doesn't this lose the location information?
> 
> And the public_flag...
> 
> 	Jakub

Ooops, yes.  Thanks.  I'm not convinced we always retain location
information in the tsubst_* calls: although we override input_location
within them, I see lots of pre-existing "build1" calls (as opposed to
"build1_loc"), which as I understand it set any EXPR_LOCATION to be
UNKNOWN_LOCATION.  On the other hand, even if I'm correct, that feels
like a pre-existing issue and orthogonal to this patch kit.

Here's an updated version of the patch which uses maybe_wrap_with_location
in tsubst_copy and tsubst_copy_and_build when copying the wrappers
(thus setting the flag, but hiding it as an implementation detail
within maybe_wrap_with_location).

I also updated the assertion as per Jason's other comment
(re NON_LVALUE_EXPR when args is NULL_TREE).

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?

gcc/cp/ChangeLog:
	* cp-gimplify.c (cp_fold): Remove the early bailout when
	processing_template_decl.
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_pt_c_tests.
	* cp-tree.h (selftest::cp_pt_c_tests): New decl.
	* mangle.c (write_expression): Skip location wrapper nodes.
	* parser.c (cp_parser_postfix_expression): Call
	maybe_add_location_wrapper on the result for RID_TYPEID. Pass true
	for new "wrap_locations_p" param of
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.
	* pt.c: Include "selftest.h".
	(tsubst_copy): Handle location wrappers.
	(tsubst_copy_and_build): Likewise.
	(build_non_dependent_expr): Likewise.
	(selftest::test_build_non_dependent_expr): New function.
	(selftest::cp_pt_c_tests): New function.
---
 gcc/cp/cp-gimplify.c |  5 ++--
 gcc/cp/cp-lang.c     |  1 +
 gcc/cp/cp-tree.h     | 10 +++++++
 gcc/cp/mangle.c      |  1 +
 gcc/cp/parser.c      | 25 ++++++++++++----
 gcc/cp/pt.c          | 83 +++++++++++++++++++++++++++++++++++++++++++++++-----
 6 files changed, 109 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index eda493a..e97247c 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2064,7 +2064,7 @@ clear_fold_cache (void)
 
 /*  This function tries to fold an expression X.
     To avoid combinatorial explosion, folding results are kept in fold_cache.
-    If we are processing a template or X is invalid, we don't fold at all.
+    If X is invalid, we don't fold at all.
     For performance reasons we don't cache expressions representing a
     declaration or constant.
     Function returns X or its folded variant.  */
@@ -2081,8 +2081,7 @@ cp_fold (tree x)
   if (!x || x == error_mark_node)
     return x;
 
-  if (processing_template_decl
-      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
+  if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
     return x;
 
   /* Don't bother to cache DECLs or constants.  */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 9992bc2..1ce986e 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,7 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_pt_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e0ce14e..901493f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7464,6 +7464,16 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+#if CHECKING_P
+namespace selftest {
+  extern void run_cp_tests (void);
+
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_pt_c_tests ();
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index bd74543..94c4bed 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2890,6 +2890,7 @@ write_expression (tree expr)
   /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
      argument is converted (via qualification conversions) to another type.  */
   while (CONVERT_EXPR_CODE_P (code)
+	 || location_wrapper_p (expr)
 	 /* Parentheses aren't mangled.  */
 	 || code == PAREN_EXPR
 	 || code == NON_LVALUE_EXPR)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f9181b7..e31d103 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2047,7 +2047,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6831,6 +6832,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7088,7 +7090,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7621,6 +7624,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7640,7 +7647,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7663,12 +7671,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7722,11 +7730,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -7992,6 +8003,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9831,6 +9843,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  expr = expr.maybe_add_location_wrapper ();
   return expr;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2fb327a..4f8086b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "type-utils.h"
 #include "gimplify.h"
 #include "gcc-rich-location.h"
+#include "selftest.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -14924,6 +14925,18 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* Ordinary template template argument.  */
 	return t;
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+	{
+	  /* Handle location wrappers by substituting the wrapped node
+	     first, *then* reusing the resulting type.  Doing the type
+	     first ensures that we handle template parameters and
+	     parameter pack expansions.  */
+	  gcc_assert (location_wrapper_p (t));
+	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	  return maybe_wrap_with_location (op0, EXPR_LOCATION (t));
+	}
+
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -18290,6 +18303,16 @@ tsubst_copy_and_build (tree t,
     case REQUIRES_EXPR:
       RETURN (tsubst_requires_expr (t, args, complain, in_decl));
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      /* We should only see these for location wrapper nodes, or within
+	 instantiate_non_dependent_expr (when args is NULL_TREE).  */
+      gcc_assert (location_wrapper_p (t) || args == NULL_TREE);
+      if (location_wrapper_p (t))
+	RETURN (maybe_wrap_with_location (RECUR (TREE_OPERAND (t, 0)),
+					  EXPR_LOCATION (t)));
+      /* fallthrough.  */
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -24981,6 +25004,7 @@ resolve_typename_type (tree type, bool only_current_p)
 tree
 build_non_dependent_expr (tree expr)
 {
+  tree orig_expr = expr;
   tree inner_expr;
 
   /* When checking, try to get a constant value for all non-dependent
@@ -24997,6 +25021,8 @@ build_non_dependent_expr (tree expr)
       && !expanding_concept ())
     fold_non_dependent_expr (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* Preserve OVERLOADs; the functions must be available to resolve
      types.  */
   inner_expr = expr;
@@ -25008,36 +25034,36 @@ build_non_dependent_expr (tree expr)
     inner_expr = TREE_OPERAND (inner_expr, 1);
   if (is_overloaded_fn (inner_expr)
       || TREE_CODE (inner_expr) == OFFSET_REF)
-    return expr;
+    return orig_expr;
   /* There is no need to return a proxy for a variable.  */
   if (VAR_P (expr))
-    return expr;
+    return orig_expr;
   /* Preserve string constants; conversions from string constants to
      "char *" are allowed, even though normally a "const char *"
      cannot be used to initialize a "char *".  */
   if (TREE_CODE (expr) == STRING_CST)
-    return expr;
+    return orig_expr;
   /* Preserve void and arithmetic constants, as an optimization -- there is no
      reason to create a new node.  */
   if (TREE_CODE (expr) == VOID_CST
       || TREE_CODE (expr) == INTEGER_CST
       || TREE_CODE (expr) == REAL_CST)
-    return expr;
+    return orig_expr;
   /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
      There is at least one place where we want to know that a
      particular expression is a throw-expression: when checking a ?:
      expression, there are special rules if the second or third
      argument is a throw-expression.  */
   if (TREE_CODE (expr) == THROW_EXPR)
-    return expr;
+    return orig_expr;
 
   /* Don't wrap an initializer list, we need to be able to look inside.  */
   if (BRACE_ENCLOSED_INITIALIZER_P (expr))
-    return expr;
+    return orig_expr;
 
   /* Don't wrap a dummy object, we need to be able to test for it.  */
   if (is_dummy_object (expr))
-    return expr;
+    return orig_expr;
 
   if (TREE_CODE (expr) == COND_EXPR)
     return build3 (COND_EXPR,
@@ -26600,4 +26626,47 @@ print_template_statistics (void)
 	   type_specializations->collisions ());
 }
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that build_non_dependent_expr () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_build_non_dependent_expr ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants, without and with location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (int_cst, build_non_dependent_expr (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (wrapped_int_cst, build_non_dependent_expr (wrapped_int_cst));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (string_lit, build_non_dependent_expr (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (wrapped_string_lit,
+	     build_non_dependent_expr (wrapped_string_lit));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_pt_c_tests ()
+{
+  test_build_non_dependent_expr ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
 #include "gt-cp-pt.h"
-- 
1.8.5.3

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

* Re: [PATCH v4 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)
  2018-01-09 18:32                                     ` [PATCH v4 " David Malcolm
@ 2018-01-09 19:45                                       ` Jason Merrill
  0 siblings, 0 replies; 111+ messages in thread
From: Jason Merrill @ 2018-01-09 19:45 UTC (permalink / raw)
  To: David Malcolm, Jakub Jelinek
  Cc: Nathan Sidwell, Richard Biener, gcc-patches List

On 01/09/2018 01:35 PM, David Malcolm wrote:
> On Tue, 2018-01-09 at 15:39 +0100, Jakub Jelinek wrote:
>> On Tue, Jan 09, 2018 at 09:36:58AM -0500, Jason Merrill wrote:
>>> On 01/09/2018 06:53 AM, David Malcolm wrote:
>>>> +    case NON_LVALUE_EXPR:
>>>> +    case VIEW_CONVERT_EXPR:
>>>> +	{
>>>> +	  /* Handle location wrappers by substituting the
>>>> wrapped node
>>>> +	     first,*then*  reusing the resulting type.  Doing
>>>> the type
>>>> +	     first ensures that we handle template parameters
>>>> and
>>>> +	     parameter pack expansions.  */
>>>> +	  gcc_assert (location_wrapper_p (t));
>>>> +	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
>>>> complain, in_decl);
>>>> +	  return build1 (code, TREE_TYPE (op0), op0);
>>>> +	}
>>>
>>> Doesn't this lose the location information?
>>
>> And the public_flag...
>>
>> 	Jakub
> 
> Ooops, yes.  Thanks.  I'm not convinced we always retain location
> information in the tsubst_* calls: although we override input_location
> within them, I see lots of pre-existing "build1" calls (as opposed to
> "build1_loc"), which as I understand it set any EXPR_LOCATION to be
> UNKNOWN_LOCATION.  On the other hand, even if I'm correct, that feels
> like a pre-existing issue and orthogonal to this patch kit.
> 
> Here's an updated version of the patch which uses maybe_wrap_with_location
> in tsubst_copy and tsubst_copy_and_build when copying the wrappers
> (thus setting the flag, but hiding it as an implementation detail
> within maybe_wrap_with_location).
> 
> I also updated the assertion as per Jason's other comment
> (re NON_LVALUE_EXPR when args is NULL_TREE).
> 
> 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?

OK.

Jason

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

* [committed] Preserving locations for variable-uses and constants (PR c++/43486)
  2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
                           ` (17 preceding siblings ...)
  2017-12-17  1:10         ` [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size David Malcolm
@ 2018-01-10 19:51         ` David Malcolm
  18 siblings, 0 replies; 111+ messages in thread
From: David Malcolm @ 2018-01-10 19:51 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

All of the various parts of this kit have now been approved; I've
committed it to trunk as r256448.

(The initial version of the kit was posted 2017-10-20, and
the followup on 2017-11-10, both in stage 1; the final patch
approval was 2018-01-09, towards the end of stage 3).

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
Successfully built stage1 on powerpc-ibm-aix7.1.3.0 (the rest of the
bootstrap there is in progress).
Manually tested with "make s-selftest-c++" on both hosts (since we
don't run the selftests for cc1plus by default).
Light benchmark testing (kdecore.cc) showed no significant
compile-time difference, and a slight (~0.1%) ggc increase.

Blurb follows:

This patch implements location wrapper nodes, preserving source locations
of the uses of variables and constants in various places in the
C++ frontend: at the arguments at callsites, and for typeid, alignof,
sizeof, and offsetof.

For example, it allows the C++ FE to underline the pertinent argument
for mismatching calls, for such expressions, improving:

extern int callee (int one, const char *two, float three);

int caller (int first, int second, float third)
{
  return callee (first, second, third);
}

from

test.cc: In function 'int caller(int, int, float)':
test.cc:5:38: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
   return callee (first, second, third);
                                      ^
test.cc:1:41: note:   initializing argument 2 of 'int callee(int, const char*, float)'
 extern int callee (int one, const char *two, float three);
                             ~~~~~~~~~~~~^~~

to:

test.cc: In function 'int caller(int, int, float)':
test.cc:5:25: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
   return callee (first, second, third);
                         ^~~~~~
test.cc:1:41: note:   initializing argument 2 of 'int callee(int, const char*, float)'
 extern int callee (int one, const char *two, float three);
                             ~~~~~~~~~~~~^~~

This is the combination of the following patches:

  "[PATCH 01/14] C++: preserve locations within build_address"
     https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00883.html

  "[PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes"
    https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00591.html

  "[PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS"
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01330.html

  "[PATCH v4 of 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)"
    https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00660.html

  "[PATCH 04/14] Update testsuite to show improvements"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00891.html

  "[v3 of 05/14] C++: handle locations wrappers when calling warn_for_memset"
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01378.html

  "[PATCH 07/14] reject_gcc_builtin: strip any location wrappers"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00886.html

  "[v3 of PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind"
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01433.html

  "[PATCH 09/14] Strip location wrappers in null_ptr_cst_p"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00888.html

  "[PATCH 11/14] Handle location wrappers in string_conv_p"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00890.html

  "[PATCH 12/14] C++: introduce null_node_p"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00894.html

  "[v3 of PATCH 13/14] c-format.c: handle location wrappers"
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01494.html

  "[PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers"
    https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00893.html

  "[v3 of PATCH 15/14] Use fold_for_warn in get_atomic_generic_size"
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01380.html

  "[PATCH] Add selftest for "fold_for_warn (error_mark_node)""
    https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01385.html

gcc/c-family/ChangeLog:
	PR c++/43486
	* c-common.c: Include "selftest.h".
	(get_atomic_generic_size): Perform the test for integral type
	before the range test for any integer constant, fixing indentation
	of braces.  Call fold_for_warn before testing for an INTEGER_CST.
	(reject_gcc_builtin): Strip any location wrapper from EXPR.
	(selftest::test_fold_for_warn): New function.
	(selftest::c_common_c_tests): New function.
	(selftest::c_family_tests): Call it, and
	selftest::c_pretty_print_c_tests.
	* c-common.h (selftest::c_pretty_print_c_tests): New decl.
	* c-format.c (check_format_arg): Convert VAR_P check to a
	fold_for_warn.
	* c-pretty-print.c: Include "selftest.h".
	(pp_c_cast_expression): Don't print casts for location wrappers.
	(selftest::assert_c_pretty_printer_output): New function.
	(ASSERT_C_PRETTY_PRINTER_OUTPUT): New macro.
	(selftest::test_location_wrappers): New function.
	(selftest::c_pretty_print_c_tests): New function.
	* c-warn.c (warn_for_memset): Call fold_for_warn on the arguments.

gcc/cp/ChangeLog:
	PR c++/43486
	* call.c (null_ptr_cst_p): Strip location wrappers when
	converting from '0' to a pointer type in C++11 onwards.
	(conversion_null_warnings): Replace comparison with null_node with
	call to null_node_p.
	(build_over_call): Likewise.
	* cp-gimplify.c (cp_fold): Remove the early bailout when
	processing_template_decl.
	* cp-lang.c (selftest::run_cp_tests): Call
	selftest::cp_pt_c_tests and selftest::cp_tree_c_tests.
	* cp-tree.h (cp_expr::maybe_add_location_wrapper): New method.
	(selftest::run_cp_tests): Move decl to bottom of file.
	(null_node_p): New inline function.
	(selftest::cp_pt_c_tests): New decl.
	(selftest::cp_tree_c_tests): New decl.
	* cvt.c (build_expr_type_conversion): Replace comparison with
	null_node with call to null_node_p.
	* error.c (args_to_string): Likewise.
	* except.c (build_throw): Likewise.
	* mangle.c (write_expression): Skip location wrapper nodes.
	* parser.c (literal_integer_zerop): New function.
	(cp_parser_postfix_expression): Call maybe_add_location_wrapper on
	the result for RID_TYPEID. Pass true for new "wrap_locations_p"
	param of cp_parser_parenthesized_expression_list.  When calling
	warn_for_memset, replace integer_zerop calls with
	literal_integer_zerop, eliminating the double logical negation
	cast to bool.  Eliminate the special-casing for CONST_DECL in
	favor of the fold_for_warn within warn_for_memset.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.
	* pt.c: Include "selftest.h".
	(tsubst_copy): Handle location wrappers.
	(tsubst_copy_and_build): Likewise.
	(build_non_dependent_expr): Likewise.
	(selftest::test_build_non_dependent_expr): New function.
	(selftest::cp_pt_c_tests): New function.
	* tree.c: Include "selftest.h".
	(lvalue_kind): Handle VIEW_CONVERT_EXPR location wrapper nodes.
	(selftest::test_lvalue_kind): New function.
	(selftest::cp_tree_c_tests): New function.
	* typeck.c (string_conv_p): Strip any location wrapper from "exp".
	(cp_build_binary_op): Replace comparison with null_node with call
	to null_node_p.
	(build_address): Use location of operand when building address
	expression.

gcc/testsuite/ChangeLog:
	PR c++/43486
	* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
	to reflect that the arguments are correctly underlined.
	* g++.dg/plugin/diagnostic-test-expressions-1.C: Add test coverage
	for globals, params, locals and literals.
	(test_sizeof): Directly test the location of "sizeof", rather than
	when used in compound expressions.
	(test_alignof): Likewise for "alignof".
	(test_string_literals): Likewise for string literals.
	(test_numeric_literals): Likewise for numeric literals.
	(test_builtin_offsetof): Likewise for "__builtin_offsetof".
	(test_typeid): Likewise for typeid.
	(test_unary_plus): New.
	* g++.dg/warn/Wformat-1.C: Add tests of pointer arithmetic on
	format strings.

gcc/ChangeLog:
	PR c++/43486
	* tree-core.h: Document EXPR_LOCATION_WRAPPER_P's usage of
	"public_flag".
	* tree.c (tree_nop_conversion): Return true for location wrapper
	nodes.
	(maybe_wrap_with_location): New function.
	(selftest::check_strip_nops): 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/c-family/c-common.c                            |  39 +++-
 gcc/c-family/c-common.h                            |   1 +
 gcc/c-family/c-format.c                            |  10 +-
 gcc/c-family/c-pretty-print.c                      |  66 +++++-
 gcc/c-family/c-warn.c                              |   3 +
 gcc/cp/call.c                                      |   6 +-
 gcc/cp/cp-gimplify.c                               |   5 +-
 gcc/cp/cp-lang.c                                   |   2 +
 gcc/cp/cp-tree.h                                   |  30 ++-
 gcc/cp/cvt.c                                       |   2 +-
 gcc/cp/error.c                                     |   2 +-
 gcc/cp/except.c                                    |   2 +-
 gcc/cp/mangle.c                                    |   1 +
 gcc/cp/parser.c                                    |  41 +++-
 gcc/cp/pt.c                                        |  83 ++++++-
 gcc/cp/tree.c                                      |  66 ++++++
 gcc/cp/typeck.c                                    |   6 +-
 .../g++.dg/diagnostic/param-type-mismatch.C        |  27 +--
 .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 256 +++++++++++++--------
 gcc/testsuite/g++.dg/warn/Wformat-1.C              |   2 +
 gcc/tree-core.h                                    |   3 +
 gcc/tree.c                                         | 103 +++++++++
 gcc/tree.h                                         |  47 ++++
 23 files changed, 639 insertions(+), 164 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 87bd326..097d192 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "substring-locations.h"
 #include "spellcheck.h"
+#include "selftest.h"
 
 cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
@@ -6737,8 +6738,15 @@ get_atomic_generic_size (location_t loc, tree function,
   for (x = n_param - n_model ; x < n_param; x++)
     {
       tree p = (*params)[x];
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
+	{
+	  error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
+		    function);
+	  return 0;
+	}
+      p = fold_for_warn (p);
       if (TREE_CODE (p) == INTEGER_CST)
-        {
+	{
 	  /* memmodel_base masks the low 16 bits, thus ignore any bits above
 	     it by using TREE_INT_CST_LOW instead of tree_to_*hwi.  Those high
 	     bits will be checked later during expansion in target specific
@@ -6748,14 +6756,7 @@ get_atomic_generic_size (location_t loc, tree function,
 			"invalid memory model argument %d of %qE", x + 1,
 			function);
 	}
-      else
-	if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
-	  {
-	    error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
-		   function);
-	    return 0;
-	  }
-      }
+    }
 
   return size_0;
 }
@@ -7846,6 +7847,8 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
   if (TREE_CODE (expr) == ADDR_EXPR)
     expr = TREE_OPERAND (expr, 0);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_TYPE (expr)
       && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
       && TREE_CODE (expr) == FUNCTION_DECL
@@ -8187,12 +8190,30 @@ maybe_suggest_missing_token_insertion (rich_location *richloc,
 
 namespace selftest {
 
+/* Verify that fold_for_warn on error_mark_node is safe.  */
+
+static void
+test_fold_for_warn ()
+{
+  ASSERT_EQ (error_mark_node, fold_for_warn (error_mark_node));
+}
+
+/* Run all of the selftests within this file.  */
+
+static void
+c_common_c_tests ()
+{
+  test_fold_for_warn ();
+}
+
 /* Run all of the tests within c-family.  */
 
 void
 c_family_tests (void)
 {
+  c_common_c_tests ();
   c_format_c_tests ();
+  c_pretty_print_c_tests ();
   c_spellcheck_cc_tests ();
 }
 
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 00bfe59..d090881 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1450,6 +1450,7 @@ namespace selftest {
   /* Declarations for specific families of tests within c-family,
      by source file, in alphabetical order.  */
   extern void c_format_c_tests (void);
+  extern void c_pretty_print_c_tests (void);
   extern void c_spellcheck_cc_tests (void);
 
   /* The entrypoint for running all of the above tests.  */
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index e071145..7a69d5a 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,12 +1536,10 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
-  if (VAR_P (format_tree))
-    {
-      /* Pull out a constant value if the front end didn't.  */
-      format_tree = decl_constant_value (format_tree);
-      STRIP_NOPS (format_tree);
-    }
+  /* Pull out a constant value if the front end didn't, and handle location
+     wrappers.  */
+  format_tree = fold_for_warn (format_tree);
+  STRIP_NOPS (format_tree);
 
   if (integer_zerop (format_tree))
     {
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 6e4f85c..c9dd8ae 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "intl.h"
 #include "tree-pretty-print.h"
+#include "selftest.h"
 
 /* The pretty-printer code is primarily designed to closely follow
    (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
@@ -1809,7 +1810,8 @@ pp_c_cast_expression (c_pretty_printer *pp, tree e)
     case FIX_TRUNC_EXPR:
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
-      pp_c_type_cast (pp, TREE_TYPE (e));
+      if (!location_wrapper_p (e))
+	pp_c_type_cast (pp, TREE_TYPE (e));
       pp_c_cast_expression (pp, TREE_OPERAND (e, 0));
       break;
 
@@ -2400,3 +2402,65 @@ pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t)
 
   pp_c_identifier (pp, name);
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for pretty-printing trees.  */
+
+/* Verify that EXPR printed by c_pretty_printer is EXPECTED, using
+   LOC as the effective location for any failures.  */
+
+static void
+assert_c_pretty_printer_output (const location &loc, const char *expected,
+				tree expr)
+{
+  c_pretty_printer pp;
+  pp.expression (expr);
+  ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
+}
+
+/* Helper function for calling assert_c_pretty_printer_output.
+   This is to avoid having to write SELFTEST_LOCATION.  */
+
+#define ASSERT_C_PRETTY_PRINTER_OUTPUT(EXPECTED, EXPR) \
+  SELFTEST_BEGIN_STMT						\
+    assert_c_pretty_printer_output ((SELFTEST_LOCATION),	\
+				    (EXPECTED),		\
+				    (EXPR));			\
+  SELFTEST_END_STMT
+
+/* Verify that location wrappers don't show up in pretty-printed output.  */
+
+static void
+test_location_wrappers ()
+{
+  /* VAR_DECL.  */
+  tree id = get_identifier ("foo");
+  tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id,
+			  integer_type_node);
+  tree wrapped_decl = maybe_wrap_with_location (decl, BUILTINS_LOCATION);
+  ASSERT_NE (wrapped_decl, decl);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", decl);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo", wrapped_decl);
+
+  /* INTEGER_CST.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  tree wrapped_cst = maybe_wrap_with_location (int_cst, BUILTINS_LOCATION);
+  ASSERT_NE (wrapped_cst, int_cst);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", int_cst);
+  ASSERT_C_PRETTY_PRINTER_OUTPUT ("42", wrapped_cst);
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+c_pretty_print_c_tests ()
+{
+  test_location_wrappers ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 33cae8b..7d87c45 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -1868,6 +1868,9 @@ void
 warn_for_memset (location_t loc, tree arg0, tree arg2,
 		 int literal_zero_mask)
 {
+  arg0 = fold_for_warn (arg0);
+  arg2 = fold_for_warn (arg2);
+
   if (warn_memset_transposed_args
       && integer_zerop (arg2)
       && (literal_zero_mask & (1 << 2)) != 0
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1c54bab..751fc6c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -526,6 +526,8 @@ null_ptr_cst_p (tree t)
 
   if (cxx_dialect >= cxx11)
     {
+      STRIP_ANY_LOCATION_WRAPPER (t);
+
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && !char_type_p (type)
@@ -6528,7 +6530,7 @@ static void
 conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
 {
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if (expr == null_node && TREE_CODE (totype) != BOOLEAN_TYPE
+  if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
       source_location loc =
@@ -7862,7 +7864,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
              func(NULL);
            }
       */
-      if (arg == null_node
+      if (null_node_p (arg)
           && DECL_TEMPLATE_INFO (fn)
           && cand->template_decl
           && !(flags & LOOKUP_EXPLICIT_TMPL_ARGS))
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index eda493a..e97247c 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2064,7 +2064,7 @@ clear_fold_cache (void)
 
 /*  This function tries to fold an expression X.
     To avoid combinatorial explosion, folding results are kept in fold_cache.
-    If we are processing a template or X is invalid, we don't fold at all.
+    If X is invalid, we don't fold at all.
     For performance reasons we don't cache expressions representing a
     declaration or constant.
     Function returns X or its folded variant.  */
@@ -2081,8 +2081,7 @@ cp_fold (tree x)
   if (!x || x == error_mark_node)
     return x;
 
-  if (processing_template_decl
-      || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node)))
+  if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
     return x;
 
   /* Don't bother to cache DECLs or constants.  */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 9992bc2..6007094 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -247,6 +247,8 @@ run_cp_tests (void)
   c_family_tests ();
 
   /* Additional C++-specific tests.  */
+  cp_pt_c_tests ();
+  cp_tree_c_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dff72a8..9c6c179 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;
@@ -7422,12 +7428,6 @@ extern tree cp_ubsan_maybe_instrument_downcast	(location_t, tree, tree, tree);
 extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
 extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
 
-#if CHECKING_P
-namespace selftest {
-  extern void run_cp_tests (void);
-} // namespace selftest
-#endif /* #if CHECKING_P */
-
 /* Inline bodies.  */
 
 inline tree
@@ -7458,6 +7458,24 @@ named_decl_hash::equal (const value_type existing, compare_type candidate)
   return candidate == name;
 }
 
+inline bool
+null_node_p (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+  return expr == null_node;
+}
+
+#if CHECKING_P
+namespace selftest {
+  extern void run_cp_tests (void);
+
+  /* Declarations for specific families of tests within cp,
+     by source file, in alphabetical order.  */
+  extern void cp_pt_c_tests ();
+  extern void cp_tree_c_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 444a24f..7ed2aad 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1642,7 +1642,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   tree conv = NULL_TREE;
   tree winner = NULL_TREE;
 
-  if (expr == null_node
+  if (null_node_p (expr)
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
     {
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index d8fbbde..cb1dcf3 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3230,7 +3230,7 @@ args_to_string (tree p, int verbose)
   reinit_cxx_pp ();
   for (; p; p = TREE_CHAIN (p))
     {
-      if (TREE_VALUE (p) == null_node)
+      if (null_node_p (TREE_VALUE (p)))
 	pp_cxx_ws_string (cxx_pp, "NULL");
       else
 	dump_type (cxx_pp, error_type (TREE_VALUE (p)), flags);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index b192762..669bf9f 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -577,7 +577,7 @@ build_throw (tree exp)
       return exp;
     }
 
-  if (exp == null_node)
+  if (exp && null_node_p (exp))
     warning (0, "throwing NULL, which has integral, not pointer type");
 
   if (exp != NULL_TREE)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index bd74543..94c4bed 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2890,6 +2890,7 @@ write_expression (tree expr)
   /* Skip NOP_EXPR and CONVERT_EXPR.  They can occur when (say) a pointer
      argument is converted (via qualification conversions) to another type.  */
   while (CONVERT_EXPR_CODE_P (code)
+	 || location_wrapper_p (expr)
 	 /* Parentheses aren't mangled.  */
 	 || code == PAREN_EXPR
 	 || code == NON_LVALUE_EXPR)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f9181b7..b16597c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2047,7 +2047,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6620,6 +6621,16 @@ cp_parser_compound_literal_p (cp_parser *parser)
   return compound_literal_p;
 }
 
+/* Return true if EXPR is the integer constant zero or a complex constant
+   of zero, without any folding, but ignoring location wrappers.  */
+
+static bool
+literal_integer_zerop (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+  return integer_zerop (expr);
+}
+
 /* Parse a postfix-expression.
 
    postfix-expression:
@@ -6831,6 +6842,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7088,7 +7100,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7164,10 +7177,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		tree arg0 = (*args)[0];
 		tree arg1 = (*args)[1];
 		tree arg2 = (*args)[2];
-		int literal_mask = ((!!integer_zerop (arg1) << 1)
-				    | (!!integer_zerop (arg2) << 2));
-		if (TREE_CODE (arg2) == CONST_DECL)
-		  arg2 = DECL_INITIAL (arg2);
+		int literal_mask = ((literal_integer_zerop (arg1) << 1)
+				    | (literal_integer_zerop (arg2) << 2));
 		warn_for_memset (input_location, arg0, arg2, literal_mask);
 	      }
 
@@ -7621,6 +7632,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7640,7 +7655,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7663,12 +7679,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7722,11 +7738,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -7992,6 +8011,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9831,6 +9851,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  expr = expr.maybe_add_location_wrapper ();
   return expr;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2fb327a..4f8086b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "type-utils.h"
 #include "gimplify.h"
 #include "gcc-rich-location.h"
+#include "selftest.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -14924,6 +14925,18 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	/* Ordinary template template argument.  */
 	return t;
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+	{
+	  /* Handle location wrappers by substituting the wrapped node
+	     first, *then* reusing the resulting type.  Doing the type
+	     first ensures that we handle template parameters and
+	     parameter pack expansions.  */
+	  gcc_assert (location_wrapper_p (t));
+	  tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	  return maybe_wrap_with_location (op0, EXPR_LOCATION (t));
+	}
+
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -18290,6 +18303,16 @@ tsubst_copy_and_build (tree t,
     case REQUIRES_EXPR:
       RETURN (tsubst_requires_expr (t, args, complain, in_decl));
 
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      /* We should only see these for location wrapper nodes, or within
+	 instantiate_non_dependent_expr (when args is NULL_TREE).  */
+      gcc_assert (location_wrapper_p (t) || args == NULL_TREE);
+      if (location_wrapper_p (t))
+	RETURN (maybe_wrap_with_location (RECUR (TREE_OPERAND (t, 0)),
+					  EXPR_LOCATION (t)));
+      /* fallthrough.  */
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -24981,6 +25004,7 @@ resolve_typename_type (tree type, bool only_current_p)
 tree
 build_non_dependent_expr (tree expr)
 {
+  tree orig_expr = expr;
   tree inner_expr;
 
   /* When checking, try to get a constant value for all non-dependent
@@ -24997,6 +25021,8 @@ build_non_dependent_expr (tree expr)
       && !expanding_concept ())
     fold_non_dependent_expr (expr);
 
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   /* Preserve OVERLOADs; the functions must be available to resolve
      types.  */
   inner_expr = expr;
@@ -25008,36 +25034,36 @@ build_non_dependent_expr (tree expr)
     inner_expr = TREE_OPERAND (inner_expr, 1);
   if (is_overloaded_fn (inner_expr)
       || TREE_CODE (inner_expr) == OFFSET_REF)
-    return expr;
+    return orig_expr;
   /* There is no need to return a proxy for a variable.  */
   if (VAR_P (expr))
-    return expr;
+    return orig_expr;
   /* Preserve string constants; conversions from string constants to
      "char *" are allowed, even though normally a "const char *"
      cannot be used to initialize a "char *".  */
   if (TREE_CODE (expr) == STRING_CST)
-    return expr;
+    return orig_expr;
   /* Preserve void and arithmetic constants, as an optimization -- there is no
      reason to create a new node.  */
   if (TREE_CODE (expr) == VOID_CST
       || TREE_CODE (expr) == INTEGER_CST
       || TREE_CODE (expr) == REAL_CST)
-    return expr;
+    return orig_expr;
   /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
      There is at least one place where we want to know that a
      particular expression is a throw-expression: when checking a ?:
      expression, there are special rules if the second or third
      argument is a throw-expression.  */
   if (TREE_CODE (expr) == THROW_EXPR)
-    return expr;
+    return orig_expr;
 
   /* Don't wrap an initializer list, we need to be able to look inside.  */
   if (BRACE_ENCLOSED_INITIALIZER_P (expr))
-    return expr;
+    return orig_expr;
 
   /* Don't wrap a dummy object, we need to be able to test for it.  */
   if (is_dummy_object (expr))
-    return expr;
+    return orig_expr;
 
   if (TREE_CODE (expr) == COND_EXPR)
     return build3 (COND_EXPR,
@@ -26600,4 +26626,47 @@ print_template_statistics (void)
 	   type_specializations->collisions ());
 }
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that build_non_dependent_expr () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_build_non_dependent_expr ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants, without and with location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (int_cst, build_non_dependent_expr (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (wrapped_int_cst, build_non_dependent_expr (wrapped_int_cst));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (string_lit, build_non_dependent_expr (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (wrapped_string_lit,
+	     build_non_dependent_expr (wrapped_string_lit));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_pt_c_tests ()
+{
+  test_build_non_dependent_expr ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
 #include "gt-cp-pt.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 87b45e0..ed51c28 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "flags.h"
+#include "selftest.h"
 
 static tree bot_manip (tree *, int *, void *);
 static tree bot_replace (tree *, int *, void *);
@@ -240,6 +241,11 @@ lvalue_kind (const_tree ref)
     case NON_DEPENDENT_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
+    case VIEW_CONVERT_EXPR:
+      if (location_wrapper_p (ref))
+	return lvalue_kind (TREE_OPERAND (ref, 0));
+      /* Fallthrough.  */
+
     default:
       if (!TREE_TYPE (ref))
 	return clk_none;
@@ -5346,4 +5352,64 @@ lang_check_failed (const char* file, int line, const char* function)
 }
 #endif /* ENABLE_TREE_CHECKING */
 
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that lvalue_kind () works, for various expressions,
+   and that location wrappers don't affect the results.  */
+
+static void
+test_lvalue_kind ()
+{
+  location_t loc = BUILTINS_LOCATION;
+
+  /* Verify constants and parameters, without and with
+     location wrappers.  */
+  tree int_cst = build_int_cst (integer_type_node, 42);
+  ASSERT_EQ (clk_none, lvalue_kind (int_cst));
+
+  tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_int_cst));
+  ASSERT_EQ (clk_none, lvalue_kind (wrapped_int_cst));
+
+  tree string_lit = build_string (4, "foo");
+  TREE_TYPE (string_lit) = char_array_type_node;
+  string_lit = fix_string_type (string_lit);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit));
+
+  tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_string_lit));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit));
+
+  tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
+			  get_identifier ("some_parm"),
+			  integer_type_node);
+  ASSERT_EQ (clk_ordinary, lvalue_kind (parm));
+
+  tree wrapped_parm = maybe_wrap_with_location (parm, loc);
+  ASSERT_TRUE (location_wrapper_p (wrapped_parm));
+  ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_parm));
+
+  /* Verify that lvalue_kind of std::move on a parm isn't
+     affected by location wrappers.  */
+  tree rvalue_ref_of_parm = move (parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm));
+  tree rvalue_ref_of_wrapped_parm = move (wrapped_parm);
+  ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm));
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+cp_tree_c_tests ()
+{
+  test_lvalue_kind ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+
 #include "gt-cp-tree.h"
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dc04b4b..669a2b4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2202,6 +2202,8 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
       && !same_type_p (t, wchar_type_node))
     return 0;
 
+  STRIP_ANY_LOCATION_WRAPPER (exp);
+
   if (TREE_CODE (exp) == STRING_CST)
     {
       /* Make sure that we don't try to convert between char and wide chars.  */
@@ -4317,7 +4319,7 @@ cp_build_binary_op (location_t location,
     }
 
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if ((orig_op0 == null_node || orig_op1 == null_node)
+  if ((null_node_p (orig_op0) || null_node_p (orig_op1))
       /* It's reasonable to use pointer values as operands of &&
 	 and ||, so NULL is no exception.  */
       && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR 
@@ -5734,7 +5736,7 @@ build_address (tree t)
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
   gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR);
-  t = build_fold_addr_expr (t);
+  t = build_fold_addr_expr_loc (EXPR_LOCATION (t), t);
   if (TREE_CODE (t) != ADDR_EXPR)
     t = rvalue (t);
   return t;
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index bc3a938..5fcde0b 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -1,9 +1,6 @@
 // { dg-options "-fdiagnostics-show-caret" }
 
-/* A collection of calls where argument 2 is of the wrong type.
-
-   TODO: we should put the caret and underline for the diagnostic
-   at the second argument, rather than the close paren.  */
+/* A collection of calls where argument 2 is of the wrong type.  */
 
 /* decl, with argname.  */
 
@@ -14,7 +11,7 @@ int test_1 (int first, int second, float third)
   return callee_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_1 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
   /* { dg-begin-multiline-output "" }
@@ -32,7 +29,7 @@ int test_2 (int first, int second, float third)
   return callee_2 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_2 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
   /* { dg-begin-multiline-output "" }
@@ -53,7 +50,7 @@ int test_3 (int first, int second, float third)
   return callee_3 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_3 (first, second, third);
-                                        ^
+                           ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
   /* { dg-begin-multiline-output "" }
@@ -71,7 +68,7 @@ int test_4 (int first, int second, float third)
   return s4::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s4::member_1 (first, second, third);
-                                            ^
+                               ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s4 { static int member_1 (int one, const char *two, float three); };
@@ -89,7 +86,7 @@ int test_5 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s5 { int member_1 (int one, const char *two, float three); };
@@ -106,7 +103,7 @@ int test_6 (int first, int second, float third, s6 *ptr)
   return ptr->member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return ptr->member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s6 { int member_1 (int one, const char *two, float three); };
@@ -128,7 +125,7 @@ int test_7 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
    return test_7 <const char *> (first, second, third);
-                                                     ^
+                                        ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  int test_7 (int one, T two, float three);
@@ -146,7 +143,7 @@ int test_8 (int first, int second, float third)
   return s8 <const char *>::member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return s8 <const char *>::member_1 (first, second, third);
-                                                           ^
+                                              ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s8 { static int member_1 (int one, T two, float three); };
@@ -165,7 +162,7 @@ int test_9 (int first, int second, float third)
   return inst.member_1 (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s9 { int member_1 (int one, T two, float three); };
@@ -182,7 +179,7 @@ int test_10 (int first, int second, float third)
   return callee_10 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_10 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
   /* { dg-begin-multiline-output "" }
@@ -200,7 +197,7 @@ int test_11 (int first, int second, float third)
   return callee_11 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
   /* { dg-begin-multiline-output "" }
    return callee_11 (first, second, third);
-                                         ^
+                            ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
   /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
index 8b6afeb..c08fec4 100644
--- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
+++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
@@ -19,6 +19,113 @@ extern void __emit_expression_range (int dummy, ...);
 
 int global;
 
+void test_global (void)
+{
+  __emit_expression_range (0, global); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, global);
+                               ^~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_param (int param)
+{
+  __emit_expression_range (0, param); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, param);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_local (void)
+{
+  int local = 5;
+
+  __emit_expression_range (0, local); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, local);
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_integer_constants (void)
+{
+  __emit_expression_range (0, 1234); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 1234);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  /* Ensure that zero works.  */
+
+  __emit_expression_range (0, 0); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 0);
+                               ^
+   { dg-end-multiline-output "" } */
+}
+
+void test_character_constants (void)
+{
+  __emit_expression_range (0, 'a'); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 'a');
+                               ^~~
+   { dg-end-multiline-output "" } */
+}
+
+void test_floating_constants (void)
+{
+  __emit_expression_range (0, 98.6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6);
+                               ^~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, .6); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, .6);
+                               ^~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.);
+                               ^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23 ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23 );
+                               ^~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 98.6f ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 98.6f );
+                               ^~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, 6.022140857e23l ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, 6.022140857e23l );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+enum test_enum {
+  TEST_ENUM_VALUE
+};
+
+void test_enumeration_constant (void)
+{
+  __emit_expression_range (0, TEST_ENUM_VALUE ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, TEST_ENUM_VALUE );
+                               ^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
 void test_parentheses (int a, int b)
 {
   __emit_expression_range (0, (a + b) ); /* { dg-warning "range" } */
@@ -103,67 +210,36 @@ void test_postfix_incdec (int i)
 
 void test_sizeof (int i)
 {
-  __emit_expression_range (0, sizeof(int) + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof i ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof(int) + i);
-                               ~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + sizeof(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof(int));
-                               ~~^~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, sizeof i + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, sizeof i + i);
-                               ~~~~~~~~~^~~
+   __emit_expression_range (0, sizeof i );
+                               ^~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, i + sizeof i); /* { dg-warning "range" } */
+  __emit_expression_range (0, sizeof (char) ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + sizeof i);
-                               ~~^~~~~~~~~~
+   __emit_expression_range (0, sizeof (char) );
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 void test_alignof (int i)
 {
-  __emit_expression_range (0, alignof(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, alignof(int) + i);
-                               ~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + alignof(int)); /* { dg-warning "range" } */
+  __emit_expression_range (0, alignof(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + alignof(int));
-                               ~~^~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, __alignof__(int) + i); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__(int) + i);
-                               ~~~~~~~~~~~~~~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__(int));
-                               ~~^~~~~~~~~~~~~~~~~~
+   __emit_expression_range (0, alignof(int));
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, __alignof__ i + i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, __alignof__ i + i);
-                               ~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0, __alignof__(int));
+                               ^~~~~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + __alignof__ i); /* { dg-warning "range" } */
+  __emit_expression_range (0, __alignof__ i); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + __alignof__ i);
-                               ~~^~~~~~~~~~~~~~~
+   __emit_expression_range (0, __alignof__ i);
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -200,6 +276,15 @@ void test_indirection (int *ptr)
    { dg-end-multiline-output "" } */
 }
 
+void test_unary_plus (int i)
+{
+  __emit_expression_range (0, +i ); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, +i );
+                               ^~
+   { dg-end-multiline-output "" } */
+}
+
 void test_unary_minus (int i)
 {
   __emit_expression_range (0, -i ); /* { dg-warning "range" } */
@@ -471,53 +556,36 @@ void test_comma_operator (int a, int b)
 
 /* Literals.  **************************************************/
 
-/* We can't test the ranges of literals directly, since the underlying
-   tree nodes don't retain a location.  However, we can test that they
-   have ranges during parsing by building compound expressions using
-   them, and verifying the ranges of the compound expressions.  */
-
-void test_string_literals (int i)
+void test_string_literals ()
 {
-  __emit_expression_range (0, "foo"[i] ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "0123456789"); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, "foo"[i] );
-                               ~~~~~~~^
+   __emit_expression_range (0, "0123456789");
+                               ^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &"foo" "bar" ); /* { dg-warning "range" } */
+  __emit_expression_range (0, "foo" "bar" ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &"foo" "bar" );
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, "foo" "bar" );
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
 void test_numeric_literals (int i)
 {
-  __emit_expression_range (0, 42 + i ); /* { dg-warning "range" } */
+  __emit_expression_range (0, 42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, 42 + i );
-                               ~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + 42 ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + 42 );
-                               ~~^~~~
+   __emit_expression_range (0, 42 );
+                               ^~
    { dg-end-multiline-output "" } */
 
   /* Verify locations of negative literals (via folding of
      unary negation).  */
 
-  __emit_expression_range (0, -42 + i ); /* { dg-warning "range" } */
+  __emit_expression_range (0, -42 ); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, -42 + i );
-                               ~~~~^~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, i + -42 ); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, i + -42 );
-                               ~~^~~~~
+   __emit_expression_range (0, -42 );
+                               ^~~
    { dg-end-multiline-output "" } */
 
   __emit_expression_range (0, i ? 0 : -1 ); /* { dg-warning "range" } */
@@ -638,16 +706,10 @@ struct s { int i; float f; };
 
 void test_builtin_offsetof (int i)
 {
-  __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
+  __emit_expression_range (0,  __builtin_offsetof (struct s, f) );  /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  i + __builtin_offsetof (struct s, f) );
-                                ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );  /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0,  __builtin_offsetof (struct s, f) + i );
-                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
+   __emit_expression_range (0,  __builtin_offsetof (struct s, f) );
+                                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
@@ -856,28 +918,22 @@ namespace std
 
 void test_typeid (int i)
 {
-  __emit_expression_range (0, &typeid(i)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i));
-                               ^~~~~~~~~~
-   { dg-end-multiline-output "" } */
-
-  __emit_expression_range (0, &typeid(int)); /* { dg-warning "range" } */
-/* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(int));
-                               ^~~~~~~~~~~~
+   __emit_expression_range (0, typeid(i));
+                               ^~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, &typeid(i * 2)); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(int)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, &typeid(i * 2));
-                               ^~~~~~~~~~~~~~
+   __emit_expression_range (0, typeid(int));
+                               ^~~~~~~~~~~
    { dg-end-multiline-output "" } */
 
-  __emit_expression_range (0, typeid(int).foo); /* { dg-warning "range" } */
+  __emit_expression_range (0, typeid(i * 2)); /* { dg-warning "range" } */
 /* { dg-begin-multiline-output "" }
-   __emit_expression_range (0, typeid(int).foo);
-                               ~~~~~~~~~~~~^~~
+   __emit_expression_range (0, typeid(i * 2));
+                               ^~~~~~~~~~~~~
    { dg-end-multiline-output "" } */
 }
 
diff --git a/gcc/testsuite/g++.dg/warn/Wformat-1.C b/gcc/testsuite/g++.dg/warn/Wformat-1.C
index 6094a9c..f2e772a 100644
--- a/gcc/testsuite/g++.dg/warn/Wformat-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wformat-1.C
@@ -7,4 +7,6 @@ foo (void)
 {
   const char *const msg = "abc";
   bar (1, msg);
+  bar (1, msg + 1);
+  bar (1, 1 + msg);
 }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 76d2dfd..56acd10 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 63084ac..bed59d3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12167,6 +12167,8 @@ tree_nop_conversion (const_tree exp)
 {
   tree outer_type, inner_type;
 
+  if (location_wrapper_p (exp))
+    return true;
   if (!CONVERT_EXPR_P (exp)
       && TREE_CODE (exp) != NON_LVALUE_EXPR)
     return false;
@@ -14093,6 +14095,42 @@ 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));
+
+  /* For now, don't add wrappers to exceptional tree nodes, to minimize
+     any impact of the wrapper nodes.  */
+  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 *
@@ -14464,6 +14502,70 @@ test_vector_cst_patterns ()
   check_vector_cst_fill (elements, build_vector (vector_type, elements), 4);
 }
 
+/* Verify that STRIP_NOPS (NODE) is EXPECTED.
+   Helper function for test_location_wrappers, to deal with STRIP_NOPS
+   modifying its argument in-place.  */
+
+static void
+check_strip_nops (tree node, tree expected)
+{
+  STRIP_NOPS (node);
+  ASSERT_EQ (expected, node);
+}
+
+/* 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));
+
+  /* Verify that STRIP_NOPS removes wrappers.  */
+  check_strip_nops (wrapped_int_cst, int_cst);
+  check_strip_nops (wrapped_string_cst, string_cst);
+  check_strip_nops (wrapped_int_var, int_var);
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -14473,6 +14575,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 316dcfd..f47e233 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)
@@ -3726,6 +3734,45 @@ valid_vector_subparts_p (poly_uint64 subparts)
   return true;
 }
 
+/* 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

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

end of thread, other threads:[~2018-01-10 19:48 UTC | newest]

Thread overview: 111+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-20 22:38 [PATCH] RFC: Preserving locations for variable-uses and constants (PR 43486) David Malcolm
2017-10-24 14:05 ` Jason Merrill
2017-10-31 21:28   ` David Malcolm
2017-11-02 14:46     ` Jason Merrill
2017-11-10 21:43       ` [PATCH v2: 00/14] " David Malcolm
2017-11-10 21:43         ` [PATCH 07/14] reject_gcc_builtin: strip any location wrappers David Malcolm
2017-12-11 23:38           ` Jason Merrill
2017-11-10 21:43         ` [PATCH 05/14] tree.c: strip location wrappers from integer_zerop etc David Malcolm
2017-12-11 23:36           ` Jason Merrill
2017-12-16 13:09             ` [PATCH] C++: handle locations wrappers when calling warn_for_memset David Malcolm
2017-12-16 20:01               ` Martin Sebor
2017-12-19 20:02                 ` Jason Merrill
2017-12-20 19:23                   ` [v3 of 05/14] " David Malcolm
2017-12-21  4:58                     ` Jason Merrill
2017-11-10 21:43         ` [PATCH 06/14] Fix Wsizeof-pointer-memaccess*.c David Malcolm
2017-12-11 23:37           ` Jason Merrill
2017-12-18  2:04             ` [v2 of PATCH 06/14] Strip location wrappers in operand_equal_p David Malcolm
2017-12-18  8:00               ` Jakub Jelinek
2017-12-19 20:13               ` Jason Merrill
2017-12-19 20:49                 ` Jakub Jelinek
2017-12-19 21:59                   ` Jason Merrill
2017-12-19 22:03                     ` Jakub Jelinek
2017-12-20  0:41                       ` [PATCH] Eliminate location wrappers in tree_nop_conversion/STRIP_NOPS David Malcolm
2017-12-20  4:27                         ` Jeff Law
2017-11-10 21:43         ` [PATCH 01/14] C++: preserve locations within build_address David Malcolm
2017-12-11 23:25           ` Jason Merrill
2017-11-10 21:43         ` [PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) David Malcolm
2017-12-12  2:10           ` Jason Merrill
2017-12-14 19:25             ` David Malcolm
2017-12-15 15:02               ` Jason Merrill
2017-12-15 16:35                 ` David Malcolm
2017-12-15 18:59                   ` Jason Merrill
2017-12-15 22:49                     ` David Malcolm
2017-12-29 17:03                     ` [v2 of PATCH " David Malcolm
2018-01-05 20:29                       ` Jason Merrill
2018-01-05 22:20                         ` David Malcolm
2018-01-08 17:10                           ` Location wrappers vs decls that change type (was Re: [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl)) David Malcolm
2018-01-08 17:14                             ` Nathan Sidwell
2018-01-08 17:18                               ` Jakub Jelinek
2018-01-08 17:28                                 ` Nathan Sidwell
2018-01-08 18:08                                   ` David Malcolm
2018-01-08 18:23                                     ` Jakub Jelinek
2018-01-09 11:34                                       ` [PATCH v2.4 of 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
2018-01-09 14:59                                         ` Jason Merrill
2018-01-08 21:48                           ` [v2 of PATCH 03/14] C++: add location_t wrapper nodes during parsing (minimal impl) Jason Merrill
2018-01-08 21:03                         ` David Malcolm
2018-01-08 21:59                           ` Jason Merrill
2018-01-08 22:27                             ` Jason Merrill
2018-01-09 12:03                               ` [PATCH v3 of " David Malcolm
2018-01-09 14:39                                 ` Jason Merrill
2018-01-09 14:39                                   ` Jakub Jelinek
2018-01-09 18:32                                     ` [PATCH v4 " David Malcolm
2018-01-09 19:45                                       ` Jason Merrill
2017-11-10 21:43         ` [PATCH 02/14] Support for adding and stripping location_t wrapper nodes David Malcolm
2017-11-15  6:31           ` Trevor Saunders
2017-11-15 11:23             ` Richard Biener
2017-11-15 15:40               ` David Malcolm
2017-11-16 10:04                 ` Richard Biener
2017-11-30 17:25                   ` [PATCH v2.1] " David Malcolm
2017-11-30 17:46                     ` Jason Merrill
2017-11-30 18:38                       ` [PATCH, v2.2] " David Malcolm
2017-11-30 20:30                         ` Jason Merrill
2017-11-10 21:44         ` [PATCH 08/14] cp/tree.c: strip location wrappers in lvalue_kind David Malcolm
2017-12-11 23:39           ` Jason Merrill
2017-12-20 22:11             ` [v2 of PATCH " David Malcolm
2017-12-21  4:56               ` Jason Merrill
2017-12-21 17:47                 ` [v3 " David Malcolm
2017-12-21 22:44                   ` Jason Merrill
2017-11-10 21:44         ` [PATCH 14/14] pp_c_cast_expression: don't print casts for location wrappers David Malcolm
2017-12-11 23:46           ` Jason Merrill
2017-11-10 21:44         ` [PATCH 09/14] Strip location wrappers in null_ptr_cst_p David Malcolm
2017-12-11 23:39           ` Jason Merrill
2017-11-10 21:44         ` [PATCH 13/14] c-format.c: handle location wrappers David Malcolm
2017-12-11 23:45           ` Jason Merrill
2017-12-17 16:26             ` [v2 of PATCH " David Malcolm
2017-12-19 19:55               ` Jason Merrill
2017-12-20 17:33                 ` David Malcolm
2017-12-21  5:03                   ` Jason Merrill
2017-12-22 19:07                     ` [v3 " David Malcolm
2018-01-05 17:35                       ` PING " David Malcolm
2018-01-05 17:48                         ` Joseph Myers
2018-01-05 20:21                       ` Jason Merrill
2017-11-10 21:44         ` [PATCH 04/14] Update testsuite to show improvements David Malcolm
2017-11-10 21:44         ` [PATCH 11/14] Handle location wrappers in string_conv_p David Malcolm
2017-12-11 23:42           ` Jason Merrill
2017-11-10 21:44         ` [PATCH 10/14] warn_for_memset: handle location wrappers David Malcolm
2017-12-11 23:41           ` Jason Merrill
2017-11-10 22:11         ` [PATCH 12/14] C++: introduce null_node_p David Malcolm
2017-12-11 23:42           ` Jason Merrill
2017-11-13 19:20         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
2017-11-18  2:50         ` [RFC v3 00/11] C++: locations for (almost) everything " David Malcolm
2017-11-18  2:50           ` [PATCH 06/11] gcc: Handle location wrappers in operand_equal_p David Malcolm
2017-11-18  2:50           ` [PATCH 02/11] cp_tree::maybe_add_location_wrapper: no-op for template decls David Malcolm
2017-11-18  2:50           ` [PATCH 01/11] C++: Add location wrappers for all constants and decls David Malcolm
2017-11-18  2:50           ` [PATCH 03/11] Implement STRIP_ANY_LOCATION_WRAPPER_SAFE David Malcolm
2017-11-18  2:51           ` [PATCH 04/11] C++: add cp_expr::strip_any_location_wrapper method David Malcolm
2017-11-18  2:51           ` [PATCH 09/11] objc: handle location wrappers in objc_maybe_build_component_ref David Malcolm
2017-11-18  2:51           ` [PATCH 08/11] C++: handle location wrappers David Malcolm
2017-11-18  2:51           ` [PATCH 05/11] C++: finish_call_expr: strip location wrapper David Malcolm
2017-11-18  2:51           ` [PATCH 07/11] c-family: handle location wrappers David Malcolm
2017-11-18  3:23           ` [PATCH 11/11] config: handle location wrappers in various attributes (untested) David Malcolm
2017-11-18  3:54           ` [PATCH 10/11] i386: handle location wrappers in ix86_handle_cconv_attribute David Malcolm
2017-11-30 20:54         ` [PATCH v2: 00/14] Preserving locations for variable-uses and constants (PR 43486) David Malcolm
2017-12-11 16:08           ` [PING ^ 2] " David Malcolm
2017-12-17  1:10         ` [PATCH 15/14] Use fold_for_warn in get_atomic_generic_size David Malcolm
2017-12-19 20:35           ` Jason Merrill
2017-12-20  0:50             ` [v2 of PATCH " David Malcolm
2017-12-20  4:22               ` Jason Merrill
2017-12-20 19:33                 ` [v3 " David Malcolm
2017-12-21  4:57                   ` Jason Merrill
2018-01-10 19:51         ` [committed] Preserving locations for variable-uses and constants (PR c++/43486) David Malcolm

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).