tree norm = NULL_TREE;
if (tree ci = get_constraints (decl))
{
- push_nested_class_guard pncs (DECL_CONTEXT (d));
-
- temp_override<tree> ovr (current_function_decl);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- current_function_decl = decl;
-
+ push_access_scope_guard pas (decl);
norm = get_normalized_constraints_from_info (ci, tmpl, diag);
}
return is_auto (t) && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t);
}
-/* RAII class to push/pop class scope T; if T is not a class, do nothing. */
+/* RAII class to push/pop the access scope for T. */
-struct push_nested_class_guard
+struct push_access_scope_guard
{
- bool push;
- push_nested_class_guard (tree t)
- : push (t && CLASS_TYPE_P (t))
+ tree decl;
+ push_access_scope_guard (tree t)
+ : decl (t)
{
- if (push)
- push_nested_class (t);
+ if (VAR_OR_FUNCTION_DECL_P (decl)
+ || TREE_CODE (decl) == TYPE_DECL)
+ push_access_scope (decl);
+ else
+ decl = NULL_TREE;
}
- ~push_nested_class_guard ()
+ ~push_access_scope_guard ()
{
- if (push)
- pop_nested_class ();
+ if (decl)
+ pop_access_scope (decl);
}
};
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
template, VAR_DECL for static member variable, or TYPE_DECL for
- alias template (needed by instantiate_decl). */
+ for a class or alias template (needed by instantiate_decl). */
void
push_access_scope (tree t)
if (DECL_FRIEND_CONTEXT (t))
push_nested_class (DECL_FRIEND_CONTEXT (t));
+ else if (DECL_IMPLICIT_TYPEDEF_P (t)
+ && CLASS_TYPE_P (TREE_TYPE (t)))
+ push_nested_class (TREE_TYPE (t));
else if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t))
current_function_decl = saved_access_scope->pop();
if (DECL_FRIEND_CONTEXT (t)
+ || (DECL_IMPLICIT_TYPEDEF_P (t)
+ && CLASS_TYPE_P (TREE_TYPE (t)))
|| DECL_CLASS_SCOPE_P (t)
|| (deduction_guide_p (t) && DECL_ARTIFICIAL (t)))
pop_nested_class ();
--- /dev/null
+// { dg-do compile { target concepts } }
+
+template<class T> requires T::value struct A { };
+template<class T> requires T::value struct B { }; // { dg-error "private" }
+
+struct S {
+private:
+ static constexpr bool value = true;
+ template<class T> requires T::value friend struct A;
+};
+
+A<S> x;
+B<S> y; // { dg-error "constraint" }