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.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * 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.
---
 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 ++++++++
 4 files changed, 41 insertions(+), 26 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ64.C

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,
                  "%<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 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 <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 00000000000..4e2b43b1d07
--- /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>();
+}

base-commit: 17a2c588c29f089d3c2a36df47175bbdf376e399
-- 
2.18.1

Reply via email to