Commit 6821245b by Jason Merrill Committed by Jason Merrill

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
parent 88b34a48
2019-11-26 Jason Merrill <jason@redhat.com>
* 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 <paolo.carlini@oracle.com> 2019-11-26 Paolo Carlini <paolo.carlini@oracle.com>
* typeck.c (cp_build_unary_op): Consistently use the accurate * typeck.c (cp_build_unary_op): Consistently use the accurate
......
...@@ -3786,27 +3786,27 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, ...@@ -3786,27 +3786,27 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
cxx_eval_constant_expression. */ cxx_eval_constant_expression. */
static void static void
non_const_var_error (tree r) non_const_var_error (location_t loc, tree r)
{ {
auto_diagnostic_group d; auto_diagnostic_group d;
tree type = TREE_TYPE (r); tree type = TREE_TYPE (r);
if (DECL_NAME (r) == heap_uninit_identifier if (DECL_NAME (r) == heap_uninit_identifier
|| DECL_NAME (r) == heap_identifier) || DECL_NAME (r) == heap_identifier)
{ {
error ("the content of uninitialized storage is not usable " error_at (loc, "the content of uninitialized storage is not usable "
"in a constant expression"); "in a constant expression");
inform (DECL_SOURCE_LOCATION (r), "allocated here"); inform (DECL_SOURCE_LOCATION (r), "allocated here");
return; return;
} }
if (DECL_NAME (r) == heap_deleted_identifier) if (DECL_NAME (r) == heap_deleted_identifier)
{ {
error ("use of allocated storage after deallocation in a " error_at (loc, "use of allocated storage after deallocation in a "
"constant expression"); "constant expression");
inform (DECL_SOURCE_LOCATION (r), "allocated here"); inform (DECL_SOURCE_LOCATION (r), "allocated here");
return; return;
} }
error ("the value of %qD is not usable in a constant " error_at (loc, "the value of %qD is not usable in a constant "
"expression", r); "expression", r);
/* Avoid error cascade. */ /* Avoid error cascade. */
if (DECL_INITIAL (r) == error_mark_node) if (DECL_INITIAL (r) == error_mark_node)
return; return;
...@@ -4765,6 +4765,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -4765,6 +4765,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return t; return t;
} }
location_t loc = cp_expr_loc_or_input_loc (t);
STRIP_ANY_LOCATION_WRAPPER (t); STRIP_ANY_LOCATION_WRAPPER (t);
if (CONSTANT_CLASS_P (t)) if (CONSTANT_CLASS_P (t))
...@@ -4794,7 +4796,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree 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->global->constexpr_ops_count >= constexpr_ops_limit)
{ {
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc,
"%<constexpr%> evaluation operation count exceeds limit of " "%<constexpr%> evaluation operation count exceeds limit of "
"%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)", "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
constexpr_ops_limit); constexpr_ops_limit);
...@@ -4877,7 +4879,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -4877,7 +4879,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (DECL_P (r)) if (DECL_P (r))
{ {
if (!ctx->quiet) if (!ctx->quiet)
non_const_var_error (r); non_const_var_error (loc, r);
*non_constant_p = true; *non_constant_p = true;
} }
break; break;
...@@ -5086,9 +5088,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5086,9 +5088,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
jump_target); jump_target);
if (!CLEANUP_EH_ONLY (t) && !*non_constant_p) if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
{ {
location_t loc = input_location; iloc_sentinel ils (loc);
if (EXPR_HAS_LOCATION (t))
input_location = EXPR_LOCATION (t);
/* Also evaluate the cleanup. If we weren't skipping at the /* Also evaluate the cleanup. If we weren't skipping at the
start of the CLEANUP_BODY, change jump_target temporarily start of the CLEANUP_BODY, change jump_target temporarily
to &initial_jump_target, so that even a return or break or 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, ...@@ -5097,7 +5097,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p, non_constant_p, overflow_p,
jump_target ? &initial_jump_target jump_target ? &initial_jump_target
: NULL); : NULL);
input_location = loc;
} }
} }
break; break;
...@@ -5365,7 +5364,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5365,7 +5364,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (REINTERPRET_CAST_P (t)) if (REINTERPRET_CAST_P (t))
{ {
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc,
"%<reinterpret_cast%> is not a constant expression"); "%<reinterpret_cast%> is not a constant expression");
*non_constant_p = true; *non_constant_p = true;
return t; return t;
...@@ -5405,7 +5404,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5405,7 +5404,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (TYPE_REF_P (type)) if (TYPE_REF_P (type))
{ {
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc,
"dereferencing a null pointer"); "dereferencing a null pointer");
*non_constant_p = true; *non_constant_p = true;
return t; return t;
...@@ -5417,7 +5416,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5417,7 +5416,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (!can_convert (type, from, tf_none)) if (!can_convert (type, from, tf_none))
{ {
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc,
"conversion of %qT null pointer to %qT " "conversion of %qT null pointer to %qT "
"is not a constant expression", "is not a constant expression",
from, type); from, type);
...@@ -5432,8 +5431,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5432,8 +5431,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
reinterpret_cast<void*>(sizeof 0) reinterpret_cast<void*>(sizeof 0)
*/ */
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc, "%<reinterpret_cast<%T>(%E)%> is not "
"%<reinterpret_cast<%T>(%E)%> is not "
"a constant expression", "a constant expression",
type, op); type, op);
*non_constant_p = true; *non_constant_p = true;
...@@ -5534,8 +5532,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5534,8 +5532,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case BASELINK: case BASELINK:
case OFFSET_REF: case OFFSET_REF:
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc, "expression %qE is not a constant expression", t);
"expression %qE is not a constant expression", t);
*non_constant_p = true; *non_constant_p = true;
break; break;
...@@ -5552,8 +5549,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5552,8 +5549,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|| !DECL_P (get_base_address (TREE_OPERAND (obj, 0)))) || !DECL_P (get_base_address (TREE_OPERAND (obj, 0))))
{ {
if (!ctx->quiet) if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t), error_at (loc, "expression %qE is not a constant expression", t);
"expression %qE is not a constant expression", t);
*non_constant_p = true; *non_constant_p = true;
return t; return t;
} }
...@@ -5661,7 +5657,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ...@@ -5661,7 +5657,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case ASM_EXPR: case ASM_EXPR:
if (!ctx->quiet) 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; *non_constant_p = true;
return t; return t;
...@@ -6724,7 +6720,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, ...@@ -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)) && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{ {
if (flags & tf_error) if (flags & tf_error)
non_const_var_error (t); non_const_var_error (loc, t);
return false; return false;
} }
return true; return true;
......
...@@ -18870,7 +18870,12 @@ tsubst_copy_and_build (tree t, ...@@ -18870,7 +18870,12 @@ tsubst_copy_and_build (tree t,
} }
if (variable_template_p (templ)) 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) if (TREE_CODE (templ) == COMPONENT_REF)
{ {
......
...@@ -9,6 +9,6 @@ template <class X> bool input_iterator{weak_input_iterator<X>}; // { dg-warning ...@@ -9,6 +9,6 @@ template <class X> bool input_iterator{weak_input_iterator<X>}; // { dg-warning
template <class X> bool forward_iterator{input_iterator<X>}; template <class X> bool forward_iterator{input_iterator<X>};
template <class X> bool bidirectional_iterator{forward_iterator<X>}; template <class X> bool bidirectional_iterator{forward_iterator<X>};
template <class X> template <class X>
concept bool random_access_iterator{bidirectional_iterator<X>}; concept bool random_access_iterator{bidirectional_iterator<X>}; // { dg-error "constant" }
void fn1(random_access_iterator); void fn1(random_access_iterator);
int main() { fn1(0); } // { dg-error "" } int main() { fn1(0); } // { dg-error "" }
// { dg-do compile { target c++14 } }
template <class T> T var = T();
template <class T>
void f()
{
constexpr T i = var<T>; // { dg-error "19:var" }
}
int main()
{
f<int>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment