This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: try_finally_expr wrong source location info


Hello,

I've fixed the location issue by generating new STATEMENT_LIST_END tree for
each compound statement and using it to store the location of closing brace.

I do understand that it's rather an ugly workaround than a solution, but still
it resolves the issue for us and doesn't break GCC testsuite. So I'll send it
here, maybe someone else needs the fix.

Best Regards,
Vyacheslav Barinov

Eric Botcazou <ebotcazou@adacore.com> writes:

>> But then, after lowering on the eh pass (gcc/tree-eh.c:1161), the "finally"
>> location is set up to the `gimple_location (tf->try_finally_expr)' which
>> actually expands to "testcase.cxx:4", a place where the "try" block starts.
>>
>> The dump testcase.cxx.009t.ehopt shows no location info for destructor:
>>  std::unique_ptr<char>::~unique_ptr (&lang);
>>
>> And next testcase.cxx.010t.eh dump shows equal location for constructor and
>> destructor:
>>  [testcase.cxx:4:38] std::unique_ptr<char>::unique_ptr ([testcase.cxx:4:38]
>> &lang, D.42272); [testcase.cxx:4:38] std::unique_ptr<char>::~unique_ptr
>> (&lang);
>>
>> I performed several experiments trying to get information about gimple_block
>> around the try_finally_expr statement right in `lower_try_finally_onedest',
>> but unsuccessfully. And also, as far as I understand, this issue should be
>> fixed in all the lowering functions, not only this one.
>>
>> Where should I dig in order to fix the issue?
>
> We have been using this patchlet locally for some time:
>
> Index: tree-eh.c
> ===================================================================
> --- tree-eh.c   (revision 248944)
> +++ tree-eh.c   (working copy)
> @@ -1413,11 +1413,12 @@ lower_try_finally_switch (struct leh_sta
>        x = gimple_build_assign (finally_tmp,
>                                build_int_cst (integer_type_node,
>                                               fallthru_index));
> +      gimple_set_location (x, finally_loc);
>        gimple_seq_add_stmt (&tf->top_p_seq, x);
>
>        tmp = build_int_cst (integer_type_node, fallthru_index);
>        last_case = build_case_label (tmp, NULL,
> -                                   create_artificial_label (tf_loc));
> +                                   create_artificial_label (finally_loc));
>        case_label_vec.quick_push (last_case);
>        last_case_index++;
>
> @@ -1426,7 +1427,7 @@ lower_try_finally_switch (struct leh_sta
>
>        tmp = lower_try_finally_fallthru_label (tf);
>        x = gimple_build_goto (tmp);
> -      gimple_set_location (x, tf_loc);
> +      gimple_set_location (x, finally_loc);
>        gimple_seq_add_stmt (&switch_body, x);
>      }
>From 2e3782efbf39bc26342131eb92b1bf45aeed9e8d Mon Sep 17 00:00:00 2001
From: Slava Barinov <v.barinov@samsung.com>
Date: Thu, 6 Jul 2017 16:14:58 +0300
Subject: [PATCH] Fix cleanup location for try_finally_expr.

        gcc/
        * tree.def: Add STATEMENT_LIST_END tree code.
        * tree.c: Add STATEMENT_LIST_END handling as TS_COMMON.
        * gimplify.c (gimplify_expr): Use STATEMENT_LIST_END location to
        provide right information for try_finally_expr.
        * tree-eh.c (lower_try_finally_onedest): Set finally location
        * c-family/c-semantics.c (pop_stmt_list): Support single-statement
        lists extraction with STATEMENT_LIST_END in the end.
        * fold-const.c (operand_equal_p): Add STATEMENT_LIST_END support.
	gcc/cp/
        * parser.c (cp_parser_compound_statement): Use STATEMENT_LIST_END
        to keep the location of closing brace.
        * pt.c: Handle STATEMENT_LIST_END.
        * constraint.cc (check_function_concept): Handle concept definitions
        with STATEMENT_LIST_END.
        * error.c (dump_expr): Add STATEMENT_LIST_END support.
	gcc/testsuite/
        * g++.dg/ext/statement-list-end.C: New.

