Message ID | 20230329023258.13487-4-nathanieloshead@gmail.com |
---|---|
State | New |
Headers | show |
Series | c++: Track lifetimes in constant evaluation [PR70331, ...] | expand |
On Wed, 29 Mar 2023, Nathaniel Shead via Gcc-patches wrote: > This patch caches the current expression's location information in the > constexpr_global_ctx struct, which allows subexpressions that have lost > location information to still provide accurate diagnostics. Also > rewrites a number of 'error' calls as 'error_at' to provide more > specific location information. > > The primary effect of this change is that many errors within evaluation > of a constexpr function will now point at the offending expression (with > expansion tracing information) rather than just the outermost call. This seems like a great improvement! In other parts of the frontend, e.g. during substitution from tsubst_expr or tsubst_copy_and_build, we do something similar by setting/restoring input_location directly. (We've since added the RAII class iloc_sentinel for this.) I wonder if that'd be preferable here? > > gcc/cp/ChangeLog: > > * constexpr.cc (constexpr_global_ctx): New field for cached > tree location, defaulting to input_location. > (cxx_eval_internal_function): Fall back to ctx->global->loc > rather than input_location. > (modifying_const_object_error): Likewise. > (cxx_eval_dynamic_cast_fn): Likewise. > (eval_and_check_array_index): Likewise. > (cxx_eval_array_reference): Likewise. > (cxx_eval_bit_field_ref): Likewise. > (cxx_eval_component_reference): Likewise. > (cxx_eval_indirect_ref): Likewise. > (cxx_eval_store_expression): Likewise. > (cxx_eval_increment_expression): Likewise. > (cxx_eval_loop_expr): Likewise. > (cxx_eval_binary_expression): Likewise. > (cxx_eval_constant_expression): Cache location of trees for use > in errors, and prefer it instead of input_location. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations. > * g++.dg/cpp0x/constexpr-diag3.C: Likewise. > * g++.dg/cpp0x/constexpr-ice20.C: Likewise. > * g++.dg/cpp1y/constexpr-89481.C: Likewise. > * g++.dg/cpp1y/constexpr-lifetime1.C: Likewise. > * g++.dg/cpp1y/constexpr-lifetime2.C: Likewise. > * g++.dg/cpp1y/constexpr-lifetime3.C: Likewise. > * g++.dg/cpp1y/constexpr-lifetime4.C: Likewise. > * g++.dg/cpp1y/constexpr-lifetime5.C: Likewise. > * g++.dg/cpp1y/constexpr-union5.C: Likewise. > * g++.dg/cpp1y/pr68180.C: Likewise. > * g++.dg/cpp1z/constexpr-lambda6.C: Likewise. > * g++.dg/cpp2a/bit-cast11.C: Likewise. > * g++.dg/cpp2a/bit-cast12.C: Likewise. > * g++.dg/cpp2a/bit-cast14.C: Likewise. > * g++.dg/cpp2a/constexpr-98122.C: Likewise. > * g++.dg/cpp2a/constexpr-dynamic17.C: Likewise. > * g++.dg/cpp2a/constexpr-init1.C: Likewise. > * g++.dg/cpp2a/constexpr-new12.C: Likewise. > * g++.dg/cpp2a/constexpr-new3.C: Likewise. > * g++.dg/ext/constexpr-vla2.C: Likewise. > * g++.dg/ext/constexpr-vla3.C: Likewise. > * g++.dg/ubsan/pr63956.C: Likewise. > > libstdc++/ChangeLog: > > * testsuite/25_algorithms/equal/constexpr_neg.cc: Updated > diagnostics locations. > > Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> > --- > gcc/cp/constexpr.cc | 83 +++++++++++-------- > gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C | 10 +-- > gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C | 2 +- > gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C | 4 +- > gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C | 3 +- > .../g++.dg/cpp1y/constexpr-lifetime1.C | 1 + > .../g++.dg/cpp1y/constexpr-lifetime2.C | 4 +- > .../g++.dg/cpp1y/constexpr-lifetime3.C | 4 +- > .../g++.dg/cpp1y/constexpr-lifetime4.C | 2 +- > .../g++.dg/cpp1y/constexpr-lifetime5.C | 4 +- > gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C | 4 +- > gcc/testsuite/g++.dg/cpp1y/pr68180.C | 4 +- > .../g++.dg/cpp1z/constexpr-lambda6.C | 4 +- > gcc/testsuite/g++.dg/cpp2a/bit-cast11.C | 10 +-- > gcc/testsuite/g++.dg/cpp2a/bit-cast12.C | 10 +-- > gcc/testsuite/g++.dg/cpp2a/bit-cast14.C | 14 ++-- > gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C | 4 +- > .../g++.dg/cpp2a/constexpr-dynamic17.C | 5 +- > gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C | 5 +- > gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C | 6 +- > gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C | 10 +-- > gcc/testsuite/g++.dg/ext/constexpr-vla2.C | 4 +- > gcc/testsuite/g++.dg/ext/constexpr-vla3.C | 4 +- > gcc/testsuite/g++.dg/ubsan/pr63956.C | 4 +- > .../25_algorithms/equal/constexpr_neg.cc | 7 +- > 25 files changed, 111 insertions(+), 101 deletions(-) > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > index bdbc12144a7..74045477a92 100644 > --- a/gcc/cp/constexpr.cc > +++ b/gcc/cp/constexpr.cc > @@ -1165,10 +1165,12 @@ public: > hash_set<tree> *modifiable; > /* Number of heap VAR_DECL deallocations. */ > unsigned heap_dealloc_count; > + /* Current location in case subtree has no location information. */ > + location_t loc; > /* Constructor. */ > constexpr_global_ctx () > : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr), > - heap_dealloc_count (0) {} > + heap_dealloc_count (0), loc (input_location) {} > > tree get_value (tree t) > { > @@ -2113,7 +2115,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, > > default: > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > "call to internal function %qE", t); > *non_constant_p = true; > return t; > @@ -2128,7 +2130,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, > > if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) > { > - location_t loc = cp_expr_loc_or_input_loc (t); > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > tree type = TREE_TYPE (TREE_TYPE (t)); > tree result = fold_binary_loc (loc, opcode, type, > fold_convert_loc (loc, type, arg0), > @@ -2164,9 +2166,9 @@ clear_no_implicit_zero (tree ctor) > EXPR is the MODIFY_EXPR expression performing the modification. */ > > static void > -modifying_const_object_error (tree expr, tree obj) > +modifying_const_object_error (const constexpr_ctx* ctx, tree expr, tree obj) > { > - location_t loc = cp_expr_loc_or_input_loc (expr); > + location_t loc = cp_expr_loc_or_loc (expr, ctx->global->loc); > auto_diagnostic_group d; > error_at (loc, "modifying a const object %qE is not allowed in " > "a constant expression", TREE_OPERAND (expr, 0)); > @@ -2358,7 +2360,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, > tree obj = CALL_EXPR_ARG (call, 0); > tree type = CALL_EXPR_ARG (call, 2); > HOST_WIDE_INT hint = int_cst_value (CALL_EXPR_ARG (call, 3)); > - location_t loc = cp_expr_loc_or_input_loc (call); > + location_t loc = cp_expr_loc_or_loc (call, ctx->global->loc); > > /* Get the target type of the dynamic_cast. */ > gcc_assert (TREE_CODE (type) == ADDR_EXPR); > @@ -3656,7 +3658,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, > && integer_zerop (lhs) && !integer_zerop (rhs)) > { > if (!ctx->quiet) > - error ("arithmetic involving a null pointer in %qE", lhs); > + error_at (loc, "arithmetic involving a null pointer in %qE", lhs); > *non_constant_p = true; > return t; > } > @@ -4149,7 +4151,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, > tree t, bool allow_one_past, > bool *non_constant_p, bool *overflow_p) > { > - location_t loc = cp_expr_loc_or_input_loc (t); > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > tree ary = TREE_OPERAND (t, 0); > t = TREE_OPERAND (t, 1); > tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue, > @@ -4187,6 +4189,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, > value_cat lval, > bool *non_constant_p, bool *overflow_p) > { > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > tree oldary = TREE_OPERAND (t, 0); > tree ary = cxx_eval_constant_expression (ctx, oldary, > lval, > @@ -4274,7 +4277,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, > building; if there's no initializer for this element yet, > that's an error. */ > if (!ctx->quiet) > - error ("accessing uninitialized array element"); > + error_at (loc, "accessing uninitialized array element"); > *non_constant_p = true; > return t; > } > @@ -4323,13 +4326,14 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > tree whole = cxx_eval_constant_expression (ctx, orig_whole, > lval, > non_constant_p, overflow_p); > + location_t loc = cp_expr_loc_or_loc (whole, ctx->global->loc); > if (*non_constant_p) > return t; > if (INDIRECT_REF_P (whole) > && integer_zerop (TREE_OPERAND (whole, 0))) > { > if (!ctx->quiet) > - error ("dereferencing a null pointer in %qE", orig_whole); > + error_at (loc, "dereferencing a null pointer in %qE", orig_whole); > *non_constant_p = true; > return t; > } > @@ -4348,7 +4352,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > if (TREE_CODE (whole) != CONSTRUCTOR) > { > if (!ctx->quiet) > - error ("%qE is not a constant expression", orig_whole); > + error_at (loc, "%qE is not a constant expression", orig_whole); > *non_constant_p = true; > return t; > } > @@ -4356,7 +4360,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > && DECL_MUTABLE_P (part)) > { > if (!ctx->quiet) > - error ("mutable %qD is not usable in a constant expression", part); > + error_at (loc, "mutable %qD is not usable in a constant expression", part); > *non_constant_p = true; > return t; > } > @@ -4386,10 +4390,10 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > { > constructor_elt *cep = CONSTRUCTOR_ELT (whole, 0); > if (cep->value == NULL_TREE) > - error ("accessing uninitialized member %qD", part); > + error_at (loc, "accessing uninitialized member %qD", part); > else > - error ("accessing %qD member instead of initialized %qD member in " > - "constant expression", part, cep->index); > + error_at (loc, "accessing %qD member instead of initialized %qD member " > + "in constant expression", part, cep->index); > } > *non_constant_p = true; > return t; > @@ -4408,7 +4412,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > building; if there's no initializer for this member yet, that's an > error. */ > if (!ctx->quiet) > - error ("accessing uninitialized member %qD", part); > + error_at (loc, "accessing uninitialized member %qD", part); > *non_constant_p = true; > return t; > } > @@ -4436,6 +4440,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > tree whole = cxx_eval_constant_expression (ctx, orig_whole, > lval, > non_constant_p, overflow_p); > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > tree start, field, value; > unsigned HOST_WIDE_INT i; > > @@ -4448,7 +4453,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > && TREE_CODE (whole) != CONSTRUCTOR) > { > if (!ctx->quiet) > - error ("%qE is not a constant expression", orig_whole); > + error_at (loc, "%qE is not a constant expression", orig_whole); > *non_constant_p = true; > } > if (*non_constant_p) > @@ -4460,7 +4465,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > TREE_OPERAND (t, 1), TREE_OPERAND (t, 2))) > return r; > if (!ctx->quiet) > - error ("%qE is not a constant expression", orig_whole); > + error_at (loc, "%qE is not a constant expression", orig_whole); > *non_constant_p = true; > return t; > } > @@ -5609,6 +5614,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > value_cat lval, > bool *non_constant_p, bool *overflow_p) > { > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > tree orig_op0 = TREE_OPERAND (t, 0); > bool empty_base = false; > > @@ -5639,7 +5645,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > if (!lval && integer_zerop (op0)) > { > if (!ctx->quiet) > - error ("dereferencing a null pointer"); > + error_at (loc, "dereferencing a null pointer"); > *non_constant_p = true; > return t; > } > @@ -5658,8 +5664,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); > /* DR 1188 says we don't have to deal with this. */ > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > - "accessing value of %qE through a %qT glvalue in a " > + error_at (loc, "accessing value of %qE through a %qT glvalue in a " > "constant expression", build_fold_indirect_ref (sub), > TREE_TYPE (t)); > *non_constant_p = true; > @@ -5906,6 +5911,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > value_cat lval, > bool *non_constant_p, bool *overflow_p) > { > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > constexpr_ctx new_ctx = *ctx; > > tree init = TREE_OPERAND (t, 1); > @@ -6030,7 +6036,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > /* A constant-expression cannot modify objects from outside the > constant-expression. */ > if (!ctx->quiet) > - error ("modification of %qE is not a constant expression", object); > + error_at (loc, "modification of %qE is not a constant expression", object); > *non_constant_p = true; > return t; > } > @@ -6128,7 +6134,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > if (cxx_dialect < cxx20) > { > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > "change of the active member of a union " > "from %qD to %qD", > CONSTRUCTOR_ELT (*valp, 0)->index, > @@ -6141,7 +6147,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > /* Diagnose changing the active union member while the union > is in the process of being initialized. */ > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > "change of the active member of a union " > "from %qD to %qD during initialization", > CONSTRUCTOR_ELT (*valp, 0)->index, > @@ -6224,7 +6230,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > if (fail) > { > if (!ctx->quiet) > - modifying_const_object_error (t, const_object_being_modified); > + modifying_const_object_error (ctx, t, const_object_being_modified); > *non_constant_p = true; > return t; > } > @@ -6381,6 +6387,8 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, > tree offset = TREE_OPERAND (t, 1); > gcc_assert (TREE_CONSTANT (offset)); > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > + > /* OFFSET is constant, but perhaps not constant enough. We need to > e.g. bash FLOAT_EXPRs to REAL_CSTs. */ > offset = fold_simple (offset); > @@ -6428,8 +6436,7 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, > VERIFY_CONSTANT (mod); > > /* Storing the modified value. */ > - tree store = build2_loc (cp_expr_loc_or_loc (t, input_location), > - MODIFY_EXPR, type, op, mod); > + tree store = build2_loc (loc, MODIFY_EXPR, type, op, mod); > mod = cxx_eval_constant_expression (ctx, store, lval, > non_constant_p, overflow_p); > ggc_free (store); > @@ -6602,6 +6609,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, > bool *non_constant_p, bool *overflow_p, > tree *jump_target) > { > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > constexpr_ctx new_ctx = *ctx; > tree local_target; > if (!jump_target) > @@ -6691,7 +6699,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, > if (++count >= constexpr_loop_limit) > { > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > + error_at (loc, > "%<constexpr%> loop iteration count exceeds limit of %d " > "(use %<-fconstexpr-loop-limit=%> to increase the limit)", > constexpr_loop_limit); > @@ -6950,7 +6958,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > return t; > } > > - location_t loc = cp_expr_loc_or_input_loc (t); > + /* Track current location, propagating down from parent calls > + in case this expression has no location information. */ > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > + ctx->global->loc = loc; > > STRIP_ANY_LOCATION_WRAPPER (t); > > @@ -6973,8 +6984,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > && !integer_zerop (t)) > { > if (!ctx->quiet) > - error ("value %qE of type %qT is not a constant expression", > - t, TREE_TYPE (t)); > + error_at (loc, "value %qE of type %qT is not a constant expression", > + t, TREE_TYPE (t)); > *non_constant_p = true; > } > > @@ -7222,8 +7233,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > if (!ctx->quiet) > { > auto_diagnostic_group d; > - error ("temporary of non-literal type %qT in a " > - "constant expression", type); > + error_at (loc, "temporary of non-literal type %qT in a " > + "constant expression", type); > explain_non_literal_class (type); > } > *non_constant_p = true; > @@ -8025,8 +8036,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > if (function_concept_p (tmpl)) > { > if (!ctx->quiet) > - error_at (cp_expr_loc_or_input_loc (t), > - "function concept must be called"); > + error_at (loc, "function concept must be called"); > r = error_mark_node; > break; > } > @@ -8121,6 +8131,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > break; > } > > + /* Reset current location in case it was modified in child calls. */ > + ctx->global->loc = loc; > + > if (r == error_mark_node) > *non_constant_p = true; > > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > index 4574eb83ff7..11630f26ffe 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > @@ -10,11 +10,11 @@ > // R() is well-formed because i is initialized before j. > > struct s { > - constexpr s() : v(v) { } > + constexpr s() : v(v) { } // { dg-error "accessing uninitialized member" } > int v; > }; > > -constexpr s bang; // { dg-error "|" } > +constexpr s bang; // { dg-message "in .constexpr. expansion" } > > struct R { > int i,j; > @@ -26,14 +26,14 @@ constexpr R r; // { dg-bogus "" } > // Ill-formed (no diagnostic required) > struct T { > int i; > - constexpr int f() { return i; } > + constexpr int f() { return i; } // { dg-error "accessing uninitialized member" } > constexpr T(): i(0) { } > - constexpr T(const T& t) : i(f()) { } // { dg-message "" } > + constexpr T(const T& t) : i(f()) { } // { dg-message "in .constexpr. expansion" } > }; > > constexpr T t1; > // Ill-formed (diagnostic required) > -constexpr T t2(t1); // { dg-message "" } > +constexpr T t2(t1); // { dg-message "in .constexpr. expansion" } > > // Well-formed > struct U { > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > index 5eedf42ba36..50c676c56cd 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > @@ -16,7 +16,7 @@ int main() > struct complex // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } } > { > complex(double r, double i) : re(r), im(i) { } > - constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } } > + constexpr double real() const { return re; } // { dg-error "not a literal type|not usable in a constant expression" "" { target { ! implicit_constexpr } } } > double imag() const { return im; } > > private: > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > index ebaa95e5324..e4e3bf865cd 100644 > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > @@ -2,6 +2,6 @@ > // { dg-do compile { target c++11 } } > > typedef bool (*Function)(int); > -constexpr bool check(int x, Function p) { return p(x); } // { dg-message "in .constexpr. expansion of" } > +constexpr bool check(int x, Function p) { return p(x); } // { dg-error "lifetime" } > > -static_assert(check(2, check), ""); // { dg-error "conversion|constant|lifetime|in .constexpr. expansion of" } > +static_assert(check(2, check), ""); // { dg-error "conversion|constant|in .constexpr. expansion of" } > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > index 8ac4ef0fd36..6f8f6a8038e 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > @@ -6,7 +6,7 @@ foo () > { > union U { long long a; int b[2]; } u { 5LL }; > u.b[1] = 4; // { dg-error "change of the active member of a union from" "" { target c++17_down } } > - return u.b[0]; > + return u.b[0]; // { dg-error "accessing uninitialized array element" "" { target c++2a } } > } > > constexpr int > @@ -19,6 +19,5 @@ bar () > > static_assert (foo () == 0, ""); // { dg-error "non-constant condition for static assertion" } > // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > - // { dg-error "accessing uninitialized array element" "" { target c++2a } .-2 } > static_assert (bar () == 4, ""); // { dg-error "non-constant condition for static assertion" "" { target c++17_down } } > // { dg-message "in 'constexpr' expansion of" "" { target c++17_down } .-1 } > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > index 43aa7c974c1..f79f1611d5f 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > @@ -11,3 +11,4 @@ constexpr const int& test() { > return local.get(); > } > constexpr int x = test(); // { dg-error "accessing object outside its lifetime" } > + > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > index 22cd919fcda..2f5ae8db6d5 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > @@ -8,9 +8,9 @@ struct S { > > constexpr int error() { > const auto& local = S{}.get(); // { dg-message "note: declared here" } > - return local; > + return local; // { dg-error "accessing object outside its lifetime" } > } > -constexpr int x = error(); // { dg-error "accessing object outside its lifetime" } > +constexpr int x = error(); // { dg-message "in .constexpr. expansion" } > > constexpr int ok() { > // temporary should only be destroyed after end of full-expression > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > index 6329f8cf6c6..53785521d05 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > @@ -7,7 +7,7 @@ constexpr int f(int i) { > int j = 123; // { dg-message "note: declared here" } > p = &j; > } > - return *p; > + return *p; // { dg-error "accessing object outside its lifetime" } > } > > -constexpr int i = f(0); // { dg-error "accessing object outside its lifetime" } > +constexpr int i = f(0); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > index 181a1201663..4302da1eddc 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > @@ -5,7 +5,7 @@ constexpr const double& test() { > return local; > } > > -static_assert(test() == 3.0, ""); // { dg-error "constant|accessing object outside its lifetime" } > +static_assert(test() == 3.0, ""); // { dg-error "non-constant condition|accessing object outside its lifetime" } > > // no deference, shouldn't error > static_assert((test(), true), ""); > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > index ad3ef579f63..a12920c8fba 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > @@ -5,7 +5,7 @@ constexpr const int& id(int x) { return x; } // { dg-message "note: declared he > > constexpr bool test() { > const int& y = id(3); > - return y == 3; > + return y == 3; // { dg-error "accessing object outside its lifetime" } > } > > -constexpr bool x = test(); // { dg-error "accessing object outside its lifetime" } > +constexpr bool x = test(); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > index 55fe9fa2f0b..3d76345d564 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > @@ -8,8 +8,8 @@ union U { > }; > > constexpr int foo(U *up) { > - up->a++; > + up->a++; // { dg-error "accessing uninitialized member" } > return {42}; > } > > -extern constexpr U u = {}; // { dg-error "accessing uninitialized member" } > +extern constexpr U u = {}; // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68180.C b/gcc/testsuite/g++.dg/cpp1y/pr68180.C > index 9e6e5e984f9..8de1ef3936b 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/pr68180.C > +++ b/gcc/testsuite/g++.dg/cpp1y/pr68180.C > @@ -6,11 +6,11 @@ typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t; > constexpr float32x4_t fill(float x) { > float32x4_t v{0}; > constexpr auto vs = sizeof(v)/sizeof(v[0]); > - for (auto i=0U; i<vs; ++i) v[i]=i; > + for (auto i=0U; i<vs; ++i) v[i]=i; // { dg-error "not a constant" } > return v+x; > } > > float32x4_t foo(float32x4_t x) { > - constexpr float32x4_t v = fill(1.f); // { dg-error "not a constant||in .constexpr. expansion of " } > + constexpr float32x4_t v = fill(1.f); // { dg-message "in .constexpr. expansion of " } > return x+v; > } > diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > index 214d3821299..c46c2d4c7fe 100644 > --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > @@ -1,7 +1,7 @@ > // Testcase from P0170R1 > // { dg-do compile { target c++17 } } > > -auto monoid = [](auto v) { return [=] { return v; }; }; > +auto monoid = [](auto v) { return [=] { return v; }; }; // { dg-error "not usable in a constant expression" } > auto add = [](auto m1) constexpr { > auto ret = m1(); > return [=](auto m2) mutable { > @@ -22,7 +22,7 @@ int main() > // member function call operator can not perform an lvalue-to-rvalue conversion > // on one of its subobjects (that represents its capture) in a constant > // expression. > - auto two = monoid(2); > + auto two = monoid(2); // { dg-message "not declared .constexpr." } > if (!(two() == 2)) __builtin_abort(); // OK, not a constant expression. > static_assert(add(one)(one)() == two()); // { dg-error "|in .constexpr. expansion of " } two() is not a constant expression > static_assert(add(one)(one)() == monoid(2)()); // OK > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > index a3eb31bc6c7..760c9ca40b4 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > @@ -28,7 +28,7 @@ f3 () > { > T t = { 1, 2 }; > S s = __builtin_bit_cast (S, t); > - return s.a[1] == 0; > + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } > } > > constexpr bool > @@ -52,12 +52,12 @@ f6 () > { > W t = { 1, 2 }; > V s = __builtin_bit_cast (V, t); > - return s.b.a[1] == 1; > + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } > } > > constexpr bool a = f1 (); > constexpr bool b = f2 (); > -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } > -constexpr bool d = f4 (); > +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > constexpr bool e = f5 (); > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > index 9c699dd55f0..e205bc6a8c1 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > @@ -33,7 +33,7 @@ f3 () > { > T t = { 1, 2 }; > S s = __builtin_bit_cast (S, t); > - return s.a[1] == 0; > + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } > } > > constexpr bool > @@ -57,12 +57,12 @@ f6 () > { > W t = { 1, 2 }; > V s = __builtin_bit_cast (V, t); > - return s.b.a[1] == 1; > + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } > } > > constexpr bool a = f1 (); > constexpr bool b = f2 (); > -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } > -constexpr bool d = f4 (); > +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > constexpr bool e = f5 (); > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > index 5e185919be4..e0cc9a39702 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > @@ -44,7 +44,7 @@ f5 () > { > T1 t = { 0, 0, 0, 0, 0, 0, 0 }; > S s = __builtin_bit_cast (S, t); > - unsigned char a = s.a; > + unsigned char a = s.a; // { dg-error "accessing uninitialized member" } > return true; > } > > @@ -53,7 +53,7 @@ f6 () > { > T2 t = { 0, 0, 0, 0, 0, 0, 0 }; > S s = __builtin_bit_cast (S, t); > - unsigned char b = s.b; > + unsigned char b = s.b; // { dg-error "accessing uninitialized member" } > return true; > } > > @@ -62,14 +62,14 @@ f7 () > { > T3 t = { 0, 0, 0, 0, 0, 0, 0 }; > S s = __builtin_bit_cast (S, t); > - unsigned char c = s.c; > + unsigned char c = s.c; // { dg-error "accessing uninitialized member" } > return true; > } > > constexpr bool a = f1 (); > constexpr bool b = f2 (); > constexpr bool c = f3 (); > -constexpr bool d = f4 (); > -constexpr bool e = f5 (); // { dg-error "accessing uninitialized member" } > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized member" } > -constexpr bool g = f7 (); // { dg-error "accessing uninitialized member" } > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > +constexpr bool e = f5 (); // { dg-message "in .constexpr. expansion" } > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > +constexpr bool g = f7 (); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > index 01bdfa5bd4d..b0c91d5ef97 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > @@ -9,7 +9,7 @@ bar () > { > V f { .b = 42 }; > constexpr auto m = &V::a; > - return (f.*m) == 42; > + return (f.*m) == 42; // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" } > } > > constexpr bool > @@ -21,5 +21,5 @@ baz () > } > > static_assert (bar (), ""); // { dg-error "non-constant condition for static assertion" } > - // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" "" { target *-*-* } .-1 } > + // { dg-message "in .constexpr. expansion" "" { target *-*-* } .-1 } > static_assert (baz (), ""); > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > index a26678e6ed7..28facf192df 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > @@ -25,8 +25,7 @@ struct D : B, A { > > constexpr B::B(V* v, A* a) > { > - dynamic_cast<B*>(a); > + dynamic_cast<B*>(a); // { dg-error "accessing uninitialized member" } > } > > -constexpr D d; // { dg-error "accessing uninitialized member" } > -// { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > +constexpr D d; // { dg-message "in 'constexpr' expansion of" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > index e56ecfed48a..b4e39b6f928 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > @@ -52,11 +52,10 @@ constexpr int > fn5 () > { > struct S { int a = 9; int b; } s; > - return s.b; > + return s.b; // { dg-error "accessing uninitialized member" } > } > > -constexpr int b = fn5 (); // { dg-error "accessing uninitialized member" } > -// { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 } > +constexpr int b = fn5 (); // { dg-message "in .constexpr. expansion of" } > > constexpr int > fn6 () > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > index 5a3d06a5fab..832782e1427 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > @@ -17,11 +17,11 @@ struct B : A { > constexpr int > foo () > { > - A *a = new B (); > + A *a = new B (); // { dg-message "allocated here" } > a->a = 4; > delete a; > - int r = a->foo (); > + int r = a->foo (); // { dg-error "constant expression" } > return r; > } > > -constexpr auto a = foo (); // { dg-error "constant expression" } > +constexpr auto a = foo (); // { dg-message "in .constexpr. expansion" } > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > index 70b841208f8..3ba440fec53 100644 > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > @@ -45,11 +45,10 @@ constexpr bool > f5 () > { > int *p = new int; // { dg-message "allocated here" } > - return *p == 1; > + return *p == 1; // { dg-error "the content of uninitialized storage is not usable in a constant expression" } > } > > -constexpr auto v5 = f5 (); // { dg-error "the content of uninitialized storage is not usable in a constant expression" } > - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > +constexpr auto v5 = f5 (); // { dg-message "in 'constexpr' expansion of" } > > constexpr bool > f6 () > @@ -57,11 +56,10 @@ f6 () > int *p = new int (2); // { dg-message "allocated here" } > int *q = p; > delete p; > - return *q == 2; > + return *q == 2; // { dg-error "use of allocated storage after deallocation in a constant expression" } > } > > -constexpr auto v6 = f6 (); // { dg-error "use of allocated storage after deallocation in a constant expression" } > - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > +constexpr auto v6 = f6 (); // { dg-message "in 'constexpr' expansion of" } > > constexpr int * > f7 () > diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > index d4ea7c58c0d..e09a27af3de 100644 > --- a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > @@ -4,7 +4,7 @@ > constexpr int > fn_bad (int n) > { > - __extension__ int a [n] = { 0 }; > + __extension__ int a [n] = { 0 }; // { dg-error "array subscript" } > int z = a [0] + (n ? fn_bad (n - 1) : 0); // { dg-message "in .constexpr. expansion of " } > return z; > } > @@ -18,4 +18,4 @@ fn_ok (int n) > } > > constexpr int i1 = fn_ok (3); > -constexpr int i2 = fn_bad (3); // { dg-error "array subscript|in .constexpr. expansion of " } > +constexpr int i2 = fn_bad (3); // { dg-message "in .constexpr. expansion of " } > diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > index 538b576a825..6f9daa1897f 100644 > --- a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > @@ -4,11 +4,11 @@ > constexpr int > foo (int n) > { > - __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; > + __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; // { dg-error "array subscript" } > int z = 0; > for (int i = 0; i <= n; ++i) > z += a[i]; > return z; > } > > -constexpr int n = foo (3); // { dg-error "array subscript|in .constexpr. expansion of " } > +constexpr int n = foo (3); // { dg-message "in .constexpr. expansion of " } > diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C > index 3a1596e6e2e..0771732ef00 100644 > --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C > +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C > @@ -100,13 +100,13 @@ constexpr int > fn7 (const int *a, int b) > { > if (b != 3) > - return fn6 (*a, b); > + return fn6 (*a, b); // { dg-error "null pointer" } > return 7; > } > > constexpr int n1 = 7; > constexpr int n2 = fn7 (&n1, 5); > -constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "null pointer|in .constexpr. expansion of " } > +constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-message "in .constexpr. expansion of " } > > constexpr int > fn8 (int i) > diff --git a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > index 34ca5c4805c..fd89ac0e166 100644 > --- a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > +++ b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > @@ -32,7 +32,7 @@ test01() > return outa; > } > > -static_assert(test01()); // { dg-error "outside the bounds" } > +static_assert(test01()); // { dg-error "non-constant condition" } > > constexpr bool > test02() > @@ -44,7 +44,8 @@ test02() > return outa; > } > > -static_assert(test02()); // { dg-error "outside the bounds" } > +static_assert(test02()); // { dg-error "non-constant condition" } > > -// { dg-prune-output "non-constant condition" } > +// Errors occuring within <algorithm> internals: > +// { dg-error "outside the bounds of array" "" { target *-*-* } 0 } > // { dg-prune-output "in 'constexpr'" } > -- > 2.34.1 > >
On Fri, Jun 23, 2023 at 01:09:14PM -0400, Patrick Palka wrote: > On Wed, 29 Mar 2023, Nathaniel Shead via Gcc-patches wrote: > > > This patch caches the current expression's location information in the > > constexpr_global_ctx struct, which allows subexpressions that have lost > > location information to still provide accurate diagnostics. Also > > rewrites a number of 'error' calls as 'error_at' to provide more > > specific location information. > > > > The primary effect of this change is that many errors within evaluation > > of a constexpr function will now point at the offending expression (with > > expansion tracing information) rather than just the outermost call. > > This seems like a great improvement! > > In other parts of the frontend, e.g. during substitution from > tsubst_expr or tsubst_copy_and_build, we do something similar by > setting/restoring input_location directly. (We've since added the RAII > class iloc_sentinel for this.) I wonder if that'd be preferable here? I didn't consider that; I've given it a try and I think it's nicer. Doing it this way also updated a number of 'error' calls that I hadn't fixed up in this version; generally this meant nicer error messages, but I had to override it for a couple of cases where I felt the errors it raised were worse (by adding context that made no sense). I'm still bootstrapping/regtesting but I'll send out an updated version of this sometime tomorrow when it's done. Thanks! > > > > gcc/cp/ChangeLog: > > > > * constexpr.cc (constexpr_global_ctx): New field for cached > > tree location, defaulting to input_location. > > (cxx_eval_internal_function): Fall back to ctx->global->loc > > rather than input_location. > > (modifying_const_object_error): Likewise. > > (cxx_eval_dynamic_cast_fn): Likewise. > > (eval_and_check_array_index): Likewise. > > (cxx_eval_array_reference): Likewise. > > (cxx_eval_bit_field_ref): Likewise. > > (cxx_eval_component_reference): Likewise. > > (cxx_eval_indirect_ref): Likewise. > > (cxx_eval_store_expression): Likewise. > > (cxx_eval_increment_expression): Likewise. > > (cxx_eval_loop_expr): Likewise. > > (cxx_eval_binary_expression): Likewise. > > (cxx_eval_constant_expression): Cache location of trees for use > > in errors, and prefer it instead of input_location. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations. > > * g++.dg/cpp0x/constexpr-diag3.C: Likewise. > > * g++.dg/cpp0x/constexpr-ice20.C: Likewise. > > * g++.dg/cpp1y/constexpr-89481.C: Likewise. > > * g++.dg/cpp1y/constexpr-lifetime1.C: Likewise. > > * g++.dg/cpp1y/constexpr-lifetime2.C: Likewise. > > * g++.dg/cpp1y/constexpr-lifetime3.C: Likewise. > > * g++.dg/cpp1y/constexpr-lifetime4.C: Likewise. > > * g++.dg/cpp1y/constexpr-lifetime5.C: Likewise. > > * g++.dg/cpp1y/constexpr-union5.C: Likewise. > > * g++.dg/cpp1y/pr68180.C: Likewise. > > * g++.dg/cpp1z/constexpr-lambda6.C: Likewise. > > * g++.dg/cpp2a/bit-cast11.C: Likewise. > > * g++.dg/cpp2a/bit-cast12.C: Likewise. > > * g++.dg/cpp2a/bit-cast14.C: Likewise. > > * g++.dg/cpp2a/constexpr-98122.C: Likewise. > > * g++.dg/cpp2a/constexpr-dynamic17.C: Likewise. > > * g++.dg/cpp2a/constexpr-init1.C: Likewise. > > * g++.dg/cpp2a/constexpr-new12.C: Likewise. > > * g++.dg/cpp2a/constexpr-new3.C: Likewise. > > * g++.dg/ext/constexpr-vla2.C: Likewise. > > * g++.dg/ext/constexpr-vla3.C: Likewise. > > * g++.dg/ubsan/pr63956.C: Likewise. > > > > libstdc++/ChangeLog: > > > > * testsuite/25_algorithms/equal/constexpr_neg.cc: Updated > > diagnostics locations. > > > > Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> > > --- > > gcc/cp/constexpr.cc | 83 +++++++++++-------- > > gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C | 10 +-- > > gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C | 2 +- > > gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C | 4 +- > > gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C | 3 +- > > .../g++.dg/cpp1y/constexpr-lifetime1.C | 1 + > > .../g++.dg/cpp1y/constexpr-lifetime2.C | 4 +- > > .../g++.dg/cpp1y/constexpr-lifetime3.C | 4 +- > > .../g++.dg/cpp1y/constexpr-lifetime4.C | 2 +- > > .../g++.dg/cpp1y/constexpr-lifetime5.C | 4 +- > > gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C | 4 +- > > gcc/testsuite/g++.dg/cpp1y/pr68180.C | 4 +- > > .../g++.dg/cpp1z/constexpr-lambda6.C | 4 +- > > gcc/testsuite/g++.dg/cpp2a/bit-cast11.C | 10 +-- > > gcc/testsuite/g++.dg/cpp2a/bit-cast12.C | 10 +-- > > gcc/testsuite/g++.dg/cpp2a/bit-cast14.C | 14 ++-- > > gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C | 4 +- > > .../g++.dg/cpp2a/constexpr-dynamic17.C | 5 +- > > gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C | 5 +- > > gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C | 6 +- > > gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C | 10 +-- > > gcc/testsuite/g++.dg/ext/constexpr-vla2.C | 4 +- > > gcc/testsuite/g++.dg/ext/constexpr-vla3.C | 4 +- > > gcc/testsuite/g++.dg/ubsan/pr63956.C | 4 +- > > .../25_algorithms/equal/constexpr_neg.cc | 7 +- > > 25 files changed, 111 insertions(+), 101 deletions(-) > > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > > index bdbc12144a7..74045477a92 100644 > > --- a/gcc/cp/constexpr.cc > > +++ b/gcc/cp/constexpr.cc > > @@ -1165,10 +1165,12 @@ public: > > hash_set<tree> *modifiable; > > /* Number of heap VAR_DECL deallocations. */ > > unsigned heap_dealloc_count; > > + /* Current location in case subtree has no location information. */ > > + location_t loc; > > /* Constructor. */ > > constexpr_global_ctx () > > : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr), > > - heap_dealloc_count (0) {} > > + heap_dealloc_count (0), loc (input_location) {} > > > > tree get_value (tree t) > > { > > @@ -2113,7 +2115,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, > > > > default: > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > > "call to internal function %qE", t); > > *non_constant_p = true; > > return t; > > @@ -2128,7 +2130,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, > > > > if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) > > { > > - location_t loc = cp_expr_loc_or_input_loc (t); > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > tree type = TREE_TYPE (TREE_TYPE (t)); > > tree result = fold_binary_loc (loc, opcode, type, > > fold_convert_loc (loc, type, arg0), > > @@ -2164,9 +2166,9 @@ clear_no_implicit_zero (tree ctor) > > EXPR is the MODIFY_EXPR expression performing the modification. */ > > > > static void > > -modifying_const_object_error (tree expr, tree obj) > > +modifying_const_object_error (const constexpr_ctx* ctx, tree expr, tree obj) > > { > > - location_t loc = cp_expr_loc_or_input_loc (expr); > > + location_t loc = cp_expr_loc_or_loc (expr, ctx->global->loc); > > auto_diagnostic_group d; > > error_at (loc, "modifying a const object %qE is not allowed in " > > "a constant expression", TREE_OPERAND (expr, 0)); > > @@ -2358,7 +2360,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, > > tree obj = CALL_EXPR_ARG (call, 0); > > tree type = CALL_EXPR_ARG (call, 2); > > HOST_WIDE_INT hint = int_cst_value (CALL_EXPR_ARG (call, 3)); > > - location_t loc = cp_expr_loc_or_input_loc (call); > > + location_t loc = cp_expr_loc_or_loc (call, ctx->global->loc); > > > > /* Get the target type of the dynamic_cast. */ > > gcc_assert (TREE_CODE (type) == ADDR_EXPR); > > @@ -3656,7 +3658,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, > > && integer_zerop (lhs) && !integer_zerop (rhs)) > > { > > if (!ctx->quiet) > > - error ("arithmetic involving a null pointer in %qE", lhs); > > + error_at (loc, "arithmetic involving a null pointer in %qE", lhs); > > *non_constant_p = true; > > return t; > > } > > @@ -4149,7 +4151,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, > > tree t, bool allow_one_past, > > bool *non_constant_p, bool *overflow_p) > > { > > - location_t loc = cp_expr_loc_or_input_loc (t); > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > tree ary = TREE_OPERAND (t, 0); > > t = TREE_OPERAND (t, 1); > > tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue, > > @@ -4187,6 +4189,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, > > value_cat lval, > > bool *non_constant_p, bool *overflow_p) > > { > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > tree oldary = TREE_OPERAND (t, 0); > > tree ary = cxx_eval_constant_expression (ctx, oldary, > > lval, > > @@ -4274,7 +4277,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, > > building; if there's no initializer for this element yet, > > that's an error. */ > > if (!ctx->quiet) > > - error ("accessing uninitialized array element"); > > + error_at (loc, "accessing uninitialized array element"); > > *non_constant_p = true; > > return t; > > } > > @@ -4323,13 +4326,14 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > > tree whole = cxx_eval_constant_expression (ctx, orig_whole, > > lval, > > non_constant_p, overflow_p); > > + location_t loc = cp_expr_loc_or_loc (whole, ctx->global->loc); > > if (*non_constant_p) > > return t; > > if (INDIRECT_REF_P (whole) > > && integer_zerop (TREE_OPERAND (whole, 0))) > > { > > if (!ctx->quiet) > > - error ("dereferencing a null pointer in %qE", orig_whole); > > + error_at (loc, "dereferencing a null pointer in %qE", orig_whole); > > *non_constant_p = true; > > return t; > > } > > @@ -4348,7 +4352,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > > if (TREE_CODE (whole) != CONSTRUCTOR) > > { > > if (!ctx->quiet) > > - error ("%qE is not a constant expression", orig_whole); > > + error_at (loc, "%qE is not a constant expression", orig_whole); > > *non_constant_p = true; > > return t; > > } > > @@ -4356,7 +4360,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > > && DECL_MUTABLE_P (part)) > > { > > if (!ctx->quiet) > > - error ("mutable %qD is not usable in a constant expression", part); > > + error_at (loc, "mutable %qD is not usable in a constant expression", part); > > *non_constant_p = true; > > return t; > > } > > @@ -4386,10 +4390,10 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > > { > > constructor_elt *cep = CONSTRUCTOR_ELT (whole, 0); > > if (cep->value == NULL_TREE) > > - error ("accessing uninitialized member %qD", part); > > + error_at (loc, "accessing uninitialized member %qD", part); > > else > > - error ("accessing %qD member instead of initialized %qD member in " > > - "constant expression", part, cep->index); > > + error_at (loc, "accessing %qD member instead of initialized %qD member " > > + "in constant expression", part, cep->index); > > } > > *non_constant_p = true; > > return t; > > @@ -4408,7 +4412,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, > > building; if there's no initializer for this member yet, that's an > > error. */ > > if (!ctx->quiet) > > - error ("accessing uninitialized member %qD", part); > > + error_at (loc, "accessing uninitialized member %qD", part); > > *non_constant_p = true; > > return t; > > } > > @@ -4436,6 +4440,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > > tree whole = cxx_eval_constant_expression (ctx, orig_whole, > > lval, > > non_constant_p, overflow_p); > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > tree start, field, value; > > unsigned HOST_WIDE_INT i; > > > > @@ -4448,7 +4453,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > > && TREE_CODE (whole) != CONSTRUCTOR) > > { > > if (!ctx->quiet) > > - error ("%qE is not a constant expression", orig_whole); > > + error_at (loc, "%qE is not a constant expression", orig_whole); > > *non_constant_p = true; > > } > > if (*non_constant_p) > > @@ -4460,7 +4465,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, > > TREE_OPERAND (t, 1), TREE_OPERAND (t, 2))) > > return r; > > if (!ctx->quiet) > > - error ("%qE is not a constant expression", orig_whole); > > + error_at (loc, "%qE is not a constant expression", orig_whole); > > *non_constant_p = true; > > return t; > > } > > @@ -5609,6 +5614,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > > value_cat lval, > > bool *non_constant_p, bool *overflow_p) > > { > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > tree orig_op0 = TREE_OPERAND (t, 0); > > bool empty_base = false; > > > > @@ -5639,7 +5645,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > > if (!lval && integer_zerop (op0)) > > { > > if (!ctx->quiet) > > - error ("dereferencing a null pointer"); > > + error_at (loc, "dereferencing a null pointer"); > > *non_constant_p = true; > > return t; > > } > > @@ -5658,8 +5664,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, > > (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); > > /* DR 1188 says we don't have to deal with this. */ > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > - "accessing value of %qE through a %qT glvalue in a " > > + error_at (loc, "accessing value of %qE through a %qT glvalue in a " > > "constant expression", build_fold_indirect_ref (sub), > > TREE_TYPE (t)); > > *non_constant_p = true; > > @@ -5906,6 +5911,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > value_cat lval, > > bool *non_constant_p, bool *overflow_p) > > { > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > constexpr_ctx new_ctx = *ctx; > > > > tree init = TREE_OPERAND (t, 1); > > @@ -6030,7 +6036,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > /* A constant-expression cannot modify objects from outside the > > constant-expression. */ > > if (!ctx->quiet) > > - error ("modification of %qE is not a constant expression", object); > > + error_at (loc, "modification of %qE is not a constant expression", object); > > *non_constant_p = true; > > return t; > > } > > @@ -6128,7 +6134,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > if (cxx_dialect < cxx20) > > { > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > > "change of the active member of a union " > > "from %qD to %qD", > > CONSTRUCTOR_ELT (*valp, 0)->index, > > @@ -6141,7 +6147,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > /* Diagnose changing the active union member while the union > > is in the process of being initialized. */ > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), > > "change of the active member of a union " > > "from %qD to %qD during initialization", > > CONSTRUCTOR_ELT (*valp, 0)->index, > > @@ -6224,7 +6230,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > if (fail) > > { > > if (!ctx->quiet) > > - modifying_const_object_error (t, const_object_being_modified); > > + modifying_const_object_error (ctx, t, const_object_being_modified); > > *non_constant_p = true; > > return t; > > } > > @@ -6381,6 +6387,8 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, > > tree offset = TREE_OPERAND (t, 1); > > gcc_assert (TREE_CONSTANT (offset)); > > > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > + > > /* OFFSET is constant, but perhaps not constant enough. We need to > > e.g. bash FLOAT_EXPRs to REAL_CSTs. */ > > offset = fold_simple (offset); > > @@ -6428,8 +6436,7 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, > > VERIFY_CONSTANT (mod); > > > > /* Storing the modified value. */ > > - tree store = build2_loc (cp_expr_loc_or_loc (t, input_location), > > - MODIFY_EXPR, type, op, mod); > > + tree store = build2_loc (loc, MODIFY_EXPR, type, op, mod); > > mod = cxx_eval_constant_expression (ctx, store, lval, > > non_constant_p, overflow_p); > > ggc_free (store); > > @@ -6602,6 +6609,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, > > bool *non_constant_p, bool *overflow_p, > > tree *jump_target) > > { > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > constexpr_ctx new_ctx = *ctx; > > tree local_target; > > if (!jump_target) > > @@ -6691,7 +6699,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, > > if (++count >= constexpr_loop_limit) > > { > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > + error_at (loc, > > "%<constexpr%> loop iteration count exceeds limit of %d " > > "(use %<-fconstexpr-loop-limit=%> to increase the limit)", > > constexpr_loop_limit); > > @@ -6950,7 +6958,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > > return t; > > } > > > > - location_t loc = cp_expr_loc_or_input_loc (t); > > + /* Track current location, propagating down from parent calls > > + in case this expression has no location information. */ > > + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); > > + ctx->global->loc = loc; > > > > STRIP_ANY_LOCATION_WRAPPER (t); > > > > @@ -6973,8 +6984,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > > && !integer_zerop (t)) > > { > > if (!ctx->quiet) > > - error ("value %qE of type %qT is not a constant expression", > > - t, TREE_TYPE (t)); > > + error_at (loc, "value %qE of type %qT is not a constant expression", > > + t, TREE_TYPE (t)); > > *non_constant_p = true; > > } > > > > @@ -7222,8 +7233,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > > if (!ctx->quiet) > > { > > auto_diagnostic_group d; > > - error ("temporary of non-literal type %qT in a " > > - "constant expression", type); > > + error_at (loc, "temporary of non-literal type %qT in a " > > + "constant expression", type); > > explain_non_literal_class (type); > > } > > *non_constant_p = true; > > @@ -8025,8 +8036,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > > if (function_concept_p (tmpl)) > > { > > if (!ctx->quiet) > > - error_at (cp_expr_loc_or_input_loc (t), > > - "function concept must be called"); > > + error_at (loc, "function concept must be called"); > > r = error_mark_node; > > break; > > } > > @@ -8121,6 +8131,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, > > break; > > } > > > > + /* Reset current location in case it was modified in child calls. */ > > + ctx->global->loc = loc; > > + > > if (r == error_mark_node) > > *non_constant_p = true; > > > > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > > index 4574eb83ff7..11630f26ffe 100644 > > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C > > @@ -10,11 +10,11 @@ > > // R() is well-formed because i is initialized before j. > > > > struct s { > > - constexpr s() : v(v) { } > > + constexpr s() : v(v) { } // { dg-error "accessing uninitialized member" } > > int v; > > }; > > > > -constexpr s bang; // { dg-error "|" } > > +constexpr s bang; // { dg-message "in .constexpr. expansion" } > > > > struct R { > > int i,j; > > @@ -26,14 +26,14 @@ constexpr R r; // { dg-bogus "" } > > // Ill-formed (no diagnostic required) > > struct T { > > int i; > > - constexpr int f() { return i; } > > + constexpr int f() { return i; } // { dg-error "accessing uninitialized member" } > > constexpr T(): i(0) { } > > - constexpr T(const T& t) : i(f()) { } // { dg-message "" } > > + constexpr T(const T& t) : i(f()) { } // { dg-message "in .constexpr. expansion" } > > }; > > > > constexpr T t1; > > // Ill-formed (diagnostic required) > > -constexpr T t2(t1); // { dg-message "" } > > +constexpr T t2(t1); // { dg-message "in .constexpr. expansion" } > > > > // Well-formed > > struct U { > > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > > index 5eedf42ba36..50c676c56cd 100644 > > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C > > @@ -16,7 +16,7 @@ int main() > > struct complex // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } } > > { > > complex(double r, double i) : re(r), im(i) { } > > - constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } } > > + constexpr double real() const { return re; } // { dg-error "not a literal type|not usable in a constant expression" "" { target { ! implicit_constexpr } } } > > double imag() const { return im; } > > > > private: > > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > > index ebaa95e5324..e4e3bf865cd 100644 > > --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C > > @@ -2,6 +2,6 @@ > > // { dg-do compile { target c++11 } } > > > > typedef bool (*Function)(int); > > -constexpr bool check(int x, Function p) { return p(x); } // { dg-message "in .constexpr. expansion of" } > > +constexpr bool check(int x, Function p) { return p(x); } // { dg-error "lifetime" } > > > > -static_assert(check(2, check), ""); // { dg-error "conversion|constant|lifetime|in .constexpr. expansion of" } > > +static_assert(check(2, check), ""); // { dg-error "conversion|constant|in .constexpr. expansion of" } > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > > index 8ac4ef0fd36..6f8f6a8038e 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C > > @@ -6,7 +6,7 @@ foo () > > { > > union U { long long a; int b[2]; } u { 5LL }; > > u.b[1] = 4; // { dg-error "change of the active member of a union from" "" { target c++17_down } } > > - return u.b[0]; > > + return u.b[0]; // { dg-error "accessing uninitialized array element" "" { target c++2a } } > > } > > > > constexpr int > > @@ -19,6 +19,5 @@ bar () > > > > static_assert (foo () == 0, ""); // { dg-error "non-constant condition for static assertion" } > > // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > > - // { dg-error "accessing uninitialized array element" "" { target c++2a } .-2 } > > static_assert (bar () == 4, ""); // { dg-error "non-constant condition for static assertion" "" { target c++17_down } } > > // { dg-message "in 'constexpr' expansion of" "" { target c++17_down } .-1 } > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > > index 43aa7c974c1..f79f1611d5f 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C > > @@ -11,3 +11,4 @@ constexpr const int& test() { > > return local.get(); > > } > > constexpr int x = test(); // { dg-error "accessing object outside its lifetime" } > > + > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > > index 22cd919fcda..2f5ae8db6d5 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C > > @@ -8,9 +8,9 @@ struct S { > > > > constexpr int error() { > > const auto& local = S{}.get(); // { dg-message "note: declared here" } > > - return local; > > + return local; // { dg-error "accessing object outside its lifetime" } > > } > > -constexpr int x = error(); // { dg-error "accessing object outside its lifetime" } > > +constexpr int x = error(); // { dg-message "in .constexpr. expansion" } > > > > constexpr int ok() { > > // temporary should only be destroyed after end of full-expression > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > > index 6329f8cf6c6..53785521d05 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C > > @@ -7,7 +7,7 @@ constexpr int f(int i) { > > int j = 123; // { dg-message "note: declared here" } > > p = &j; > > } > > - return *p; > > + return *p; // { dg-error "accessing object outside its lifetime" } > > } > > > > -constexpr int i = f(0); // { dg-error "accessing object outside its lifetime" } > > +constexpr int i = f(0); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > > index 181a1201663..4302da1eddc 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C > > @@ -5,7 +5,7 @@ constexpr const double& test() { > > return local; > > } > > > > -static_assert(test() == 3.0, ""); // { dg-error "constant|accessing object outside its lifetime" } > > +static_assert(test() == 3.0, ""); // { dg-error "non-constant condition|accessing object outside its lifetime" } > > > > // no deference, shouldn't error > > static_assert((test(), true), ""); > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > > index ad3ef579f63..a12920c8fba 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C > > @@ -5,7 +5,7 @@ constexpr const int& id(int x) { return x; } // { dg-message "note: declared he > > > > constexpr bool test() { > > const int& y = id(3); > > - return y == 3; > > + return y == 3; // { dg-error "accessing object outside its lifetime" } > > } > > > > -constexpr bool x = test(); // { dg-error "accessing object outside its lifetime" } > > +constexpr bool x = test(); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > > index 55fe9fa2f0b..3d76345d564 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C > > @@ -8,8 +8,8 @@ union U { > > }; > > > > constexpr int foo(U *up) { > > - up->a++; > > + up->a++; // { dg-error "accessing uninitialized member" } > > return {42}; > > } > > > > -extern constexpr U u = {}; // { dg-error "accessing uninitialized member" } > > +extern constexpr U u = {}; // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68180.C b/gcc/testsuite/g++.dg/cpp1y/pr68180.C > > index 9e6e5e984f9..8de1ef3936b 100644 > > --- a/gcc/testsuite/g++.dg/cpp1y/pr68180.C > > +++ b/gcc/testsuite/g++.dg/cpp1y/pr68180.C > > @@ -6,11 +6,11 @@ typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t; > > constexpr float32x4_t fill(float x) { > > float32x4_t v{0}; > > constexpr auto vs = sizeof(v)/sizeof(v[0]); > > - for (auto i=0U; i<vs; ++i) v[i]=i; > > + for (auto i=0U; i<vs; ++i) v[i]=i; // { dg-error "not a constant" } > > return v+x; > > } > > > > float32x4_t foo(float32x4_t x) { > > - constexpr float32x4_t v = fill(1.f); // { dg-error "not a constant||in .constexpr. expansion of " } > > + constexpr float32x4_t v = fill(1.f); // { dg-message "in .constexpr. expansion of " } > > return x+v; > > } > > diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > > index 214d3821299..c46c2d4c7fe 100644 > > --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > > +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C > > @@ -1,7 +1,7 @@ > > // Testcase from P0170R1 > > // { dg-do compile { target c++17 } } > > > > -auto monoid = [](auto v) { return [=] { return v; }; }; > > +auto monoid = [](auto v) { return [=] { return v; }; }; // { dg-error "not usable in a constant expression" } > > auto add = [](auto m1) constexpr { > > auto ret = m1(); > > return [=](auto m2) mutable { > > @@ -22,7 +22,7 @@ int main() > > // member function call operator can not perform an lvalue-to-rvalue conversion > > // on one of its subobjects (that represents its capture) in a constant > > // expression. > > - auto two = monoid(2); > > + auto two = monoid(2); // { dg-message "not declared .constexpr." } > > if (!(two() == 2)) __builtin_abort(); // OK, not a constant expression. > > static_assert(add(one)(one)() == two()); // { dg-error "|in .constexpr. expansion of " } two() is not a constant expression > > static_assert(add(one)(one)() == monoid(2)()); // OK > > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > > index a3eb31bc6c7..760c9ca40b4 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C > > @@ -28,7 +28,7 @@ f3 () > > { > > T t = { 1, 2 }; > > S s = __builtin_bit_cast (S, t); > > - return s.a[1] == 0; > > + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } > > } > > > > constexpr bool > > @@ -52,12 +52,12 @@ f6 () > > { > > W t = { 1, 2 }; > > V s = __builtin_bit_cast (V, t); > > - return s.b.a[1] == 1; > > + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } > > } > > > > constexpr bool a = f1 (); > > constexpr bool b = f2 (); > > -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } > > -constexpr bool d = f4 (); > > +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } > > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > > constexpr bool e = f5 (); > > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } > > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > > index 9c699dd55f0..e205bc6a8c1 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C > > @@ -33,7 +33,7 @@ f3 () > > { > > T t = { 1, 2 }; > > S s = __builtin_bit_cast (S, t); > > - return s.a[1] == 0; > > + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } > > } > > > > constexpr bool > > @@ -57,12 +57,12 @@ f6 () > > { > > W t = { 1, 2 }; > > V s = __builtin_bit_cast (V, t); > > - return s.b.a[1] == 1; > > + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } > > } > > > > constexpr bool a = f1 (); > > constexpr bool b = f2 (); > > -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } > > -constexpr bool d = f4 (); > > +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } > > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > > constexpr bool e = f5 (); > > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } > > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > > index 5e185919be4..e0cc9a39702 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C > > @@ -44,7 +44,7 @@ f5 () > > { > > T1 t = { 0, 0, 0, 0, 0, 0, 0 }; > > S s = __builtin_bit_cast (S, t); > > - unsigned char a = s.a; > > + unsigned char a = s.a; // { dg-error "accessing uninitialized member" } > > return true; > > } > > > > @@ -53,7 +53,7 @@ f6 () > > { > > T2 t = { 0, 0, 0, 0, 0, 0, 0 }; > > S s = __builtin_bit_cast (S, t); > > - unsigned char b = s.b; > > + unsigned char b = s.b; // { dg-error "accessing uninitialized member" } > > return true; > > } > > > > @@ -62,14 +62,14 @@ f7 () > > { > > T3 t = { 0, 0, 0, 0, 0, 0, 0 }; > > S s = __builtin_bit_cast (S, t); > > - unsigned char c = s.c; > > + unsigned char c = s.c; // { dg-error "accessing uninitialized member" } > > return true; > > } > > > > constexpr bool a = f1 (); > > constexpr bool b = f2 (); > > constexpr bool c = f3 (); > > -constexpr bool d = f4 (); > > -constexpr bool e = f5 (); // { dg-error "accessing uninitialized member" } > > -constexpr bool f = f6 (); // { dg-error "accessing uninitialized member" } > > -constexpr bool g = f7 (); // { dg-error "accessing uninitialized member" } > > +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } > > +constexpr bool e = f5 (); // { dg-message "in .constexpr. expansion" } > > +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } > > +constexpr bool g = f7 (); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > > index 01bdfa5bd4d..b0c91d5ef97 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C > > @@ -9,7 +9,7 @@ bar () > > { > > V f { .b = 42 }; > > constexpr auto m = &V::a; > > - return (f.*m) == 42; > > + return (f.*m) == 42; // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" } > > } > > > > constexpr bool > > @@ -21,5 +21,5 @@ baz () > > } > > > > static_assert (bar (), ""); // { dg-error "non-constant condition for static assertion" } > > - // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" "" { target *-*-* } .-1 } > > + // { dg-message "in .constexpr. expansion" "" { target *-*-* } .-1 } > > static_assert (baz (), ""); > > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > > index a26678e6ed7..28facf192df 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C > > @@ -25,8 +25,7 @@ struct D : B, A { > > > > constexpr B::B(V* v, A* a) > > { > > - dynamic_cast<B*>(a); > > + dynamic_cast<B*>(a); // { dg-error "accessing uninitialized member" } > > } > > > > -constexpr D d; // { dg-error "accessing uninitialized member" } > > -// { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > > +constexpr D d; // { dg-message "in 'constexpr' expansion of" } > > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > > index e56ecfed48a..b4e39b6f928 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C > > @@ -52,11 +52,10 @@ constexpr int > > fn5 () > > { > > struct S { int a = 9; int b; } s; > > - return s.b; > > + return s.b; // { dg-error "accessing uninitialized member" } > > } > > > > -constexpr int b = fn5 (); // { dg-error "accessing uninitialized member" } > > -// { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 } > > +constexpr int b = fn5 (); // { dg-message "in .constexpr. expansion of" } > > > > constexpr int > > fn6 () > > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > > index 5a3d06a5fab..832782e1427 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C > > @@ -17,11 +17,11 @@ struct B : A { > > constexpr int > > foo () > > { > > - A *a = new B (); > > + A *a = new B (); // { dg-message "allocated here" } > > a->a = 4; > > delete a; > > - int r = a->foo (); > > + int r = a->foo (); // { dg-error "constant expression" } > > return r; > > } > > > > -constexpr auto a = foo (); // { dg-error "constant expression" } > > +constexpr auto a = foo (); // { dg-message "in .constexpr. expansion" } > > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > > index 70b841208f8..3ba440fec53 100644 > > --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C > > @@ -45,11 +45,10 @@ constexpr bool > > f5 () > > { > > int *p = new int; // { dg-message "allocated here" } > > - return *p == 1; > > + return *p == 1; // { dg-error "the content of uninitialized storage is not usable in a constant expression" } > > } > > > > -constexpr auto v5 = f5 (); // { dg-error "the content of uninitialized storage is not usable in a constant expression" } > > - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > > +constexpr auto v5 = f5 (); // { dg-message "in 'constexpr' expansion of" } > > > > constexpr bool > > f6 () > > @@ -57,11 +56,10 @@ f6 () > > int *p = new int (2); // { dg-message "allocated here" } > > int *q = p; > > delete p; > > - return *q == 2; > > + return *q == 2; // { dg-error "use of allocated storage after deallocation in a constant expression" } > > } > > > > -constexpr auto v6 = f6 (); // { dg-error "use of allocated storage after deallocation in a constant expression" } > > - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } > > +constexpr auto v6 = f6 (); // { dg-message "in 'constexpr' expansion of" } > > > > constexpr int * > > f7 () > > diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > > index d4ea7c58c0d..e09a27af3de 100644 > > --- a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > > +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C > > @@ -4,7 +4,7 @@ > > constexpr int > > fn_bad (int n) > > { > > - __extension__ int a [n] = { 0 }; > > + __extension__ int a [n] = { 0 }; // { dg-error "array subscript" } > > int z = a [0] + (n ? fn_bad (n - 1) : 0); // { dg-message "in .constexpr. expansion of " } > > return z; > > } > > @@ -18,4 +18,4 @@ fn_ok (int n) > > } > > > > constexpr int i1 = fn_ok (3); > > -constexpr int i2 = fn_bad (3); // { dg-error "array subscript|in .constexpr. expansion of " } > > +constexpr int i2 = fn_bad (3); // { dg-message "in .constexpr. expansion of " } > > diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > > index 538b576a825..6f9daa1897f 100644 > > --- a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > > +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C > > @@ -4,11 +4,11 @@ > > constexpr int > > foo (int n) > > { > > - __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; > > + __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; // { dg-error "array subscript" } > > int z = 0; > > for (int i = 0; i <= n; ++i) > > z += a[i]; > > return z; > > } > > > > -constexpr int n = foo (3); // { dg-error "array subscript|in .constexpr. expansion of " } > > +constexpr int n = foo (3); // { dg-message "in .constexpr. expansion of " } > > diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C > > index 3a1596e6e2e..0771732ef00 100644 > > --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C > > +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C > > @@ -100,13 +100,13 @@ constexpr int > > fn7 (const int *a, int b) > > { > > if (b != 3) > > - return fn6 (*a, b); > > + return fn6 (*a, b); // { dg-error "null pointer" } > > return 7; > > } > > > > constexpr int n1 = 7; > > constexpr int n2 = fn7 (&n1, 5); > > -constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "null pointer|in .constexpr. expansion of " } > > +constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-message "in .constexpr. expansion of " } > > > > constexpr int > > fn8 (int i) > > diff --git a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > > index 34ca5c4805c..fd89ac0e166 100644 > > --- a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > > +++ b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc > > @@ -32,7 +32,7 @@ test01() > > return outa; > > } > > > > -static_assert(test01()); // { dg-error "outside the bounds" } > > +static_assert(test01()); // { dg-error "non-constant condition" } > > > > constexpr bool > > test02() > > @@ -44,7 +44,8 @@ test02() > > return outa; > > } > > > > -static_assert(test02()); // { dg-error "outside the bounds" } > > +static_assert(test02()); // { dg-error "non-constant condition" } > > > > -// { dg-prune-output "non-constant condition" } > > +// Errors occuring within <algorithm> internals: > > +// { dg-error "outside the bounds of array" "" { target *-*-* } 0 } > > // { dg-prune-output "in 'constexpr'" } > > -- > > 2.34.1 > > > > >
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index bdbc12144a7..74045477a92 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1165,10 +1165,12 @@ public: hash_set<tree> *modifiable; /* Number of heap VAR_DECL deallocations. */ unsigned heap_dealloc_count; + /* Current location in case subtree has no location information. */ + location_t loc; /* Constructor. */ constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr), - heap_dealloc_count (0) {} + heap_dealloc_count (0), loc (input_location) {} tree get_value (tree t) { @@ -2113,7 +2115,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, default: if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), "call to internal function %qE", t); *non_constant_p = true; return t; @@ -2128,7 +2130,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) { - location_t loc = cp_expr_loc_or_input_loc (t); + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); tree type = TREE_TYPE (TREE_TYPE (t)); tree result = fold_binary_loc (loc, opcode, type, fold_convert_loc (loc, type, arg0), @@ -2164,9 +2166,9 @@ clear_no_implicit_zero (tree ctor) EXPR is the MODIFY_EXPR expression performing the modification. */ static void -modifying_const_object_error (tree expr, tree obj) +modifying_const_object_error (const constexpr_ctx* ctx, tree expr, tree obj) { - location_t loc = cp_expr_loc_or_input_loc (expr); + location_t loc = cp_expr_loc_or_loc (expr, ctx->global->loc); auto_diagnostic_group d; error_at (loc, "modifying a const object %qE is not allowed in " "a constant expression", TREE_OPERAND (expr, 0)); @@ -2358,7 +2360,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, tree obj = CALL_EXPR_ARG (call, 0); tree type = CALL_EXPR_ARG (call, 2); HOST_WIDE_INT hint = int_cst_value (CALL_EXPR_ARG (call, 3)); - location_t loc = cp_expr_loc_or_input_loc (call); + location_t loc = cp_expr_loc_or_loc (call, ctx->global->loc); /* Get the target type of the dynamic_cast. */ gcc_assert (TREE_CODE (type) == ADDR_EXPR); @@ -3656,7 +3658,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, && integer_zerop (lhs) && !integer_zerop (rhs)) { if (!ctx->quiet) - error ("arithmetic involving a null pointer in %qE", lhs); + error_at (loc, "arithmetic involving a null pointer in %qE", lhs); *non_constant_p = true; return t; } @@ -4149,7 +4151,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t, bool allow_one_past, bool *non_constant_p, bool *overflow_p) { - location_t loc = cp_expr_loc_or_input_loc (t); + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue, @@ -4187,6 +4189,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, value_cat lval, bool *non_constant_p, bool *overflow_p) { + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); tree oldary = TREE_OPERAND (t, 0); tree ary = cxx_eval_constant_expression (ctx, oldary, lval, @@ -4274,7 +4277,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, building; if there's no initializer for this element yet, that's an error. */ if (!ctx->quiet) - error ("accessing uninitialized array element"); + error_at (loc, "accessing uninitialized array element"); *non_constant_p = true; return t; } @@ -4323,13 +4326,14 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, non_constant_p, overflow_p); + location_t loc = cp_expr_loc_or_loc (whole, ctx->global->loc); if (*non_constant_p) return t; if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0))) { if (!ctx->quiet) - error ("dereferencing a null pointer in %qE", orig_whole); + error_at (loc, "dereferencing a null pointer in %qE", orig_whole); *non_constant_p = true; return t; } @@ -4348,7 +4352,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, if (TREE_CODE (whole) != CONSTRUCTOR) { if (!ctx->quiet) - error ("%qE is not a constant expression", orig_whole); + error_at (loc, "%qE is not a constant expression", orig_whole); *non_constant_p = true; return t; } @@ -4356,7 +4360,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, && DECL_MUTABLE_P (part)) { if (!ctx->quiet) - error ("mutable %qD is not usable in a constant expression", part); + error_at (loc, "mutable %qD is not usable in a constant expression", part); *non_constant_p = true; return t; } @@ -4386,10 +4390,10 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, { constructor_elt *cep = CONSTRUCTOR_ELT (whole, 0); if (cep->value == NULL_TREE) - error ("accessing uninitialized member %qD", part); + error_at (loc, "accessing uninitialized member %qD", part); else - error ("accessing %qD member instead of initialized %qD member in " - "constant expression", part, cep->index); + error_at (loc, "accessing %qD member instead of initialized %qD member " + "in constant expression", part, cep->index); } *non_constant_p = true; return t; @@ -4408,7 +4412,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, building; if there's no initializer for this member yet, that's an error. */ if (!ctx->quiet) - error ("accessing uninitialized member %qD", part); + error_at (loc, "accessing uninitialized member %qD", part); *non_constant_p = true; return t; } @@ -4436,6 +4440,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, non_constant_p, overflow_p); + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); tree start, field, value; unsigned HOST_WIDE_INT i; @@ -4448,7 +4453,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, && TREE_CODE (whole) != CONSTRUCTOR) { if (!ctx->quiet) - error ("%qE is not a constant expression", orig_whole); + error_at (loc, "%qE is not a constant expression", orig_whole); *non_constant_p = true; } if (*non_constant_p) @@ -4460,7 +4465,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, TREE_OPERAND (t, 1), TREE_OPERAND (t, 2))) return r; if (!ctx->quiet) - error ("%qE is not a constant expression", orig_whole); + error_at (loc, "%qE is not a constant expression", orig_whole); *non_constant_p = true; return t; } @@ -5609,6 +5614,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, value_cat lval, bool *non_constant_p, bool *overflow_p) { + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); tree orig_op0 = TREE_OPERAND (t, 0); bool empty_base = false; @@ -5639,7 +5645,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, if (!lval && integer_zerop (op0)) { if (!ctx->quiet) - error ("dereferencing a null pointer"); + error_at (loc, "dereferencing a null pointer"); *non_constant_p = true; return t; } @@ -5658,8 +5664,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); /* DR 1188 says we don't have to deal with this. */ if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "accessing value of %qE through a %qT glvalue in a " + error_at (loc, "accessing value of %qE through a %qT glvalue in a " "constant expression", build_fold_indirect_ref (sub), TREE_TYPE (t)); *non_constant_p = true; @@ -5906,6 +5911,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, value_cat lval, bool *non_constant_p, bool *overflow_p) { + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); constexpr_ctx new_ctx = *ctx; tree init = TREE_OPERAND (t, 1); @@ -6030,7 +6036,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, /* A constant-expression cannot modify objects from outside the constant-expression. */ if (!ctx->quiet) - error ("modification of %qE is not a constant expression", object); + error_at (loc, "modification of %qE is not a constant expression", object); *non_constant_p = true; return t; } @@ -6128,7 +6134,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (cxx_dialect < cxx20) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), "change of the active member of a union " "from %qD to %qD", CONSTRUCTOR_ELT (*valp, 0)->index, @@ -6141,7 +6147,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, /* Diagnose changing the active union member while the union is in the process of being initialized. */ if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (cp_expr_loc_or_loc (t, ctx->global->loc), "change of the active member of a union " "from %qD to %qD during initialization", CONSTRUCTOR_ELT (*valp, 0)->index, @@ -6224,7 +6230,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (fail) { if (!ctx->quiet) - modifying_const_object_error (t, const_object_being_modified); + modifying_const_object_error (ctx, t, const_object_being_modified); *non_constant_p = true; return t; } @@ -6381,6 +6387,8 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, tree offset = TREE_OPERAND (t, 1); gcc_assert (TREE_CONSTANT (offset)); + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); + /* OFFSET is constant, but perhaps not constant enough. We need to e.g. bash FLOAT_EXPRs to REAL_CSTs. */ offset = fold_simple (offset); @@ -6428,8 +6436,7 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, VERIFY_CONSTANT (mod); /* Storing the modified value. */ - tree store = build2_loc (cp_expr_loc_or_loc (t, input_location), - MODIFY_EXPR, type, op, mod); + tree store = build2_loc (loc, MODIFY_EXPR, type, op, mod); mod = cxx_eval_constant_expression (ctx, store, lval, non_constant_p, overflow_p); ggc_free (store); @@ -6602,6 +6609,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p, tree *jump_target) { + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); constexpr_ctx new_ctx = *ctx; tree local_target; if (!jump_target) @@ -6691,7 +6699,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, if (++count >= constexpr_loop_limit) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (loc, "%<constexpr%> loop iteration count exceeds limit of %d " "(use %<-fconstexpr-loop-limit=%> to increase the limit)", constexpr_loop_limit); @@ -6950,7 +6958,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } - location_t loc = cp_expr_loc_or_input_loc (t); + /* Track current location, propagating down from parent calls + in case this expression has no location information. */ + location_t loc = cp_expr_loc_or_loc (t, ctx->global->loc); + ctx->global->loc = loc; STRIP_ANY_LOCATION_WRAPPER (t); @@ -6973,8 +6984,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, && !integer_zerop (t)) { if (!ctx->quiet) - error ("value %qE of type %qT is not a constant expression", - t, TREE_TYPE (t)); + error_at (loc, "value %qE of type %qT is not a constant expression", + t, TREE_TYPE (t)); *non_constant_p = true; } @@ -7222,8 +7233,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (!ctx->quiet) { auto_diagnostic_group d; - error ("temporary of non-literal type %qT in a " - "constant expression", type); + error_at (loc, "temporary of non-literal type %qT in a " + "constant expression", type); explain_non_literal_class (type); } *non_constant_p = true; @@ -8025,8 +8036,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (function_concept_p (tmpl)) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "function concept must be called"); + error_at (loc, "function concept must be called"); r = error_mark_node; break; } @@ -8121,6 +8131,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; } + /* Reset current location in case it was modified in child calls. */ + ctx->global->loc = loc; + if (r == error_mark_node) *non_constant_p = true; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C index 4574eb83ff7..11630f26ffe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C @@ -10,11 +10,11 @@ // R() is well-formed because i is initialized before j. struct s { - constexpr s() : v(v) { } + constexpr s() : v(v) { } // { dg-error "accessing uninitialized member" } int v; }; -constexpr s bang; // { dg-error "|" } +constexpr s bang; // { dg-message "in .constexpr. expansion" } struct R { int i,j; @@ -26,14 +26,14 @@ constexpr R r; // { dg-bogus "" } // Ill-formed (no diagnostic required) struct T { int i; - constexpr int f() { return i; } + constexpr int f() { return i; } // { dg-error "accessing uninitialized member" } constexpr T(): i(0) { } - constexpr T(const T& t) : i(f()) { } // { dg-message "" } + constexpr T(const T& t) : i(f()) { } // { dg-message "in .constexpr. expansion" } }; constexpr T t1; // Ill-formed (diagnostic required) -constexpr T t2(t1); // { dg-message "" } +constexpr T t2(t1); // { dg-message "in .constexpr. expansion" } // Well-formed struct U { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C index 5eedf42ba36..50c676c56cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C @@ -16,7 +16,7 @@ int main() struct complex // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } } { complex(double r, double i) : re(r), im(i) { } - constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } } + constexpr double real() const { return re; } // { dg-error "not a literal type|not usable in a constant expression" "" { target { ! implicit_constexpr } } } double imag() const { return im; } private: diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C index ebaa95e5324..e4e3bf865cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C @@ -2,6 +2,6 @@ // { dg-do compile { target c++11 } } typedef bool (*Function)(int); -constexpr bool check(int x, Function p) { return p(x); } // { dg-message "in .constexpr. expansion of" } +constexpr bool check(int x, Function p) { return p(x); } // { dg-error "lifetime" } -static_assert(check(2, check), ""); // { dg-error "conversion|constant|lifetime|in .constexpr. expansion of" } +static_assert(check(2, check), ""); // { dg-error "conversion|constant|in .constexpr. expansion of" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C index 8ac4ef0fd36..6f8f6a8038e 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C @@ -6,7 +6,7 @@ foo () { union U { long long a; int b[2]; } u { 5LL }; u.b[1] = 4; // { dg-error "change of the active member of a union from" "" { target c++17_down } } - return u.b[0]; + return u.b[0]; // { dg-error "accessing uninitialized array element" "" { target c++2a } } } constexpr int @@ -19,6 +19,5 @@ bar () static_assert (foo () == 0, ""); // { dg-error "non-constant condition for static assertion" } // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } - // { dg-error "accessing uninitialized array element" "" { target c++2a } .-2 } static_assert (bar () == 4, ""); // { dg-error "non-constant condition for static assertion" "" { target c++17_down } } // { dg-message "in 'constexpr' expansion of" "" { target c++17_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C index 43aa7c974c1..f79f1611d5f 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime1.C @@ -11,3 +11,4 @@ constexpr const int& test() { return local.get(); } constexpr int x = test(); // { dg-error "accessing object outside its lifetime" } + diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C index 22cd919fcda..2f5ae8db6d5 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime2.C @@ -8,9 +8,9 @@ struct S { constexpr int error() { const auto& local = S{}.get(); // { dg-message "note: declared here" } - return local; + return local; // { dg-error "accessing object outside its lifetime" } } -constexpr int x = error(); // { dg-error "accessing object outside its lifetime" } +constexpr int x = error(); // { dg-message "in .constexpr. expansion" } constexpr int ok() { // temporary should only be destroyed after end of full-expression diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C index 6329f8cf6c6..53785521d05 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime3.C @@ -7,7 +7,7 @@ constexpr int f(int i) { int j = 123; // { dg-message "note: declared here" } p = &j; } - return *p; + return *p; // { dg-error "accessing object outside its lifetime" } } -constexpr int i = f(0); // { dg-error "accessing object outside its lifetime" } +constexpr int i = f(0); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C index 181a1201663..4302da1eddc 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime4.C @@ -5,7 +5,7 @@ constexpr const double& test() { return local; } -static_assert(test() == 3.0, ""); // { dg-error "constant|accessing object outside its lifetime" } +static_assert(test() == 3.0, ""); // { dg-error "non-constant condition|accessing object outside its lifetime" } // no deference, shouldn't error static_assert((test(), true), ""); diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C index ad3ef579f63..a12920c8fba 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime5.C @@ -5,7 +5,7 @@ constexpr const int& id(int x) { return x; } // { dg-message "note: declared he constexpr bool test() { const int& y = id(3); - return y == 3; + return y == 3; // { dg-error "accessing object outside its lifetime" } } -constexpr bool x = test(); // { dg-error "accessing object outside its lifetime" } +constexpr bool x = test(); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C index 55fe9fa2f0b..3d76345d564 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C @@ -8,8 +8,8 @@ union U { }; constexpr int foo(U *up) { - up->a++; + up->a++; // { dg-error "accessing uninitialized member" } return {42}; } -extern constexpr U u = {}; // { dg-error "accessing uninitialized member" } +extern constexpr U u = {}; // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68180.C b/gcc/testsuite/g++.dg/cpp1y/pr68180.C index 9e6e5e984f9..8de1ef3936b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr68180.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr68180.C @@ -6,11 +6,11 @@ typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t; constexpr float32x4_t fill(float x) { float32x4_t v{0}; constexpr auto vs = sizeof(v)/sizeof(v[0]); - for (auto i=0U; i<vs; ++i) v[i]=i; + for (auto i=0U; i<vs; ++i) v[i]=i; // { dg-error "not a constant" } return v+x; } float32x4_t foo(float32x4_t x) { - constexpr float32x4_t v = fill(1.f); // { dg-error "not a constant||in .constexpr. expansion of " } + constexpr float32x4_t v = fill(1.f); // { dg-message "in .constexpr. expansion of " } return x+v; } diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C index 214d3821299..c46c2d4c7fe 100644 --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C @@ -1,7 +1,7 @@ // Testcase from P0170R1 // { dg-do compile { target c++17 } } -auto monoid = [](auto v) { return [=] { return v; }; }; +auto monoid = [](auto v) { return [=] { return v; }; }; // { dg-error "not usable in a constant expression" } auto add = [](auto m1) constexpr { auto ret = m1(); return [=](auto m2) mutable { @@ -22,7 +22,7 @@ int main() // member function call operator can not perform an lvalue-to-rvalue conversion // on one of its subobjects (that represents its capture) in a constant // expression. - auto two = monoid(2); + auto two = monoid(2); // { dg-message "not declared .constexpr." } if (!(two() == 2)) __builtin_abort(); // OK, not a constant expression. static_assert(add(one)(one)() == two()); // { dg-error "|in .constexpr. expansion of " } two() is not a constant expression static_assert(add(one)(one)() == monoid(2)()); // OK diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C index a3eb31bc6c7..760c9ca40b4 100644 --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast11.C @@ -28,7 +28,7 @@ f3 () { T t = { 1, 2 }; S s = __builtin_bit_cast (S, t); - return s.a[1] == 0; + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } } constexpr bool @@ -52,12 +52,12 @@ f6 () { W t = { 1, 2 }; V s = __builtin_bit_cast (V, t); - return s.b.a[1] == 1; + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } } constexpr bool a = f1 (); constexpr bool b = f2 (); -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } -constexpr bool d = f4 (); +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } constexpr bool e = f5 (); -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C index 9c699dd55f0..e205bc6a8c1 100644 --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast12.C @@ -33,7 +33,7 @@ f3 () { T t = { 1, 2 }; S s = __builtin_bit_cast (S, t); - return s.a[1] == 0; + return s.a[1] == 0; // { dg-error "accessing uninitialized array element" } } constexpr bool @@ -57,12 +57,12 @@ f6 () { W t = { 1, 2 }; V s = __builtin_bit_cast (V, t); - return s.b.a[1] == 1; + return s.b.a[1] == 1; // { dg-error "accessing uninitialized array element" } } constexpr bool a = f1 (); constexpr bool b = f2 (); -constexpr bool c = f3 (); // { dg-error "accessing uninitialized array element" } -constexpr bool d = f4 (); +constexpr bool c = f3 (); // { dg-message "in .constexpr. expansion" } +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } constexpr bool e = f5 (); -constexpr bool f = f6 (); // { dg-error "accessing uninitialized array element" } +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C index 5e185919be4..e0cc9a39702 100644 --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast14.C @@ -44,7 +44,7 @@ f5 () { T1 t = { 0, 0, 0, 0, 0, 0, 0 }; S s = __builtin_bit_cast (S, t); - unsigned char a = s.a; + unsigned char a = s.a; // { dg-error "accessing uninitialized member" } return true; } @@ -53,7 +53,7 @@ f6 () { T2 t = { 0, 0, 0, 0, 0, 0, 0 }; S s = __builtin_bit_cast (S, t); - unsigned char b = s.b; + unsigned char b = s.b; // { dg-error "accessing uninitialized member" } return true; } @@ -62,14 +62,14 @@ f7 () { T3 t = { 0, 0, 0, 0, 0, 0, 0 }; S s = __builtin_bit_cast (S, t); - unsigned char c = s.c; + unsigned char c = s.c; // { dg-error "accessing uninitialized member" } return true; } constexpr bool a = f1 (); constexpr bool b = f2 (); constexpr bool c = f3 (); -constexpr bool d = f4 (); -constexpr bool e = f5 (); // { dg-error "accessing uninitialized member" } -constexpr bool f = f6 (); // { dg-error "accessing uninitialized member" } -constexpr bool g = f7 (); // { dg-error "accessing uninitialized member" } +constexpr bool d = f4 (); // { dg-message "in .constexpr. expansion" } +constexpr bool e = f5 (); // { dg-message "in .constexpr. expansion" } +constexpr bool f = f6 (); // { dg-message "in .constexpr. expansion" } +constexpr bool g = f7 (); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C index 01bdfa5bd4d..b0c91d5ef97 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C @@ -9,7 +9,7 @@ bar () { V f { .b = 42 }; constexpr auto m = &V::a; - return (f.*m) == 42; + return (f.*m) == 42; // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" } } constexpr bool @@ -21,5 +21,5 @@ baz () } static_assert (bar (), ""); // { dg-error "non-constant condition for static assertion" } - // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" "" { target *-*-* } .-1 } + // { dg-message "in .constexpr. expansion" "" { target *-*-* } .-1 } static_assert (baz (), ""); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C index a26678e6ed7..28facf192df 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C @@ -25,8 +25,7 @@ struct D : B, A { constexpr B::B(V* v, A* a) { - dynamic_cast<B*>(a); + dynamic_cast<B*>(a); // { dg-error "accessing uninitialized member" } } -constexpr D d; // { dg-error "accessing uninitialized member" } -// { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } +constexpr D d; // { dg-message "in 'constexpr' expansion of" } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C index e56ecfed48a..b4e39b6f928 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C @@ -52,11 +52,10 @@ constexpr int fn5 () { struct S { int a = 9; int b; } s; - return s.b; + return s.b; // { dg-error "accessing uninitialized member" } } -constexpr int b = fn5 (); // { dg-error "accessing uninitialized member" } -// { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 } +constexpr int b = fn5 (); // { dg-message "in .constexpr. expansion of" } constexpr int fn6 () diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C index 5a3d06a5fab..832782e1427 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C @@ -17,11 +17,11 @@ struct B : A { constexpr int foo () { - A *a = new B (); + A *a = new B (); // { dg-message "allocated here" } a->a = 4; delete a; - int r = a->foo (); + int r = a->foo (); // { dg-error "constant expression" } return r; } -constexpr auto a = foo (); // { dg-error "constant expression" } +constexpr auto a = foo (); // { dg-message "in .constexpr. expansion" } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C index 70b841208f8..3ba440fec53 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C @@ -45,11 +45,10 @@ constexpr bool f5 () { int *p = new int; // { dg-message "allocated here" } - return *p == 1; + return *p == 1; // { dg-error "the content of uninitialized storage is not usable in a constant expression" } } -constexpr auto v5 = f5 (); // { dg-error "the content of uninitialized storage is not usable in a constant expression" } - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } +constexpr auto v5 = f5 (); // { dg-message "in 'constexpr' expansion of" } constexpr bool f6 () @@ -57,11 +56,10 @@ f6 () int *p = new int (2); // { dg-message "allocated here" } int *q = p; delete p; - return *q == 2; + return *q == 2; // { dg-error "use of allocated storage after deallocation in a constant expression" } } -constexpr auto v6 = f6 (); // { dg-error "use of allocated storage after deallocation in a constant expression" } - // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 } +constexpr auto v6 = f6 (); // { dg-message "in 'constexpr' expansion of" } constexpr int * f7 () diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C index d4ea7c58c0d..e09a27af3de 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C @@ -4,7 +4,7 @@ constexpr int fn_bad (int n) { - __extension__ int a [n] = { 0 }; + __extension__ int a [n] = { 0 }; // { dg-error "array subscript" } int z = a [0] + (n ? fn_bad (n - 1) : 0); // { dg-message "in .constexpr. expansion of " } return z; } @@ -18,4 +18,4 @@ fn_ok (int n) } constexpr int i1 = fn_ok (3); -constexpr int i2 = fn_bad (3); // { dg-error "array subscript|in .constexpr. expansion of " } +constexpr int i2 = fn_bad (3); // { dg-message "in .constexpr. expansion of " } diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C index 538b576a825..6f9daa1897f 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C @@ -4,11 +4,11 @@ constexpr int foo (int n) { - __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; + __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; // { dg-error "array subscript" } int z = 0; for (int i = 0; i <= n; ++i) z += a[i]; return z; } -constexpr int n = foo (3); // { dg-error "array subscript|in .constexpr. expansion of " } +constexpr int n = foo (3); // { dg-message "in .constexpr. expansion of " } diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C index 3a1596e6e2e..0771732ef00 100644 --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C @@ -100,13 +100,13 @@ constexpr int fn7 (const int *a, int b) { if (b != 3) - return fn6 (*a, b); + return fn6 (*a, b); // { dg-error "null pointer" } return 7; } constexpr int n1 = 7; constexpr int n2 = fn7 (&n1, 5); -constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "null pointer|in .constexpr. expansion of " } +constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-message "in .constexpr. expansion of " } constexpr int fn8 (int i) diff --git a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc index 34ca5c4805c..fd89ac0e166 100644 --- a/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc +++ b/libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc @@ -32,7 +32,7 @@ test01() return outa; } -static_assert(test01()); // { dg-error "outside the bounds" } +static_assert(test01()); // { dg-error "non-constant condition" } constexpr bool test02() @@ -44,7 +44,8 @@ test02() return outa; } -static_assert(test02()); // { dg-error "outside the bounds" } +static_assert(test02()); // { dg-error "non-constant condition" } -// { dg-prune-output "non-constant condition" } +// Errors occuring within <algorithm> internals: +// { dg-error "outside the bounds of array" "" { target *-*-* } 0 } // { dg-prune-output "in 'constexpr'" }
This patch caches the current expression's location information in the constexpr_global_ctx struct, which allows subexpressions that have lost location information to still provide accurate diagnostics. Also rewrites a number of 'error' calls as 'error_at' to provide more specific location information. The primary effect of this change is that many errors within evaluation of a constexpr function will now point at the offending expression (with expansion tracing information) rather than just the outermost call. gcc/cp/ChangeLog: * constexpr.cc (constexpr_global_ctx): New field for cached tree location, defaulting to input_location. (cxx_eval_internal_function): Fall back to ctx->global->loc rather than input_location. (modifying_const_object_error): Likewise. (cxx_eval_dynamic_cast_fn): Likewise. (eval_and_check_array_index): Likewise. (cxx_eval_array_reference): Likewise. (cxx_eval_bit_field_ref): Likewise. (cxx_eval_component_reference): Likewise. (cxx_eval_indirect_ref): Likewise. (cxx_eval_store_expression): Likewise. (cxx_eval_increment_expression): Likewise. (cxx_eval_loop_expr): Likewise. (cxx_eval_binary_expression): Likewise. (cxx_eval_constant_expression): Cache location of trees for use in errors, and prefer it instead of input_location. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-48089.C: Updated diagnostic locations. * g++.dg/cpp0x/constexpr-diag3.C: Likewise. * g++.dg/cpp0x/constexpr-ice20.C: Likewise. * g++.dg/cpp1y/constexpr-89481.C: Likewise. * g++.dg/cpp1y/constexpr-lifetime1.C: Likewise. * g++.dg/cpp1y/constexpr-lifetime2.C: Likewise. * g++.dg/cpp1y/constexpr-lifetime3.C: Likewise. * g++.dg/cpp1y/constexpr-lifetime4.C: Likewise. * g++.dg/cpp1y/constexpr-lifetime5.C: Likewise. * g++.dg/cpp1y/constexpr-union5.C: Likewise. * g++.dg/cpp1y/pr68180.C: Likewise. * g++.dg/cpp1z/constexpr-lambda6.C: Likewise. * g++.dg/cpp2a/bit-cast11.C: Likewise. * g++.dg/cpp2a/bit-cast12.C: Likewise. * g++.dg/cpp2a/bit-cast14.C: Likewise. * g++.dg/cpp2a/constexpr-98122.C: Likewise. * g++.dg/cpp2a/constexpr-dynamic17.C: Likewise. * g++.dg/cpp2a/constexpr-init1.C: Likewise. * g++.dg/cpp2a/constexpr-new12.C: Likewise. * g++.dg/cpp2a/constexpr-new3.C: Likewise. * g++.dg/ext/constexpr-vla2.C: Likewise. * g++.dg/ext/constexpr-vla3.C: Likewise. * g++.dg/ubsan/pr63956.C: Likewise. libstdc++/ChangeLog: * testsuite/25_algorithms/equal/constexpr_neg.cc: Updated diagnostics locations. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> --- gcc/cp/constexpr.cc | 83 +++++++++++-------- gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C | 10 +-- gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C | 4 +- gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C | 3 +- .../g++.dg/cpp1y/constexpr-lifetime1.C | 1 + .../g++.dg/cpp1y/constexpr-lifetime2.C | 4 +- .../g++.dg/cpp1y/constexpr-lifetime3.C | 4 +- .../g++.dg/cpp1y/constexpr-lifetime4.C | 2 +- .../g++.dg/cpp1y/constexpr-lifetime5.C | 4 +- gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C | 4 +- gcc/testsuite/g++.dg/cpp1y/pr68180.C | 4 +- .../g++.dg/cpp1z/constexpr-lambda6.C | 4 +- gcc/testsuite/g++.dg/cpp2a/bit-cast11.C | 10 +-- gcc/testsuite/g++.dg/cpp2a/bit-cast12.C | 10 +-- gcc/testsuite/g++.dg/cpp2a/bit-cast14.C | 14 ++-- gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C | 4 +- .../g++.dg/cpp2a/constexpr-dynamic17.C | 5 +- gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C | 5 +- gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C | 6 +- gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C | 10 +-- gcc/testsuite/g++.dg/ext/constexpr-vla2.C | 4 +- gcc/testsuite/g++.dg/ext/constexpr-vla3.C | 4 +- gcc/testsuite/g++.dg/ubsan/pr63956.C | 4 +- .../25_algorithms/equal/constexpr_neg.cc | 7 +- 25 files changed, 111 insertions(+), 101 deletions(-)