From: Patrick Palka Date: Wed, 30 Jun 2021 17:12:36 +0000 (-0400) Subject: c++: Fix push_access_scope and introduce RAII wrapper for it X-Git-Tag: basepoints/gcc-13~6376 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c28e1d288ab727de6eb493e1aa2eadf5d5eef3ab;p=thirdparty%2Fgcc.git c++: Fix push_access_scope and introduce RAII wrapper for it When push_access_scope is passed a TYPE_DECL for a class type (which can happen during e.g. satisfaction), we undesirably push only the enclosing context of the class instead of the class itself. This causes us to mishandle e.g. testcase below due to us not entering the scope of A before checking its constraints. This patch adjusts push_access_scope accordingly, and introduces an RAII wrapper for it. We make use of this wrapper right away by replacing the only user of push_nested_class_guard with this new wrapper, which means we can remove push_nested_class_guard (whose functionality is basically subsumed by the new wrapper). gcc/cp/ChangeLog: * constraint.cc (get_normalized_constraints_from_decl): Use push_access_scope_guard instead of push_nested_class_guard. * cp-tree.h (struct push_nested_class_guard): Replace with ... (struct push_access_scope_guard): ... this. * pt.c (push_access_scope): When the argument corresponds to a class type, push the class instead of its context. (pop_access_scope): Adjust accordingly. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-access2.C: New test. --- diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 6df3ca6ce323..99d3ccc69980 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -926,12 +926,7 @@ get_normalized_constraints_from_decl (tree d, bool diag = false) tree norm = NULL_TREE; if (tree ci = get_constraints (decl)) { - push_nested_class_guard pncs (DECL_CONTEXT (d)); - - temp_override 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); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6f713719589b..58da74600015 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8463,21 +8463,24 @@ is_constrained_auto (const_tree t) 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); } }; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d2936c106ba2..f8f7616bf2a1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -224,7 +224,7 @@ static void instantiate_body (tree pattern, tree args, tree d, bool nested); /* 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) @@ -234,6 +234,9 @@ 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)) @@ -260,6 +263,8 @@ pop_access_scope (tree 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 (); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C new file mode 100644 index 000000000000..8ddcad236e39 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-access2.C @@ -0,0 +1,13 @@ +// { dg-do compile { target concepts } } + +template requires T::value struct A { }; +template requires T::value struct B { }; // { dg-error "private" } + +struct S { +private: + static constexpr bool value = true; + template requires T::value friend struct A; +}; + +A x; +B y; // { dg-error "constraint" }