Signed-off-by: Slava Barinov <v.barinov@samsung.com>
---
 gcc/ChangeLog                                      | 17 ++++++++++++++
 gcc/c-family/c-semantics.c                         |  6 +++++
 gcc/cp/ChangeLog                                   |  7 ++++++
 gcc/cp/constexpr.c                                 |  7 ++++++
 gcc/cp/constraint.cc                               |  9 ++++++++
 gcc/cp/error.c                                     |  1 +
 gcc/cp/parser.c                                    | 15 ++++++++++---
 gcc/cp/pt.c                                        |  3 +++
 gcc/fold-const.c                                   |  4 ++++
 gcc/gimple.c                                       |  1 +
 gcc/gimplify.c                                     | 26 ++++++++++++++++++++++
 gcc/testsuite/ChangeLog                            |  4 ++++
 .../c-c++-common/Wimplicit-fallthrough-6.c         | 16 ++++++-------
 .../c-c++-common/Wimplicit-fallthrough-7.c         |  4 ++--
 gcc/testsuite/g++.dg/ext/statement-list-end.C      | 11 +++++++++
 gcc/testsuite/g++.dg/gcov/gcov-2.C                 |  4 ++--
 gcc/testsuite/g++.dg/parse/error26.C               |  4 ++--
 gcc/testsuite/g++.dg/tm/inherit2.C                 |  4 ++--
 gcc/testsuite/g++.dg/tm/unsafe1.C                  |  4 ++--
 .../g++.dg/warn/Wimplicit-fallthrough-1.C          |  4 ++--
 gcc/tree-eh.c                                      | 15 +++++++++----
 gcc/tree.c                                         |  2 ++
 gcc/tree.def                                       |  4 ++++
 23 files changed, 145 insertions(+), 27 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/statement-list-end.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2acf140f407..45df6c6b5a8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2017-07-06  Vyacheslav Barinov  <v.barinov@samsung.com>
