This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: try_finally_expr wrong source location info
- From: Vyacheslav Barinov <v dot barinov at samsung dot com>
- To: gcc at gcc dot gnu dot org
- Cc: Eric Botcazou <ebotcazou at adacore dot com>, Merzlyakov Alexey <alexey dot merzlyakov at samsung dot com>, Ostapenko Maksim <m dot ostapenko at samsung dot com>
- Date: Wed, 12 Jul 2017 15:44:44 +0300
- Subject: Re: try_finally_expr wrong source location info
- Authentication-results: sourceware.org; auth=none
- Cms-type: 201P
- References: <CGME20170609175524eucas1p281bea1138dfbd7c7b5c0d49dfa78155f@eucas1p2.samsung.com> <877f0lqc53.fsf@samsung.com> <1555213.uMUt3NAUX6@polaris>
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