diff mbox series

c++: More set_identifier_type_value fixing [PR 99116]

Message ID eb857883-c8aa-90fd-683d-9f796b31ba66@acm.org
State New
Headers show
Series c++: More set_identifier_type_value fixing [PR 99116] | expand

Commit Message

Nathan Sidwell Feb. 17, 2021, 1:41 p.m. UTC
My recent change looked	under template_parms in	two places, but	that was 
covering up a separate problem.  We were attempting to set the 
identifier_type_value of a template_parm into the template_parm scope. 
The peeking stopped us doing that, but confused	 poplevel, leaving an 
identifier value lying around.  This fixes the underlying problem in 
do_pushtag -- we only need to set the identifier_type_value directly 
when we're in a template_parm scope (a later pushdecl will push the 
actual	template_decl).	 for non-class non-template-parm bindings 
do_pushdecl already ends up manipulating identifier_type_value correctly.

         PR c++/99116
         gcc/cp/
         * name-lookup.c (do_pushdecl): Don't peek under	template_parm
         bindings here ...
         (set_identifier_type_value_with_scope):	... or here.
         (do_pushtag): Only set_identifier_type_value_with_scope	at
         non-class template parm	scope, and use parent scope.
         gcc/testsuite/
         * g++.dg/lookup/pr99116-1.C: New.
         * g++.dg/lookup/pr99116-2.C: New.
diff mbox series

Patch

diff --git c/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c
index 5aa206d40d4..0b0fb80c1ff 100644
--- c/gcc/cp/name-lookup.c
+++ w/gcc/cp/name-lookup.c
@@ -3691,14 +3691,9 @@  do_pushdecl (tree decl, bool hiding)
 	    if (match == error_mark_node)
 	      ;
 	    else if (TREE_CODE (match) == TYPE_DECL)
-	      {
-		auto *l = level;
-		while (l->kind == sk_template_parms)
-		  l = l->level_chain;
-		gcc_checking_assert (REAL_IDENTIFIER_TYPE_VALUE (name)
-				     == (l->kind == sk_namespace
-					 ? NULL_TREE : TREE_TYPE (match)));
-	      }
+	      gcc_checking_assert (REAL_IDENTIFIER_TYPE_VALUE (name)
+				   == (level->kind == sk_namespace
+				       ? NULL_TREE : TREE_TYPE (match)));
 	    else if (iter.hidden_p () && !hiding)
 	      {
 		/* Unhiding a previously hidden decl.  */
@@ -4756,12 +4751,13 @@  print_binding_stack (void)
 static void
 set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
 {
-  while (b->kind == sk_template_parms)
-    b = b->level_chain;
-
   if (b->kind == sk_namespace)
     /* At namespace scope we should not see an identifier type value.  */
-    gcc_checking_assert (!REAL_IDENTIFIER_TYPE_VALUE (id));
+    gcc_checking_assert (!REAL_IDENTIFIER_TYPE_VALUE (id)
+			 /* We could be pushing a friend underneath a template
+			    parm (ill-formed).  */
+			 || (TEMPLATE_PARM_P
+			     (TYPE_NAME (REAL_IDENTIFIER_TYPE_VALUE (id)))));
   else
     {
       /* Push the current type value, so we can restore it later  */
@@ -8257,10 +8253,8 @@  do_pushtag (tree name, tree type, TAG_how how)
       if (decl == error_mark_node)
 	return decl;
 
-      bool in_class = false;
       if (b->kind == sk_class)
 	{
-	  in_class = true;
 	  if (!TYPE_BEING_DEFINED (current_class_type))
 	    /* Don't push anywhere if the class is complete; a lambda in an
 	       NSDMI is not a member of the class.  */
@@ -8275,7 +8269,12 @@  do_pushtag (tree name, tree type, TAG_how how)
 	    pushdecl_class_level (decl);
 	}
       else if (b->kind == sk_template_parms)
-	in_class = b->level_chain->kind == sk_class;
+	{
+	  /* Do not push the tag here -- we'll want to push the
+	     TEMPLATE_DECL.  */
+	  if (b->level_chain->kind != sk_class)
+	    set_identifier_type_value_with_scope (name, tdef, b->level_chain);
+	}
       else
 	{
 	  decl = do_pushdecl_with_scope
@@ -8293,9 +8292,6 @@  do_pushtag (tree name, tree type, TAG_how how)
 	    }
 	}
 
-      if (!in_class)
-	set_identifier_type_value_with_scope (name, tdef, b);
-
       TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
 
       /* If this is a local class, keep track of it.  We need this
diff --git c/gcc/testsuite/g++.dg/lookup/pr99116-1.C w/gcc/testsuite/g++.dg/lookup/pr99116-1.C
new file mode 100644
index 00000000000..01b483ea915
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/pr99116-1.C
@@ -0,0 +1,25 @@ 
+// PR 99116 sliding hidden friends under template parm scopes
+
+template<int T> struct Z {
+
+  friend struct T; // { dg-error "shadows template parameter" }
+};
+
+struct Y {
+
+  template<typename S> struct A {};
+
+  friend struct S;
+};
+
+struct X
+{
+  struct S2 {};
+  
+  struct In
+  {
+    friend struct S2;
+  };
+};
+
+typedef int S2;
diff --git c/gcc/testsuite/g++.dg/lookup/pr99116-2.C w/gcc/testsuite/g++.dg/lookup/pr99116-2.C
new file mode 100644
index 00000000000..2a4148bade8
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/pr99116-2.C
@@ -0,0 +1,19 @@ 
+// PR 99116, we need to remove the namespace-scope meaning of
+// IDENTIFIER_TYPE_VALUE.
+
+namespace __gnu_cxx 
+{
+template<typename _CharT>
+struct char_traits
+{
+  static void length();
+};
+
+template<typename _T>
+void char_traits<_T>::length ()
+{
+}
+
+}
+       
+struct char_traits;