+
+	* tree.def: Add STATEMENT_LIST_END tree code.
+	* tree.c: Add STATEMENT_LIST_END handling as TS_COMMON.
+	* gimplify.c (gimplify_expr): Use STATEMENT_LIST_END location to
+	provide right information for try_finally_expr.
+	* tree-eh.c (lower_try_finally_onedest): Set finally location
+	accordingly to location of last statement in cleanup.
+	* gimple.c (DEFTREECODE): handle STATEMENT_LIST_END as appropriate
+	GIMPLE_SINGLE_RHS.
+	* cp/constraint.cc (check_function_concept): Handle concept
+	definitions with STATEMENT_LIST_END.
+	* cp/error.c (dump_expr): Add STATEMENT_LIST_END support.
+	* fold-const.c (operand_equal_p): Add STATEMENT_LIST_END support.
+	* c-family/c-semantics.c (pop_stmt_list): Support single-statement
+	lists extraction with STATEMENT_LIST_END in the end.
+
 2017-07-06  Christophe Lyon  <christophe.lyon@linaro.org>
 
 	* doc/sourcebuild.texi (Test Directives, Variants of
diff --git a/gcc/c-family/c-semantics.c b/gcc/c-family/c-semantics.c
index 3ceb714e4b1..b5cecf35bb1 100644
--- a/gcc/c-family/c-semantics.c
+++ b/gcc/c-family/c-semantics.c
@@ -66,6 +66,12 @@ pop_stmt_list (tree t)
   if (TREE_SIDE_EFFECTS (t))
     {
       tree_stmt_iterator i = tsi_start (t);
+      if (i.ptr->next && i.ptr->next->stmt &&
+	  TREE_CODE(i.ptr->next->stmt) == STATEMENT_LIST_END)
+	{
+	  tree_stmt_iterator i = tsi_last (t);
+	  tsi_delink (&i);
+	}
 
       /* If the statement list contained exactly one statement, then
 	 extract it immediately.  */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4dffee44f17..8a5c929bae3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2017-07-06  Vyacheslav Barinov  <v.barinov@samsung.com>
+
+	* parser.c (cp_parser_compound_statement): Use STATEMENT_LIST_END
+	to keep the location of closing brace.
+	* pt.c: Handle STATEMENT_LIST_END.
+	* constexpr.c (cxx_eval_constant_expression): Likewise.
+
 2017-07-04  Jakub Jelinek  <jakub@redhat.com>
 
 	* parser.c (cp_parser_decomposition_declaration): Replace
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 32180a74c3f..715d9c8514b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -448,6 +448,7 @@ check_constexpr_ctor_body_1 (tree last, tree list)
 
     case USING_STMT:
     case STATIC_ASSERT:
+    case STATEMENT_LIST_END:
       return true;
 
     default:
@@ -562,6 +563,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
 	body = BIND_EXPR_BODY (body);
 	goto found;
 
+      case STATEMENT_LIST_END:
+	break;
+
       default:
 	gcc_unreachable ();
     }
@@ -673,6 +677,7 @@ constexpr_fn_retval (tree body)
       return constexpr_fn_retval (BIND_EXPR_BODY (body));
 
     case USING_STMT:
+    case STATEMENT_LIST_END:
       return NULL_TREE;
 
     default:
@@ -4486,6 +4491,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case EMPTY_CLASS_EXPR:
+    case STATEMENT_LIST_END:
       /* This is good enough for a function argument that might not get
 	 used, and they can't do anything with it, so just return it.  */
       return t;
@@ -5777,6 +5783,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
 
     case TYPE_DECL:
     case TAG_DEFN:
+    case STATEMENT_LIST_END:
       /* We can see these in statement-expressions.  */
       return true;
 
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 64a8ea926d2..1c1456162d9 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-objc.h"
 #include "cp-objcp-common.h"
 #include "tree-inline.h"
+#include "tree-iterator.h"
 #include "decl.h"
 #include "toplev.h"
 #include "type-utils.h"
@@ -2499,6 +2500,14 @@ check_function_concept (tree fn)
   if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
     body = TREE_OPERAND (body, 0);
 
+  // We need to cut the STATEMENT_LIST_END before the check.
+  if (TREE_CODE (body) == STATEMENT_LIST &&
+      TREE_CODE (STATEMENT_LIST_TAIL (body)->stmt) == STATEMENT_LIST_END)
+    {
+      tree_stmt_iterator i = tsi_last (body);
+      tsi_delink(&i);
+    }
+
   /* Check that the definition is written correctly. */
   if (TREE_CODE (body) != RETURN_EXPR)
     {
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 43b5cec0a95..2c89448f07d 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2688,6 +2688,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
     case STMT_EXPR:
     case EXPR_STMT:
     case STATEMENT_LIST:
+    case STATEMENT_LIST_END:
       /* We don't yet have a way of dumping statements in a
 	 human-readable format.  */
       pp_string (pp, "({...})");
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index dbe00527924..41658fd581d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11142,11 +11142,20 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
     cp_parser_label_declaration (parser);
   /* Parse an (optional) statement-seq.  */
   cp_parser_statement_seq_opt (parser, in_statement_expr);
+  /* Consume the `}' and keep location, if there is a `}' and compound_stmt is
+     not empty. */
+  cp_token *token = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+  if (token &&
+      TREE_CODE(compound_stmt) == STATEMENT_LIST &&
+      STATEMENT_LIST_HEAD (compound_stmt) &&
+      STATEMENT_LIST_TAIL (compound_stmt))
+    {
+      tree brace_stmt = build0(STATEMENT_LIST_END, void_type_node);
+      SET_EXPR_LOCATION(brace_stmt, token->location);
+      add_stmt(brace_stmt);
+    }
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
-  /* Consume the `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
-
   return compound_stmt;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bd02951cb85..cb2ffd30ba0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16516,6 +16516,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       RETURN (build2_loc (EXPR_LOCATION (t), ANNOTATE_EXPR,
 			  TREE_TYPE (tmp), tmp, RECUR (TREE_OPERAND (t, 1))));
 
+    case STATEMENT_LIST_END:
+      RETURN (t);
+
     default:
       gcc_assert (!STATEMENT_CODE_P (TREE_CODE (t)));
 
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 1bcbbb58154..d573d147cfd 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3207,6 +3207,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 	    return OP_SAME (0);
 	  return 0;
 
+	case STATEMENT_LIST_END:
+	  return 1;
+	  /* All STATEMENT_LIST_END are equal */
+
 	default:
 	  return 0;
 	}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 488f8c82b82..a5a8b929698 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2060,6 +2060,7 @@ get_gimple_rhs_num_ops (enum tree_code code)
       || (SYM) == ADDR_EXPR						    \
       || (SYM) == WITH_SIZE_EXPR					    \
       || (SYM) == SSA_NAME) ? GIMPLE_SINGLE_RHS				    \
