tree templ = TREE_OPERAND (var, 0);
tree arglist = TREE_OPERAND (var, 1);
- tree tmpl_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (templ));
- arglist = add_outermost_template_args (tmpl_args, arglist);
-
- templ = most_general_template (templ);
tree parms = DECL_TEMPLATE_PARMS (templ);
arglist = coerce_innermost_template_parms (parms, arglist, templ, complain,
/*req_all*/true,
deferring_access_check_sentinel acs (dk_no_deferred);
/* Determine what specialization of the original template to
- instantiate; do this relative to the scope of the class for
- sake of access checking. */
- push_nested_class (type);
+ instantiate. */
t = most_specialized_partial_spec (type, tf_warning_or_error);
- pop_nested_class ();
if (t == error_mark_node)
return error_mark_node;
else if (t)
/* We need to determine if we're using a partial or explicit
specialization now, because the type of the variable could be
different. */
- tree tid = lookup_template_variable (gen_tmpl, targ_ptr);
+ tree tid = lookup_template_variable (tmpl, targ_ptr);
tree elt = most_specialized_partial_spec (tid, complain);
if (elt == error_mark_node)
pattern = error_mark_node;
tree outer_args = NULL_TREE;
tree tmpl, args;
+ tree decl;
if (TYPE_P (target))
{
tree tinfo = CLASSTYPE_TEMPLATE_INFO (target);
tmpl = TI_TEMPLATE (tinfo);
args = TI_ARGS (tinfo);
+ decl = TYPE_NAME (target);
}
else if (TREE_CODE (target) == TEMPLATE_ID_EXPR)
{
tmpl = TREE_OPERAND (target, 0);
args = TREE_OPERAND (target, 1);
+ decl = DECL_TEMPLATE_RESULT (tmpl);
}
else if (VAR_P (target))
{
tree tinfo = DECL_TEMPLATE_INFO (target);
tmpl = TI_TEMPLATE (tinfo);
args = TI_ARGS (tinfo);
+ decl = target;
}
else
gcc_unreachable ();
+ push_access_scope_guard pas (decl);
+ deferring_access_check_sentinel acs (dk_no_deferred);
+
tree main_tmpl = most_general_template (tmpl);
/* For determining which partial specialization to use, only the
if (variable_template_specialization_p (d))
{
/* Look up an explicit specialization, if any. */
- tree tid = lookup_template_variable (gen_tmpl, gen_args);
- tree elt = most_specialized_partial_spec (tid, tf_warning_or_error);
+ tree elt = most_specialized_partial_spec (d, tf_warning_or_error);
if (elt && elt != error_mark_node)
{
td = TREE_VALUE (elt);
--- /dev/null
+// PR c++/96204
+// { dg-do compile { target c++14 } }
+// A variant of access40.C where has_type_member is a variable template instead
+// of a class template.
+
+template<class, class = void>
+constexpr bool has_type_member = false;
+
+template<class T>
+constexpr bool has_type_member<T, typename T::type> = true;
+
+struct Parent;
+
+struct Child {
+private:
+ friend struct Parent;
+ typedef void type;
+};
+
+struct Parent {
+ // The partial specialization does not match despite Child::type
+ // being accessible from the current scope.
+ static_assert(!has_type_member<Child>, "");
+};
--- /dev/null
+// PR c++/96204
+// { dg-do compile { target c++14 } }
+// A variant of access40a.C where has_type_member is a variable template instead
+// of a class template.
+
+template<class T>
+struct A {
+ template<class, class = void>
+ static constexpr bool has_type_member = false;
+};
+
+template<class T>
+template<class U>
+constexpr int A<T>::has_type_member<U, typename U::type> = true;
+
+struct Child {
+private:
+ friend struct A<int>;
+ typedef void type;
+};
+
+// The partial specialization matches because A<int> is a friend of Child.
+static_assert(A<int>::has_type_member<Child>, "");
+using type1 = const int;
+using type1 = decltype(A<int>::has_type_member<Child>);
+
+static_assert(!A<char>::has_type_member<Child>, "");
+using type2 = const bool;
+using type2 = decltype(A<char>::has_type_member<Child>);