Commit 43574e4f by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/89285 (ICE after casting the this pointer in the constructor in C++17 mode)

	PR c++/89285
	* builtins.c (fold_builtin_arith_overflow): If first two args are
	INTEGER_CSTs, set intres and ovfres to constants rather than calls
	to ifn.

	* constexpr.c (struct constexpr_fundef): Add parms and result members.
	(retrieve_constexpr_fundef): Adjust for the above change.
	(register_constexpr_fundef): Save constexpr body with copy_fn,
	temporarily set DECL_CONTEXT on DECL_RESULT before that.
	(get_fundef_copy): Change FUN argument to FUNDEF with
	constexpr_fundef * type, grab body and parms/result out of
	constexpr_fundef struct and temporarily change it for copy_fn calls
	too.
	(cxx_eval_builtin_function_call): For __builtin_FUNCTION temporarily
	adjust current_function_decl from ctx->call context.  Test
	!potential_constant_expression instead of !is_constant_expression.
	(cxx_bind_parameters_in_call): Grab parameters from new_call.  Undo
	convert_for_arg_passing changes for TREE_ADDRESSABLE type passing.
	(cxx_eval_call_expression): Adjust get_fundef_copy caller.
	(cxx_eval_conditional_expression): For IF_STMT, allow then or else
	operands to be NULL.
	(label_matches): Handle BREAK_STMT and CONTINUE_STMT.
	(cxx_eval_loop_expr): Add support for FOR_STMT, WHILE_STMT and DO_STMT.
	(cxx_eval_switch_expr): Add support for SWITCH_STMT.
	(cxx_eval_constant_expression): Handle IF_STMT, FOR_STMT, WHILE_STMT,
	DO_STMT, CONTINUE_STMT, SWITCH_STMT, BREAK_STMT and CONTINUE_STMT.
	For SIZEOF_EXPR, recurse on the result of fold_sizeof_expr.  Ignore
	DECL_EXPR with USING_DECL operand.
	* lambda.c (maybe_add_lambda_conv_op): Build thisarg using
	build_int_cst to make it a valid constant expression.

	* g++.dg/ubsan/vptr-4.C: Expect reinterpret_cast errors.
	* g++.dg/cpp1y/constexpr-84192.C (f2): Adjust expected diagnostics.
	* g++.dg/cpp1y/constexpr-70265-2.C (foo): Adjust expected line of
	diagnostics.
	* g++.dg/cpp1y/constexpr-89285.C: New test.
	* g++.dg/cpp0x/constexpr-arith-overflow.C (add, sub, mul): Ifdef out
	for C++11.
	(TEST_ADD, TEST_SUB, TEST_MUL): Define to Assert (true) for C++11.
	* g++.dg/cpp0x/constexpr-arith-overflow2.C: New test.

