From 6821245b3fd9e392ca56dfab4a4921a59ffa234b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 26 Nov 2019 22:14:33 -0500 Subject: [PATCH] Remember the location of a variable template-id. I noticed that tsubst of a TEMPLATE_ID_EXPR was losing the location information from its EXPR_LOCATION. Then I noticed that cxx_eval_constant_expression was also throwing away location information for variable references. * pt.c (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: Remember the location of a variable template-id. * constexpr.c (cxx_eval_constant_expression): Get expr location before stripping location wrappers. (non_const_var_error): Take location argument. From-SVN: r278755 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/constexpr.c | 44 +++++++++++------------- gcc/cp/pt.c | 7 +++- gcc/testsuite/g++.dg/concepts/pr67595.C | 2 +- gcc/testsuite/g++.dg/cpp1y/var-templ64.C | 14 ++++++++ 5 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ64.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9f27a58cc6b..6cf8579377d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-11-26 Jason Merrill + + * pt.c (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: Remember the + location of a variable template-id. + * constexpr.c (cxx_eval_constant_expression): Get expr location + before stripping location wrappers. + (non_const_var_error): Take location argument. + 2019-11-26 Paolo Carlini * typeck.c (cp_build_unary_op): Consistently use the accurate diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 658455cce96..f648b1d8e4c 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3786,27 +3786,27 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, cxx_eval_constant_expression. */ static void -non_const_var_error (tree r) +non_const_var_error (location_t loc, tree r) { auto_diagnostic_group d; tree type = TREE_TYPE (r); if (DECL_NAME (r) == heap_uninit_identifier || DECL_NAME (r) == heap_identifier) { - error ("the content of uninitialized storage is not usable " - "in a constant expression"); + error_at (loc, "the content of uninitialized storage is not usable " + "in a constant expression"); inform (DECL_SOURCE_LOCATION (r), "allocated here"); return; } if (DECL_NAME (r) == heap_deleted_identifier) { - error ("use of allocated storage after deallocation in a " - "constant expression"); + error_at (loc, "use of allocated storage after deallocation in a " + "constant expression"); inform (DECL_SOURCE_LOCATION (r), "allocated here"); return; } - error ("the value of %qD is not usable in a constant " - "expression", r); + error_at (loc, "the value of %qD is not usable in a constant " + "expression", r); /* Avoid error cascade. */ if (DECL_INITIAL (r) == error_mark_node) return; @@ -4765,6 +4765,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } + location_t loc = cp_expr_loc_or_input_loc (t); + STRIP_ANY_LOCATION_WRAPPER (t); if (CONSTANT_CLASS_P (t)) @@ -4794,7 +4796,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (++ctx->global->constexpr_ops_count >= constexpr_ops_limit) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (loc, "% evaluation operation count exceeds limit of " "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)", constexpr_ops_limit); @@ -4877,7 +4879,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (DECL_P (r)) { if (!ctx->quiet) - non_const_var_error (r); + non_const_var_error (loc, r); *non_constant_p = true; } break; @@ -5086,9 +5088,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, jump_target); if (!CLEANUP_EH_ONLY (t) && !*non_constant_p) { - location_t loc = input_location; - if (EXPR_HAS_LOCATION (t)) - input_location = EXPR_LOCATION (t); + iloc_sentinel ils (loc); /* Also evaluate the cleanup. If we weren't skipping at the start of the CLEANUP_BODY, change jump_target temporarily to &initial_jump_target, so that even a return or break or @@ -5097,7 +5097,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, non_constant_p, overflow_p, jump_target ? &initial_jump_target : NULL); - input_location = loc; } } break; @@ -5365,7 +5364,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (REINTERPRET_CAST_P (t)) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (loc, "% is not a constant expression"); *non_constant_p = true; return t; @@ -5405,7 +5404,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (TYPE_REF_P (type)) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (loc, "dereferencing a null pointer"); *non_constant_p = true; return t; @@ -5417,7 +5416,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (!can_convert (type, from, tf_none)) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), + error_at (loc, "conversion of %qT null pointer to %qT " "is not a constant expression", from, type); @@ -5432,8 +5431,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, reinterpret_cast(sizeof 0) */ if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "%(%E)%> is not " + error_at (loc, "%(%E)%> is not " "a constant expression", type, op); *non_constant_p = true; @@ -5534,8 +5532,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case BASELINK: case OFFSET_REF: if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "expression %qE is not a constant expression", t); + error_at (loc, "expression %qE is not a constant expression", t); *non_constant_p = true; break; @@ -5552,8 +5549,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, || !DECL_P (get_base_address (TREE_OPERAND (obj, 0)))) { if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (t), - "expression %qE is not a constant expression", t); + error_at (loc, "expression %qE is not a constant expression", t); *non_constant_p = true; return t; } @@ -5661,7 +5657,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case ASM_EXPR: if (!ctx->quiet) - inline_asm_in_constexpr_error (cp_expr_loc_or_input_loc (t)); + inline_asm_in_constexpr_error (loc); *non_constant_p = true; return t; @@ -6724,7 +6720,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { if (flags & tf_error) - non_const_var_error (t); + non_const_var_error (loc, t); return false; } return true; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 78b78bab74d..a11718ed41e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18870,7 +18870,12 @@ tsubst_copy_and_build (tree t, } if (variable_template_p (templ)) - RETURN (lookup_and_finish_template_variable (templ, targs, complain)); + { + tree r = lookup_and_finish_template_variable (templ, targs, + complain); + r = maybe_wrap_with_location (r, EXPR_LOCATION (t)); + RETURN (r); + } if (TREE_CODE (templ) == COMPONENT_REF) { diff --git a/gcc/testsuite/g++.dg/concepts/pr67595.C b/gcc/testsuite/g++.dg/concepts/pr67595.C index 7199e0517d4..029ec7a1186 100644 --- a/gcc/testsuite/g++.dg/concepts/pr67595.C +++ b/gcc/testsuite/g++.dg/concepts/pr67595.C @@ -9,6 +9,6 @@ template bool input_iterator{weak_input_iterator}; // { dg-warning template bool forward_iterator{input_iterator}; template bool bidirectional_iterator{forward_iterator}; template -concept bool random_access_iterator{bidirectional_iterator}; +concept bool random_access_iterator{bidirectional_iterator}; // { dg-error "constant" } void fn1(random_access_iterator); int main() { fn1(0); } // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ64.C b/gcc/testsuite/g++.dg/cpp1y/var-templ64.C new file mode 100644 index 00000000000..4e2b43b1d07 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ64.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++14 } } + +template T var = T(); + +template +void f() +{ + constexpr T i = var; // { dg-error "19:var" } +} + +int main() +{ + f(); +} -- 2.30.2