+   : ((SYM) == STATEMENT_LIST_END) ? GIMPLE_SINGLE_RHS			    \
    : GIMPLE_INVALID_RHS),
 #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS,
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 641a8210dad..724520b06a9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1023,6 +1023,11 @@ voidify_wrapper_expr (tree wrapper, tree temp)
 	    case STATEMENT_LIST:
 	      {
 		tree_stmt_iterator i = tsi_last (*p);
+		if (TREE_CODE(*tsi_stmt_ptr (i)) == STATEMENT_LIST_END)
+		  {
+		    tsi_delink(&i);
+		    i = tsi_last (*p);
+		  }
 		TREE_SIDE_EFFECTS (*p) = 1;
 		TREE_TYPE (*p) = void_type_node;
 		p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
@@ -11671,6 +11676,19 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	       end of gimplify_expr.  */
 	    input_location = UNKNOWN_LOCATION;
 	    eval = cleanup = NULL;
+	    location_t finally_loc = 0;
+	    /* The cleanup location can be extracted from STATEMENT_LIST_END
+	       location added especially for this purpose. */
+	    if (TREE_OPERAND (*expr_p, 0) &&
+		TREE_CODE (TREE_OPERAND (*expr_p, 0)) == STATEMENT_LIST)
+	      {
+		const tree_statement_list_node* last_node =
+		  STATEMENT_LIST_TAIL(TREE_OPERAND (*expr_p, 0));
+		if (last_node &&
+		    last_node->stmt &&
+		    TREE_CODE (last_node->stmt) == STATEMENT_LIST_END)
+		  finally_loc = EXPR_LOCATION(last_node->stmt);
+	      }
 	    gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
 	    gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
 	    /* Don't create bogus GIMPLE_TRY with empty cleanup.  */
@@ -11691,6 +11709,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	    if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
 	      gimple_try_set_catch_is_cleanup (try_,
 					       TRY_CATCH_IS_CLEANUP (*expr_p));
+
+	    gimple *last_in_seq = gimple_seq_last_stmt (cleanup);
+	    gimple_set_location(last_in_seq, finally_loc);
+
 	    gimplify_seq_add_stmt (pre_p, try_);
 	    ret = GS_ALL_DONE;
 	    break;
@@ -11752,6 +11774,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	  ret = gimplify_statement_list (expr_p, pre_p);
 	  break;
 
+	case STATEMENT_LIST_END:
+	  ret = GS_ALL_DONE;
+	  break;
+
 	case WITH_SIZE_EXPR:
 	  {
 	    gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d629c2bd90d..7a8e8dcf1eb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-06  Vyacheslav Barinov  <v.barinov@samsung.com>
+
+	* g++.dg/ext/statement-list-end.C: New.
+
 2017-07-06  Christophe Lyon  <christophe.lyon@linaro.org>
 
 	* lib/target-supports-dg.exp (dg-require-stack-check): New.
diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c
index 32d5febda83..9593f670709 100644
--- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c
+++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c
@@ -121,8 +121,8 @@ L1:
 	int j = 0;
 	bar (j);
 	if (j == 8)
-	  return; /* { dg-warning "statement may fall through" "" { target c++ } } */
-      }
+	  return;
+      } /* { dg-warning "statement may fall through" "" { target c++ } } */
     case 2:
       bar (99);
     }
@@ -151,8 +151,8 @@ L1:
 	if (j == 8)
 	  bar (1);
 	else
-	  return; /* { dg-warning "statement may fall through" "" { target c++ } } */
-      }
+	  return;
+      } /* { dg-warning "statement may fall through" "" { target c++ } } */
     case 2:
       bar (99);
     }
@@ -181,8 +181,8 @@ L1:
 	if (j == 8)
 	  bar (1);
 	else
-	  bar (2); /* { dg-warning "statement may fall through" "" { target c++ } } */
-      }
+	  bar (2);
+      } /* { dg-warning "statement may fall through" "" { target c++ } } */
     case 2:
       bar (99);
     }
@@ -281,8 +281,8 @@ L1:
     case 1:
       { /* { dg-warning "statement may fall through" "" { target c } } */
 	int j = 9;
-	switch (j); /* { dg-warning "statement may fall through" "" { target c++ } } */
-      }
+	switch (j);
+      } /* { dg-warning "statement may fall through" "" { target c++ } } */
     case 2:
       bar (99);
     }
diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
index 24a573b4d19..1145e313352 100644
--- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
+++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
@@ -22,8 +22,8 @@ f (int i)
     {
     case 1:
       { /* { dg-warning "statement may fall through" "" { target c } } */
-	int a[i]; /* { dg-warning "statement may fall through" "" { target c++ } } */
-      }
+	int a[i];
+      } /* { dg-warning "statement may fall through" "" { target c++ } } */
     case 2:
       bar (99);
     }
diff --git a/gcc/testsuite/g++.dg/ext/statement-list-end.C b/gcc/testsuite/g++.dg/ext/statement-list-end.C
new file mode 100644
index 00000000000..3381172492a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/statement-list-end.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple-lineno" } */
+/* { dg-require-effective-target c++11 } */
+
+#include <memory>
+void i ()
+{
+  std::unique_ptr<char> c(new char);
+}
+
+/* { dg-final { scan-tree-dump "9:1] std::unique_ptr<char>::~unique_ptr" "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-2.C b/gcc/testsuite/g++.dg/gcov/gcov-2.C
index 6d002f5d2cd..2b4cdd844e9 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-2.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-2.C
@@ -20,9 +20,9 @@ private:
 
 void foo()
 {
-  C c;					/* count(2) */
+  C c;					/* count(1) */
   c.seti (1);				/* count(1) */
-}
+}					/* count(1) */
 
 int main()
 {
diff --git a/gcc/testsuite/g++.dg/parse/error26.C b/gcc/testsuite/g++.dg/parse/error26.C
index 95f299163e9..9092bbf2960 100644
--- a/gcc/testsuite/g++.dg/parse/error26.C
+++ b/gcc/testsuite/g++.dg/parse/error26.C
@@ -4,11 +4,11 @@
 void foo()
 {
   if (({int c[2];})) ; // { dg-error "7:ISO C.. forbids" "7" }
-  // { dg-error "17:could not convert" "17" { target *-*-* } .-1 }
+  // { dg-error "18:could not convert" "18" { target *-*-* } .-1 }
 }
 
 void bar()
 {
   if (({})); // { dg-error "7:ISO C.. forbids" "7" }
-  // { dg-error "11:could not convert" "11" { target *-*-* } .-1 }
+  // { dg-error "9:could not convert" "9" { target *-*-* } .-1 }
 }
diff --git a/gcc/testsuite/g++.dg/tm/inherit2.C b/gcc/testsuite/g++.dg/tm/inherit2.C
index 3b696a9ffb6..366f9b30e90 100644
--- a/gcc/testsuite/g++.dg/tm/inherit2.C
+++ b/gcc/testsuite/g++.dg/tm/inherit2.C
@@ -26,8 +26,8 @@ int main()
     B b; // ok
     D1 d1; // ok
     B& b1 = d1;
-    D2 x; // { dg-error "" "destructor of D2 is not transaction-safe" }
+    D2 x;
     b1.f(); // ok, calls D1::f()
     delete b2; // undefined behavior: calls unsafe destructor of D2
-  }
+  } // { dg-error "" "destructor of D2 is not transaction-safe" }
 }
diff --git a/gcc/testsuite/g++.dg/tm/unsafe1.C b/gcc/testsuite/g++.dg/tm/unsafe1.C
index 91dd7b110ec..e86b1bd33c4 100644
--- a/gcc/testsuite/g++.dg/tm/unsafe1.C
+++ b/gcc/testsuite/g++.dg/tm/unsafe1.C
@@ -5,8 +5,8 @@ struct S {
   virtual ~S();
 };
 int f() transaction_safe {
-  S s;		     // { dg-error "unsafe" "invocation of unsafe destructor" }
-}
+  S s;
+} // { dg-error "unsafe" "invocation of unsafe destructor" }
 
 int g(int x) { // is transaction-safe
   if (x <= 0)
diff --git a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C
index 053ed6885c5..b5ebd3daaad 100644
--- a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C
@@ -25,8 +25,8 @@ fn2 ()
   switch (0) {
   case 0:
   {
-    A b; // { dg-warning "statement may fall through" }
-  }
+    A b;
+  } // { dg-warning "statement may fall through" }
   default:
     a = 0;
   }
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 79d02adbade..65a61746fcb 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1135,10 +1135,16 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
   gimple_stmt_iterator gsi;
   tree finally_label;
   location_t loc = gimple_location (tf->try_finally_expr);
