+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-04-13 Denis Khalikov <d.khalikov@partner.samsung.com>
PR sanitizer/80414
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. */
+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-01-26 Jason Merrill <jason@redhat.com>
PR c++/79176 - lambda ICE with -flto -Os
case USING_STMT:
case STATIC_ASSERT:
+ case STATEMENT_LIST_END:
return true;
default:
body = BIND_EXPR_BODY (body);
goto found;
+ case STATEMENT_LIST_END:
+ break;
+
default:
gcc_unreachable ();
}
return constexpr_fn_retval (BIND_EXPR_BODY (body));
case USING_STMT:
+ case STATEMENT_LIST_END:
return NULL_TREE;
default:
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;
case TYPE_DECL:
case TAG_DEFN:
+ case STATEMENT_LIST_END:
/* We can see these in statement-expressions. */
return true;
#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"
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)
{
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, "({...})");
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;
}
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)));
SIGNED, &quo))
return wide_int_to_tree (TREE_TYPE (arg1), quo);
- return NULL_TREE;
+ return NULL_TREE;
}
\f
/* This is nonzero if we should defer warnings about undefined
and the operand is a signaling NaN. */
if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
&& REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg1)))
- return NULL_TREE;
+ return NULL_TREE;
real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
t = build_real (type, value);
|| TREE_TYPE (arg1) == error_mark_node)
return 0;
- /* Similar, if either does not have a type (like a released SSA name),
+ /* Similar, if either does not have a type (like a released SSA name),
they aren't equal. */
if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
return 0;
case DOT_PROD_EXPR:
return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
+ case STATEMENT_LIST_END:
+ return 1;
+ /* All STATEMENT_LIST_END are equal */
+
default:
return 0;
}
Double check this so we won't get false
positives for GENERIC. */
|| (c0->index
- && (TREE_CODE (c0->index) != INTEGER_CST
+ && (TREE_CODE (c0->index) != INTEGER_CST
|| !compare_tree_int (c0->index, i)))
|| (c1->index
- && (TREE_CODE (c1->index) != INTEGER_CST
+ && (TREE_CODE (c1->index) != INTEGER_CST
|| !compare_tree_int (c1->index, i))))
return 0;
}
A || ~B
or
A && ~B
- LOC is the location of the resulting expression. OP is the inner
+ LOC is the location of the resulting expression. OP is the inner
logical operation; the left-hand side in the examples above, while CMPOP
is the right-hand side. RHS_ONLY is used to prevent us from accidentally
removing a condition that guards another, as in
if (NULL_TREE == i_type
|| TYPE_PRECISION (i_type) != total_bytes)
return 0;
-
+
value = TREE_FIXED_CST (expr);
i_value = double_int_to_tree (i_type, value.data);
side-effects. */
&& simple_operand_p_2 (TREE_OPERAND (arg1, 0)))
{
- tem = fold_build2_loc (loc, ncode, type,
+ tem = fold_build2_loc (loc, ncode, type,
arg0, TREE_OPERAND (arg1, 0));
return fold_build2_loc (loc, icode, type, tem,
TREE_OPERAND (arg1, 1));
case TRUNC_DIV_EXPR:
/* Fall through */
-
+
case FLOOR_DIV_EXPR:
/* Simplify A / (B << N) where A and B are positive and B is
a power of 2, to A >> (N + log2(B)). */
l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
-
+
n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
-
+
if ((operand_equal_p (n0, a0, 0)
&& operand_equal_p (n1, a1, 0))
|| (operand_equal_p (n0, a1, 0)
|| (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,
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);
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. */
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;
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,
+2017-07-06 Vyacheslav Barinov <v.barinov@samsung.com>
+
+ * g++.dg/ext/statement-list-end.C: New.
+
2017-04-13 Denis Khalikov <d.khalikov@partner.samsung.com>
PR sanitizer/80414
--- /dev/null
+/* { 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" } } */
void foo()
{
- C c; /* count(2) */
+ C c; /* count(1) */
c.seti (1); /* count(1) */
-}
+} /* count(1) */
int main()
{
void foo()
{
if (({int c[2];})) ; // { dg-error "7:ISO C.. forbids" "7" }
- // { dg-error "17:could not convert" "17" { target *-*-* } 6 }
+ // { 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 *-*-* } 12 }
+ // { dg-error "11:could not convert" "11" { target *-*-* } .-1 }
}
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" }
}
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)
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. */
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);
}
}
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);
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++;
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);
}
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;
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:
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.