From 747f950c5bb202d29b514da1115490d55318521e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 13 Mar 2017 15:34:35 -0400
Subject: [PATCH 05/25] Fix location of sizeof/alignof (PR c++/80016)

PR c++/80016 reports an issue with bizarre underlined range
for a complicated expression.

The root cause for the incorrect *starting* location of that range
is that alignof and sizeof expressions currently have
start == finish == caret at the opening parenthesis of the
expression.

This patch fixes this by generating appropriate start and finish
locations for alignof and sizeof expressions.

OK for trunk now, or should this wait until stage 1?

gcc/cp/ChangeLog:
	PR c++/80016
	* parser.c (cp_parser_unary_expression):  Generate a location
	range for alignof and sizeof expressions.

gcc/testsuite/ChangeLog:
	PR c++/80016
	* g++.dg/plugin/diagnostic-test-expressions-1.C (test_sizeof): New
	test function.
	(test_alignof): New test function.
---
 gcc/cp/parser.c                                    | 19 +++++--
 .../g++.dg/plugin/diagnostic-test-expressions-1.C  | 66 ++++++++++++++++++++++
 2 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c1b6496..c0a1de8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7804,12 +7804,11 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 	  {
 	    tree operand, ret;
 	    enum tree_code op;
-	    location_t first_loc;
+	    location_t start_loc = token->location;
 
 	    op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
 	    /* Consume the token.  */
 	    cp_lexer_consume_token (parser->lexer);
-	    first_loc = cp_lexer_peek_token (parser->lexer)->location;
 	    /* Parse the operand.  */
 	    operand = cp_parser_sizeof_operand (parser, keyword);
 
@@ -7845,9 +7844,21 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 		    TREE_SIDE_EFFECTS (ret) = 0;
 		    TREE_READONLY (ret) = 1;
 		  }
-		SET_EXPR_LOCATION (ret, first_loc);
 	      }
-	    return ret;
+
+	    /* Construct a location e.g. :
+	       alignof (expr)
+	       ^~~~~~~~~~~~~~
+	       with start == caret at the start of the "alignof"/"sizeof"
+	       token, with the endpoint at the final closing paren.  */
+	    location_t finish_loc
+	      = cp_lexer_previous_token (parser->lexer)->location;
+	    location_t compound_loc
+	      = make_location (start_loc, start_loc, finish_loc);
+
+	    cp_expr ret_expr (ret);
+	    ret_expr.set_location (compound_loc);
+	    return ret_expr;
 	  }
 
 	case RID_NEW:
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 4d3b07c..2c004f3 100644
--- a/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
+++ b/gcc/testsuite/g++.dg/plugin/diagnostic-test-expressions-1.C
@@ -101,6 +101,72 @@ int test_postfix_incdec (int i)
 
 /* Unary operators.  ****************************************************/
 
+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" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, sizeof i + i);
+                               ~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, i + sizeof i); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, i + sizeof i);
+                               ~~^~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
+int 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" } */
+/* { 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));
+                               ~~^~~~~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, __alignof__ i + i); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, __alignof__ i + i);
+                               ~~~~~~~~~~~~~~^~~
+   { dg-end-multiline-output "" } */
+
+  __emit_expression_range (0, i + __alignof__ i); /* { dg-warning "range" } */
+/* { dg-begin-multiline-output "" }
+   __emit_expression_range (0, i + __alignof__ i);
+                               ~~^~~~~~~~~~~~~~~
+   { dg-end-multiline-output "" } */
+}
+
 int test_prefix_incdec (int i)
 {
   __emit_expression_range (0, ++i ); /* { dg-warning "range" } */
-- 
1.8.5.3