+  location_t finally_loc;
 
   finally = gimple_try_cleanup (tf->top_p);
   tf->top_p_seq = gimple_try_eval (tf->top_p);
 
+  /* The location of the finally is either the last stmt in the finally
+     block or the location of the TRY_FINALLY itself.  */
+  x = gimple_seq_last_stmt (finally);
+  finally_loc = x ? gimple_location (x) : loc;
+
   /* Since there's only one destination, and the destination edge can only
      either be EH or non-EH, that implies that all of our incoming edges
      are of the same type.  Therefore we can lower EH_ELSE immediately.  */
@@ -1159,7 +1165,7 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
       if (LOCATION_LOCUS (gimple_location (stmt)) == UNKNOWN_LOCATION)
 	{
 	  tree block = gimple_block (stmt);
-	  gimple_set_location (stmt, gimple_location (tf->try_finally_expr));
+	  gimple_set_location (stmt, finally_loc);
 	  gimple_set_block (stmt, block);
 	}
     }
@@ -1182,7 +1188,7 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
       return;
     }
 
-  finally_label = create_artificial_label (loc);
+  finally_label = create_artificial_label (finally_loc);
   label_stmt = gimple_build_label (finally_label);
   gimple_seq_add_stmt (&tf->top_p_seq, label_stmt);
 
@@ -1414,11 +1420,12 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
       x = gimple_build_assign (finally_tmp,
 			       build_int_cst (integer_type_node,
 					      fallthru_index));
+      gimple_set_location (x, finally_loc);
       gimple_seq_add_stmt (&tf->top_p_seq, x);
 
       tmp = build_int_cst (integer_type_node, fallthru_index);
       last_case = build_case_label (tmp, NULL,
-				    create_artificial_label (tf_loc));
+				    create_artificial_label (finally_loc));
       case_label_vec.quick_push (last_case);
       last_case_index++;
 
@@ -1427,7 +1434,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
 
       tmp = lower_try_finally_fallthru_label (tf);
       x = gimple_build_goto (tmp);
-      gimple_set_location (x, tf_loc);
+      gimple_set_location (x, finally_loc);
       gimple_seq_add_stmt (&switch_body, x);
     }
 
diff --git a/gcc/tree.c b/gcc/tree.c
index ca28afad0f2..f07758e155d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -469,6 +469,7 @@ tree_node_structure_for_code (enum tree_code code)
     case SSA_NAME:		return TS_SSA_NAME;
     case PLACEHOLDER_EXPR:	return TS_COMMON;
     case STATEMENT_LIST:	return TS_STATEMENT_LIST;
+    case STATEMENT_LIST_END:	return TS_COMMON;
     case BLOCK:			return TS_BLOCK;
     case CONSTRUCTOR:		return TS_CONSTRUCTOR;
     case TREE_BINFO:		return TS_BINFO;
@@ -824,6 +825,7 @@ tree_code_size (enum tree_code code)
 	case TREE_LIST:		return sizeof (struct tree_list);
 
 	case ERROR_MARK:
+	case STATEMENT_LIST_END:
 	case PLACEHOLDER_EXPR:	return sizeof (struct tree_common);
 
 	case TREE_VEC:
diff --git a/gcc/tree.def b/gcc/tree.def
index 0ec805903a9..5bab6e4482f 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -991,6 +991,10 @@ DEFTREECODE (POLYNOMIAL_CHREC, "polynomial_chrec", tcc_expression, 3)
    Use the interface in tree-iterator.h to access this node.  */
 DEFTREECODE (STATEMENT_LIST, "statement_list", tcc_exceptional, 0)
 
+/* Used to keep STATEMENT_LIST end location.
+   The only useful field is location, which points to the closing brace. */
+DEFTREECODE (STATEMENT_LIST_END, "statement_list_end", tcc_expression, 0)
+
 /* Predicate assertion.  Artificial expression generated by the optimizers
    to keep track of predicate values.  This expression may only appear on
    the RHS of assignments.
-- 
2.13.2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]