Attached is a resubmission of the patch for c++/60760 originally submitted late in the 6.0 cycle along with a patch for c++/67376. Since c++/60760 was not a regression, it was decided that it would be safer to defer the fix until after the 6.1.0 release.
While retesting this patch I was happy to notice that it also fixes another bug: c++/71091 - constexpr reference bound to a null pointer dereference accepted. Martin
PR c++/60760 - arithmetic on null pointers should not be allowed in constant expressions PR c++/71091 - constexpr reference bound to a null pointer dereference accepted gcc/testsuite/ChangeLog: 2016-05-12 Martin Sebor <mse...@redhat.com> PR c++/60760 PR c++/71091 * g++.dg/cpp0x/constexpr-nullptr-2.C: New test. * gcc/testsuite/g++.dg/ubsan/pr63956.C: Adjust. gcc/cp/ChangeLog: 2016-05-12 Martin Sebor <mse...@redhat.com> PR c++/60760 PR c++/71091 * constexpr.c (cxx_eval_call_expression): Add argument. (cxx_eval_unary_expression): Same. (cxx_eval_conditional_expression): Same. (cxx_eval_array_reference): Same. (cxx_fold_indirect_ref): Same. (cxx_eval_statement_list): Same. (cxx_eval_loop_expr): Same. (cxx_eval_binary_expression): Same. Detect and reject invalid uses of null pointers. (cxx_eval_component_reference): Same. (cxx_eval_constant_expression): Same. (cxx_eval_indirect_ref): Add argument. Detect invalid uses of null pointers without rejecting them here. (cxx_eval_outermost_constant_expr): Adjust. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 6054d1a..3821ad0 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -918,7 +918,8 @@ struct constexpr_ctx { static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table; static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, - bool, bool *, bool *, tree * = NULL); + bool, bool *, bool *, bool * = NULL, + tree * = NULL); /* Compute a hash value for a constexpr call representation. */ @@ -1491,7 +1492,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, tree jump_target = NULL_TREE; cxx_eval_constant_expression (&ctx_with_save_exprs, body, lval, non_constant_p, overflow_p, - &jump_target); + NULL, &jump_target); if (DECL_CONSTRUCTOR_P (fun)) /* This can be null for a subobject constructor call, in @@ -1716,20 +1717,21 @@ cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + bool *nullptr_p) { tree r = NULL_TREE; tree orig_lhs = TREE_OPERAND (t, 0); tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer subtraction. */ if (*non_constant_p) return t; rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); if (*non_constant_p) return t; @@ -1751,6 +1753,15 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, || null_member_pointer_value_p (rhs))) r = constant_boolean_node (!is_code_eq, type); } + if (code == POINTER_PLUS_EXPR && !*non_constant_p + && tree_int_cst_equal (lhs, null_pointer_node)) + { + if (!ctx->quiet) + error ("arithmetic involving null pointer %qE", lhs); + if (nullptr_p) + *nullptr_p = true; + return t; + } if (r == NULL_TREE) r = fold_binary_loc (loc, code, type, lhs, rhs); @@ -1791,11 +1802,11 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2), lval, non_constant_p, overflow_p, - jump_target); + NULL, jump_target); return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, non_constant_p, overflow_p, - jump_target); + NULL, jump_target); } /* Returns less than, equal to, or greater than zero if KEY is found to be @@ -2066,7 +2077,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + bool *nullptr_p) { unsigned HOST_WIDE_INT i; tree field; @@ -2075,7 +2087,14 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree orig_whole = TREE_OPERAND (t, 0); tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); + if (nullptr_p && *nullptr_p) + { + if (!ctx->quiet) + error ("%qE dereferences a null pointer", orig_whole); + } + if (TREE_CODE (whole) == PTRMEM_CST) whole = cplus_expand_constant (whole); if (whole == orig_whole) @@ -2807,7 +2826,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) static tree cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + bool *nullptr_p) { tree orig_op0 = TREE_OPERAND (t, 0); bool empty_base = false; @@ -2832,6 +2852,9 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, tree op0 = cxx_eval_constant_expression (ctx, orig_op0, /*lval*/false, non_constant_p, overflow_p); + if (nullptr_p && tree_int_cst_equal (op0, null_pointer_node)) + *nullptr_p = true; + /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -3328,7 +3351,7 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, } r = cxx_eval_constant_expression (ctx, stmt, false, non_constant_p, overflow_p, - jump_target); + NULL, jump_target); if (*non_constant_p) break; if (returns (jump_target) || breaks (jump_target)) @@ -3360,7 +3383,8 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, new_ctx.save_exprs = &save_exprs; cxx_eval_constant_expression (&new_ctx, body, /*lval*/false, - non_constant_p, overflow_p, jump_target); + non_constant_p, overflow_p, NULL, + jump_target); /* Forget saved values of SAVE_EXPRs. */ for (hash_set<tree>::iterator iter = save_exprs.begin(); @@ -3457,15 +3481,20 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t, } /* Attempt to reduce the expression T to a constant value. - On failure, issue diagnostic and return error_mark_node. */ + On failure, issue diagnostic and return error_mark_node. + Similar to NON_CONSTANT_P and OVERFLOW_P, when NULLPTR_P is non-null, + the object it points to is set to true when an invalid use of a null + pointer is detected. */ /* FIXME unify with c_fully_fold */ /* FIXME overflow_p is too global */ static tree cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p, - tree *jump_target) + bool *non_constant_p, + bool *overflow_p, + bool *nullptr_p, + tree *jump_target) { constexpr_ctx new_ctx; tree r = t; @@ -3484,10 +3513,22 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (!flag_permissive || ctx->quiet) *overflow_p = true; } + + if (TREE_CODE (t) == INTEGER_CST + && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE + && !integer_zerop (t)) + { + if (!ctx->quiet) + error ("null pointer arithmetic in %qE", t); + if (nullptr_p) + *nullptr_p = true; + } + return t; } - switch (TREE_CODE (t)) + tree_code tcode = TREE_CODE (t); + switch (tcode) { case RESULT_DECL: if (lval) @@ -3576,7 +3617,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { init = cxx_eval_constant_expression (ctx, init, false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); /* Don't share a CONSTRUCTOR that might be changed. */ init = unshare_constructor (init); ctx->values->put (r, init); @@ -3616,7 +3658,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, initialization of a temporary. */ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); if (!*non_constant_p) /* Adjust the type of the result to the type of the temporary. */ r = adjust_temp_type (TREE_TYPE (t), r); @@ -3638,14 +3681,16 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case SCOPE_REF: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); break; case RETURN_EXPR: if (TREE_OPERAND (t, 0) != NULL_TREE) r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); *jump_target = t; break; @@ -3656,7 +3701,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, else { r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); ctx->values->put (t, r); if (ctx->save_exprs) ctx->save_exprs->add (t); @@ -3673,18 +3719,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); break; case TRY_FINALLY_EXPR: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); if (!*non_constant_p) /* Also evaluate the cleanup. */ cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); break; /* These differ from cxx_eval_unary_expression in that this doesn't @@ -3693,7 +3739,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case MEM_REF: case INDIRECT_REF: r = cxx_eval_indirect_ref (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); break; case ADDR_EXPR: @@ -3701,7 +3747,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, /*lval*/true, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -3744,19 +3791,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, || TREE_CODE (op1) == EMPTY_CLASS_EXPR) r = cxx_eval_constant_expression (ctx, op0, lval, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); else { /* Check that the LHS is constant and then discard it. */ cxx_eval_constant_expression (ctx, op0, true, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); if (*non_constant_p) return t; op1 = TREE_OPERAND (t, 1); r = cxx_eval_constant_expression (ctx, op1, lval, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); } } break; @@ -3807,7 +3854,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case RANGE_EXPR: case COMPLEX_EXPR: r = cxx_eval_binary_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); break; /* fold can introduce non-IF versions of these; still treat them as @@ -3845,7 +3892,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } r = cxx_eval_component_reference (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); break; case BIT_FIELD_REF: @@ -3898,12 +3945,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case NOP_EXPR: case UNARY_PLUS_EXPR: { - enum tree_code tcode = TREE_CODE (t); tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + nullptr_p); if (*non_constant_p) return t; tree type = TREE_TYPE (t); @@ -3924,15 +3971,28 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } } - if (POINTER_TYPE_P (type) - && TREE_CODE (op) == INTEGER_CST - && !integer_zerop (op)) - { - if (!ctx->quiet) - error_at (EXPR_LOC_OR_LOC (t, input_location), - "reinterpret_cast from integer to pointer"); - *non_constant_p = true; - return t; + if (POINTER_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST) + { + const char *msg = NULL; + if (integer_zerop (op)) + { + if (nullptr_p) + *nullptr_p = true; + if (!same_type_ignoring_top_level_qualifiers_p (type, + TREE_TYPE (op))) + msg = "invalid conversion involving a null pointer"; + } + else + msg = "reinterpret_cast from integer to pointer"; + + if (msg) + { + if (!ctx->quiet) + error_at (EXPR_LOC_OR_LOC (t, input_location), msg); + + *non_constant_p = true; + return t; + } } if (op == oldop && tcode != UNARY_PLUS_EXPR) /* We didn't fold at the top so we could check for ptr-int @@ -3965,7 +4025,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return cxx_eval_constant_expression (ctx, BIND_EXPR_BODY (t), lval, non_constant_p, overflow_p, - jump_target); + nullptr_p, jump_target); case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: @@ -4014,7 +4074,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, tree ctor = lval ? ctx->object : ctx->ctor; return cxx_eval_constant_expression (ctx, ctor, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, nullptr_p); } break; @@ -4132,8 +4192,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, r = TARGET_EXPR_INITIAL (r); } - r = cxx_eval_constant_expression (&ctx, r, - false, &non_constant_p, &overflow_p); + bool nullptr_p = false; + r = cxx_eval_constant_expression (&ctx, r, false, + &non_constant_p, &overflow_p, &nullptr_p); verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C new file mode 100644 index 0000000..9ee1316 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C @@ -0,0 +1,191 @@ +// PR c++/60760 - arithmetic on null pointers should not be allowed +// in constant expressions +// PR c++/71091 - constexpr reference bound to a null pointer dereference +// accepted +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wno-pointer-arith" } + +// Generate a null poiinter. +constexpr int* null () { return 0; } + +// Test case from comment #0 in c++/60760. +namespace PR_60760_comment_0 { + +constexpr int* ptr = nullptr; +constexpr int* ptr2 = ptr + 1; // { dg-error "null pointer|not a constant" } + +} + +// Test case from comment #1 in c++/60760. +namespace PR_60760_comment_1 { + +constexpr int* ptr = nullptr; +constexpr int x = 0; +constexpr int* ptr2 = ptr + x; // Adding zero is valid. +constexpr int* ptr3 = ptr - x; // As is subtracting zero. + +} + +// Test case from c++/71091. +namespace PR_71091 { + +constexpr int *p = 0; +constexpr int &r = *p; // { dg-error "null pointer" } + +} + +// Other testr cases. +namespace C { + +struct S { int a, b[1]; } s; + +constexpr S *p0 = &s; +constexpr S *p1 = nullptr; + +constexpr int *r0 = p1->b; // { dg-error "null pointer|constant expression" } + +} + +namespace D { + +struct A { int i; const A *pa1; const A *pa0; }; + +constexpr A a1 = { 0, 0, 0 }; +constexpr A a2 = { 1, &a1, 0 }; + +constexpr const A *pa2 = &a2; +constexpr int i0 = pa2->i; +constexpr int i1 = pa2->pa1->i; +constexpr int i2 = pa2->pa1->pa0->i; // { dg-error "null pointer|not a constant" } + +constexpr const A *pa3 = &*pa2->pa1->pa0; +constexpr const A *pa4 = pa2->pa1->pa0 + 1; // { dg-error "null pointer|not a constant" } + +constexpr const int *pi0 = &pa2->pa1->pa0->i; // { dg-error "null pointer|not a constant" } + +constexpr const A *pa5 = 0; +constexpr const int *pi1 = &pa5->i; // { dg-error "null pointer|not a constant" } + +} + + +namespace SimpleTests { + +constexpr int* p0 = nullptr; +constexpr int* q0 = p0; +constexpr int* r0 = null (); + +// Adding or subtracting zero from a null pointer is valid in C++. +constexpr int* p1 = p0 + 0; +constexpr int* p2 = p0 - 0; +constexpr int* p3 = 0 + p0; + +// While the text of the C++ standard still doesn't allow it, CWG +// issue 232 implies that dererencing a null pointer is intended +// to be permitted in contexts where the result isn't evaluated. +// For compatibility with C that should at a minimum include +// expressions like &*p that are valid there. +constexpr int* p4 = &*p0; +constexpr int* p5 = p0 + 1; // { dg-error "null pointer|not a constant" } +constexpr int* p6 = 1 + p0; // { dg-error "null pointer|not a constant" } +constexpr int* p7 = p0 - 1; // { dg-error "null pointer|not a constant" } +constexpr int* p8 = &p0 [0]; +constexpr int* p9 = &0 [p0]; + +constexpr int* p10 = null () + 2; // { dg-error "null pointer|not a constant" } +constexpr int* p11 = 3 + null (); // { dg-error "null pointer|not a constant" } +constexpr int* p12 = null () - 4; // { dg-error "null pointer|not a constant" } +constexpr int* p13 = &null ()[4]; // { dg-error "null pointer|not a constant" } +constexpr int* p14 = &3[null ()]; // { dg-error "null pointer|not a constant" } + +constexpr int* q1 = q0 + 0; +constexpr int* q2 = q0 - 0; +constexpr int* q3 = q0 + 1; // { dg-error "null pointer|not a constant" } +constexpr int* q4 = q0 + 2; // { dg-error "null pointer|not a constant" } +constexpr int* q5 = &q0 [0]; + +// Subtracting null pointers from one another is valid. +constexpr int i0 = p0 - (int*)0; +constexpr int i1 = p0 - static_cast<int*>(0); +constexpr int i2 = p0 - (int*)nullptr; +constexpr int i3 = p0 - static_cast<int*>(nullptr); +constexpr int i4 = p0 - p0; +constexpr int i5 = p0 - q0; +constexpr int i6 = p0 - r0; +constexpr int i7 = (int*)0 - p0; +constexpr int i8 = static_cast<int*>(0) - p0; +constexpr int i9 = (int*)nullptr - p0; +constexpr int i10 = static_cast<int*>(nullptr) - p0; +constexpr int i11 = q0 - p0; +constexpr int i12 = r0 - p0; + +} + +namespace IndirectTests { + +struct S { int i, j; struct SA { struct SB { int *pi; } sb; } sa; }; + +constexpr S* ps = (S*)0; + +// Comparing null pointers is valid. +constexpr bool b0 = ps == ps; +constexpr bool b1 = ps != ps; +constexpr bool b2 = ps < ps; +constexpr bool b3 = ps <= ps; +constexpr bool b4 = ps > ps; +constexpr bool b5 = ps >= ps; + +constexpr bool b6 = ps == (S*)0; +constexpr bool b7 = ps != (S*)0; +constexpr bool b8 = ps < (S*)0; +constexpr bool b9 = ps <= (S*)0; +constexpr bool b10 = ps > (S*)0; +constexpr bool b11 = ps >= (S*)0; + +constexpr S* ps1 = ps; +constexpr S* ps2 = ps1; + +// The following aren't diagnosed due to a bug. +// constexpr int* pi0 = &((S*)0)->i; +// constexpr int* pi1 = &((S*)nullptr)->i; + +constexpr int* pj0 = &((S*)0)->j; // { dg-error "null pointer|not a constant" } +constexpr int* pj1 = &((S*)nullptr)->j; // { dg-error "null pointer|not a constant" } + +constexpr int* psi = &ps->i; // { dg-error "null pointer|not a constant" } +constexpr int* psj = &ps->j; // { dg-error "null pointer|not a constant" } + +constexpr int* ps1i = &ps1->i; // { dg-error "null pointer|not a constant" } +constexpr int* ps2i = &ps1->i; // { dg-error "null pointer|not a constant" } + +constexpr int* ps1j = &ps1->j; // { dg-error "null pointer|not a constant" } +constexpr int* ps2j = &ps1->j; // { dg-error "null pointer|not a constant" } + +} + +namespace FunctionTests { + +typedef void Func (); + +// Arithmetic on member function pointers is diagnosed with -Wpointer-arith. +// With constexpr, only zero may be added or subtracted. +constexpr Func *pf0 = 0; +constexpr Func *pf1 = pf0 + 0; // triggers -Wpointer-arith +constexpr Func *pf2 = pf0 - 0; // triggers -Wpointer-arith +constexpr Func *pf3 = 0 + pf0; // triggers -Wpointer-arith +constexpr Func *pf4 = pf0 + 1; // { dg-error "null pointer|not a constant" } +constexpr Func *pf5 = 2 + pf0; // { dg-error "null pointer|not a constant" } +constexpr Func *pf6 = pf0 - 3; // { dg-error "null pointer|not a constant" } + +struct S; +typedef void (S::*MemFuncPtr)(); + +// Arithmetic on member function pointers is rejected with a hard error. +constexpr MemFuncPtr pmf0 = nullptr; +constexpr MemFuncPtr pmf1 = pmf0 + 0; // { dg-error "invalid operands" } +constexpr MemFuncPtr pmf2 = 0 + pmf0; // { dg-error "invalid operands" } +constexpr MemFuncPtr pmf3 = pmf0 + 1; // { dg-error "invalid operands" } +constexpr MemFuncPtr pmf4 = 1 + pmf0; // { dg-error "invalid operands" } +constexpr MemFuncPtr pmf5 = pmf0 - 1; // { dg-error "invalid operands" } + +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C index 25db8a4..ac01fa4 100644 --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C @@ -92,7 +92,7 @@ constexpr int fn6 (const int &a, int b) { if (b != 2) - b = a; // { dg-error "is not a constant expression" } + b = a; return b; } @@ -106,7 +106,7 @@ fn7 (const int *a, int b) constexpr int n1 = 7; constexpr int n2 = fn7 (&n1, 5); -constexpr int n3 = fn7 ((const int *) 0, 8); +constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "null pointer" } constexpr int fn8 (int i)