[PATCH] c++: access of dtor named by qualified template-id [PR100918]

Patrick Palka ppalka@redhat.com
Fri Jun 4 21:08:50 GMT 2021


Here, when resolving the destructor named by Inner<int>::~Inner<int>
(which is valid only before C++20) we end up in cp_parser_lookup_name to
look up the name Inner relative to the scope Inner<int>.  The lookup
naturally finds the injected-class-name Inner<int>, and because
is_template is true, we adjust this lookup result to the TEMPLATE_DECL
Inner, and then check access of this adjusted lookup result.  But this
access check fails because the scope is Inner<int> and not Outer, and
the context_for_name_lookup of the TEMPLATE_DECL is Outer.

The simplest fix seems to be to perform the access check on the original
lookup result (the injected-class-name) instead of the TEMPLATE_DECL.
So this patch moves the access check in cp_parser_lookup_name to before
the injected-class-name adjustment.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

	PR c++/100918

gcc/cp/ChangeLog:

	* parser.c (cp_parser_lookup_name): Check access of the lookup
	result before we potentially adjust an injected-class-name to
	its TEMPLATE_DECL.

gcc/testsuite/ChangeLog:

	* g++.dg/template/access38.C: New test.
---
 gcc/cp/parser.c                          | 24 +++++++++++++-----------
 gcc/testsuite/g++.dg/template/access38.C | 15 +++++++++++++++
 2 files changed, 28 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/access38.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4a46828e162..829a94b2928 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29505,6 +29505,19 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (!decl || decl == error_mark_node)
     return error_mark_node;
 
+  /* If we have resolved the name of a member declaration, check to
+     see if the declaration is accessible.  When the name resolves to
+     set of overloaded functions, accessibility is checked when
+     overload resolution is done.  If we have a TREE_LIST, then the lookup
+     is either ambiguous or it found multiple injected-class-names, the
+     accessibility of which is trivially satisfied.
+
+     During an explicit instantiation, access is not checked at all,
+     as per [temp.explicit].  */
+  if (DECL_P (decl))
+    check_accessibility_of_qualified_id (decl, object_type, parser->scope,
+					 tf_warning_or_error);
+
   /* Pull out the template from an injected-class-name (or multiple).  */
   if (is_template)
     decl = maybe_get_template_decl_from_type_decl (decl);
@@ -29531,17 +29544,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	      || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
 	      || BASELINK_P (decl));
 
-  /* If we have resolved the name of a member declaration, check to
-     see if the declaration is accessible.  When the name resolves to
-     set of overloaded functions, accessibility is checked when
-     overload resolution is done.
-
-     During an explicit instantiation, access is not checked at all,
-     as per [temp.explicit].  */
-  if (DECL_P (decl))
-    check_accessibility_of_qualified_id (decl, object_type, parser->scope,
-					 tf_warning_or_error);
-
   maybe_record_typedef_use (decl);
 
   return cp_expr (decl, name_location);
diff --git a/gcc/testsuite/g++.dg/template/access38.C b/gcc/testsuite/g++.dg/template/access38.C
new file mode 100644
index 00000000000..488f8650c97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access38.C
@@ -0,0 +1,15 @@
+// PR c++/100918
+
+struct Outer {
+  template<class T>
+  struct Inner { ~Inner(); };
+};
+
+template<>
+Outer::Inner<int>::~Inner<int>() { } // { dg-error "template-id" "" { target c++20 } }
+
+template<class T>
+Outer::Inner<T>::~Inner<T>() { } // { dg-error "template-id" "" { target c++20 } }
+
+Outer::Inner<int> x;
+Outer::Inner<char> y;
-- 
2.32.0.rc2



More information about the Gcc-patches mailing list