From-SVN: r269078
parent d331c5f1
2019-02-21 Jakub Jelinek <jakub@redhat.com>
PR c++/89285
* builtins.c (fold_builtin_arith_overflow): If first two args are
INTEGER_CSTs, set intres and ovfres to constants rather than calls
to ifn.
2019-02-21 H.J. Lu <hongjiu.lu@intel.com>
PR target/87412
......
......@@ -9302,8 +9302,7 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
tree arg0, tree arg1, tree arg2)
{
enum internal_fn ifn = IFN_LAST;
/* The code of the expression corresponding to the type-generic
built-in, or ERROR_MARK for the type-specific ones. */
/* The code of the expression corresponding to the built-in. */
enum tree_code opcode = ERROR_MARK;
bool ovf_only = false;
......@@ -9313,42 +9312,39 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
ovf_only = true;
/* FALLTHRU */
case BUILT_IN_ADD_OVERFLOW:
opcode = PLUS_EXPR;
/* FALLTHRU */
case BUILT_IN_SADD_OVERFLOW:
case BUILT_IN_SADDL_OVERFLOW:
case BUILT_IN_SADDLL_OVERFLOW:
case BUILT_IN_UADD_OVERFLOW:
case BUILT_IN_UADDL_OVERFLOW:
case BUILT_IN_UADDLL_OVERFLOW:
opcode = PLUS_EXPR;
ifn = IFN_ADD_OVERFLOW;
break;
case BUILT_IN_SUB_OVERFLOW_P:
ovf_only = true;
/* FALLTHRU */
case BUILT_IN_SUB_OVERFLOW:
opcode = MINUS_EXPR;
/* FALLTHRU */
case BUILT_IN_SSUB_OVERFLOW:
case BUILT_IN_SSUBL_OVERFLOW:
case BUILT_IN_SSUBLL_OVERFLOW:
case BUILT_IN_USUB_OVERFLOW:
case BUILT_IN_USUBL_OVERFLOW:
case BUILT_IN_USUBLL_OVERFLOW:
opcode = MINUS_EXPR;
ifn = IFN_SUB_OVERFLOW;
break;
case BUILT_IN_MUL_OVERFLOW_P:
ovf_only = true;
/* FALLTHRU */
case BUILT_IN_MUL_OVERFLOW:
opcode = MULT_EXPR;
/* FALLTHRU */
case BUILT_IN_SMUL_OVERFLOW:
case BUILT_IN_SMULL_OVERFLOW:
case BUILT_IN_SMULLL_OVERFLOW:
case BUILT_IN_UMUL_OVERFLOW:
case BUILT_IN_UMULL_OVERFLOW:
case BUILT_IN_UMULLL_OVERFLOW:
opcode = MULT_EXPR;
ifn = IFN_MUL_OVERFLOW;
break;
default:
......@@ -9373,13 +9369,27 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
? boolean_true_node : boolean_false_node,
arg2);
tree ctype = build_complex_type (type);
tree call = build_call_expr_internal_loc (loc, ifn, ctype,
2, arg0, arg1);
tree tgt = save_expr (call);
tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
tree intres, ovfres;
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
intres = fold_binary_loc (loc, opcode, type,
fold_convert_loc (loc, type, arg0),
fold_convert_loc (loc, type, arg1));
if (TREE_OVERFLOW (intres))
intres = drop_tree_overflow (intres);
ovfres = (arith_overflowed_p (opcode, type, arg0, arg1)
? boolean_true_node : boolean_false_node);
}
else
{
tree ctype = build_complex_type (type);
tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2,
arg0, arg1);
tree tgt = save_expr (call);
intres = build1_loc (loc, REALPART_EXPR, type, tgt);
ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
}
if (ovf_only)
return omit_one_operand_loc (loc, boolean_type_node, ovfres, arg2);
......
2019-02-21 Jakub Jelinek <jakub@redhat.com>
PR c++/89285
* constexpr.c (struct constexpr_fundef): Add parms and result members.
(retrieve_constexpr_fundef): Adjust for the above change.
(register_constexpr_fundef): Save constexpr body with copy_fn,
temporarily set DECL_CONTEXT on DECL_RESULT before that.
(get_fundef_copy): Change FUN argument to FUNDEF with
constexpr_fundef * type, grab body and parms/result out of
constexpr_fundef struct and temporarily change it for copy_fn calls
too.
(cxx_eval_builtin_function_call): For __builtin_FUNCTION temporarily
adjust current_function_decl from ctx->call context. Test
!potential_constant_expression instead of !is_constant_expression.
(cxx_bind_parameters_in_call): Grab parameters from new_call. Undo
convert_for_arg_passing changes for TREE_ADDRESSABLE type passing.
(cxx_eval_call_expression): Adjust get_fundef_copy caller.
(cxx_eval_conditional_expression): For IF_STMT, allow then or else
operands to be NULL.
(label_matches): Handle BREAK_STMT and CONTINUE_STMT.
(cxx_eval_loop_expr): Add support for FOR_STMT, WHILE_STMT and DO_STMT.
(cxx_eval_switch_expr): Add support for SWITCH_STMT.
(cxx_eval_constant_expression): Handle IF_STMT, FOR_STMT, WHILE_STMT,
DO_STMT, CONTINUE_STMT, SWITCH_STMT, BREAK_STMT and CONTINUE_STMT.
For SIZEOF_EXPR, recurse on the result of fold_sizeof_expr. Ignore
DECL_EXPR with USING_DECL operand.
* lambda.c (maybe_add_lambda_conv_op): Build thisarg using
build_int_cst to make it a valid constant expression.
2019-02-20 Jason Merrill <jason@redhat.com>
PR c++/88690 - C++17 ICE with empty base in aggregate.
......
......@@ -1087,8 +1087,7 @@ maybe_add_lambda_conv_op (tree type)
tree optype = TREE_TYPE (callop);
tree fn_result = TREE_TYPE (optype);
tree thisarg = build_nop (TREE_TYPE (DECL_ARGUMENTS (callop)),
null_pointer_node);
tree thisarg = build_int_cst (TREE_TYPE (DECL_ARGUMENTS (callop)), 0);
if (generic_lambda_p)
{
++processing_template_decl;
......
2019-02-21 Jakub Jelinek <jakub@redhat.com>
PR c++/89285
* g++.dg/ubsan/vptr-4.C: Expect reinterpret_cast errors.
* g++.dg/cpp1y/constexpr-84192.C (f2): Adjust expected diagnostics.
* g++.dg/cpp1y/constexpr-70265-2.C (foo): Adjust expected line of
diagnostics.
* g++.dg/cpp1y/constexpr-89285.C: New test.
* g++.dg/cpp0x/constexpr-arith-overflow.C (add, sub, mul): Ifdef out
for C++11.
(TEST_ADD, TEST_SUB, TEST_MUL): Define to Assert (true) for C++11.
* g++.dg/cpp0x/constexpr-arith-overflow2.C: New test.
2019-02-21 H.J. Lu <hongjiu.lu@intel.com>
PR target/87412
......
......@@ -27,6 +27,7 @@
#define Assert(expr) static_assert ((expr), #expr)
#if __cplusplus >= 201402L
template <class T>
constexpr T add (T x, T y, T z = T ())
{
......@@ -48,6 +49,11 @@ constexpr T mul (T x, T y, T z = T ())
#define TEST_ADD(T, x, y, z) Assert (z == add<T>(x, y))
#define TEST_SUB(T, x, y, z) Assert (z == sub<T>(x, y))
#define TEST_MUL(T, x, y, z) Assert (z == mul<T>(x, y))
#else
#define TEST_ADD(T, x, y, z) Assert (true)
#define TEST_SUB(T, x, y, z) Assert (true)
#define TEST_MUL(T, x, y, z) Assert (true)
#endif
TEST_ADD (signed char, 0, 0, 0);
......
// PR c++/70507 - integer overflow builtins not constant expressions
// The constexpr-arith-overflow.C testcase covers this for C++14 and later.
// { dg-do compile }
// { dg-options "-std=c++11" }
#define Assert(expr) static_assert ((expr), #expr)
template <class T>
constexpr T add (T x, T y, T z = T ())
{
return __builtin_add_overflow (x, y, &z) ? 0 : z; // { dg-error "is not a constant expression" }
}
template <class T>
constexpr T sub (T x, T y, T z = T ())
{
return __builtin_sub_overflow (x, y, &z) ? 0 : z; // { dg-error "is not a constant expression" }
}
template <class T>
constexpr T mul (T x, T y, T z = T ())
{
return __builtin_mul_overflow (x, y, &z) ? 0 : z; // { dg-error "is not a constant expression" }
}
Assert (0 == add<int>(0, 0)); // { dg-error "non-constant condition for static assertion" }
Assert (0 == sub<int>(0, 0)); // { dg-error "non-constant condition for static assertion" }
Assert (0 == mul<int>(0, 0)); // { dg-error "non-constant condition for static assertion" }
// { dg-message "expansion of" "" { target *-*-* } .-3 }
// { dg-message "expansion of" "" { target *-*-* } .-3 }
// { dg-message "expansion of" "" { target *-*-* } .-3 }
......@@ -5,8 +5,8 @@ constexpr int
foo (int p)
{
int t = 0;
while (1)
t = 0; // { dg-error "count exceeds" }
while (1) // { dg-error "count exceeds" }
t = 0;
return t;
}
......
......@@ -12,7 +12,7 @@ void
f2 ()
{
for (;;)
constexpr bool b = ({ break; false; }) && false; // { dg-error "statement is not a constant expression" }
constexpr bool b = ({ break; false; }) && false; // { dg-error "is not a constant expression" }
}
constexpr bool
......
// PR c++/89285
// { dg-do compile { target c++14 } }
struct A {
int a {};
};
struct B {
int b {};
constexpr B (A *x) {
int *c = &x->a;
while (*c)
c = reinterpret_cast<int *>((reinterpret_cast<char *>(c) + *c));
*c = reinterpret_cast<char *>(this) - reinterpret_cast<char *>(c); // { dg-error "reinterpret_cast" }
}
};
struct C : A {
B bar {this};
};
constexpr C foo {}; // { dg-message "expansion of" }
......@@ -15,11 +15,11 @@ struct T : S {
int b;
int g() { return 0; }
virtual int v() { return 1; }
constexpr const T *foo() { return (const T *) reinterpret_cast<const S *> (this); }
constexpr const T *foo() { return (const T *) reinterpret_cast<const S *> (this); } // { dg-error "is not a constant expression" }
};
constexpr T t;
constexpr const T *p = t.foo ();
constexpr const T *p = t.foo (); // { dg-message "expansion of" }
template <typename U>
struct V {
......@@ -39,16 +39,17 @@ struct W : V<U> {
};
constexpr W<int> w;
constexpr const W<int> *s = w.foo ();
constexpr const W<int> *s = w.foo (); // { dg-error "is not a constant expression" }
// { dg-message "expansion of" "" { target *-*-* } .-1 }
template <typename U>
int foo (void)
{
static constexpr T t;
static constexpr const T *p = t.foo ();
static constexpr const T *p = t.foo (); // { dg-message "expansion of" }
static constexpr W<U> w;
static constexpr const W<U> *s = w.foo ();
return t.b + w.b;
static constexpr const W<U> *s = w.foo (); // { dg-error "is not a constant expression" }
return t.b + w.b; // { dg-message "expansion of" "" { target *-*-* } .-1 }
}
int x = foo <char> ();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment