aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c44
-rw-r--r--gcc/cp/pt.c7
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr67595.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ64.C14
5 files changed, 49 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9f27a58..6cf8579 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+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>
* typeck.c (cp_build_unary_op): Consistently use the accurate
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 658455c..f648b1d 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,
"%<constexpr%> 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,
"%<reinterpret_cast%> 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<void*>(sizeof 0)
*/
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
- "%<reinterpret_cast<%T>(%E)%> is not "
+ error_at (loc, "%<reinterpret_cast<%T>(%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 78b78ba..a11718e 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 7199e05..029ec7a 100644
--- a/gcc/testsuite/g++.dg/concepts/pr67595.C
+++ b/gcc/testsuite/g++.dg/concepts/pr67595.C
@@ -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 bidirectional_iterator{forward_iterator<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);
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 0000000..4e2b43b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ64.C
@@ -0,0 +1,14 @@
+// { 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>();
+}