Hi! When a variable template (both static data member of some class or at namespace level) is accessed without template arguments, finish_id_expression_1 handles it through: /* If we didn't find anything, or what we found was a type, then this wasn't really an id-expression. */ if (TREE_CODE (decl) == TEMPLATE_DECL && !DECL_FUNCTION_TEMPLATE_P (decl)) { *error_msg = G_("missing template arguments"); return error_mark_node; } On the following invalid testcase the access is from within a template and in that case finish_id_expression{,_1} isn't really called for that, instead tsubst_qualified_id just calls finish_qualified_id_expr.
The ICE is because we pass over a TEMPLATE_DECL to the middle-end (e.g. on rhs of an INIT_EXPR etc.). The following patch does something similar to what finish_id_expression_1 does. Bootstrapped/regtested on x86_64-linux and i686-linux. Or should it be done in tsubst_qualified_id instead (before or after the finish_qualified_id_expr call? 2019-03-13 Jakub Jelinek <ja...@redhat.com> PR c++/89512 * semantics.c (finish_qualified_id_expr): Reject variable templates. * g++.dg/cpp1y/var-templ61.C: New test. --- gcc/cp/semantics.c.jj 2019-03-08 11:45:27.556465237 +0100 +++ gcc/cp/semantics.c 2019-03-13 17:41:58.694698814 +0100 @@ -2112,6 +2112,14 @@ finish_qualified_id_expr (tree qualifyin expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false, complain); } + else if (!template_p + && TREE_CODE (expr) == TEMPLATE_DECL + && !DECL_FUNCTION_TEMPLATE_P (expr)) + { + if (complain & tf_error) + error ("%qE missing template arguments", expr); + return error_mark_node; + } else { /* In a template, return a SCOPE_REF for most qualified-ids --- gcc/testsuite/g++.dg/cpp1y/var-templ61.C.jj 2019-03-13 17:36:33.895936102 +0100 +++ gcc/testsuite/g++.dg/cpp1y/var-templ61.C 2019-03-13 17:41:30.868147514 +0100 @@ -0,0 +1,20 @@ +// PR c++/89512 +// { dg-do compile { target c++14 } } + +struct A { + template <typename T> + static const int a = 0; +}; + +struct B { + template <typename T> + static int foo () + { + return T::a; // { dg-error "missing template arguments" } + } +}; + +int bar () +{ + return B::foo<A> (); // { dg-message "required from here" } +} Jakub