Avoid crash on friend in nested class template.
authorJason Merrill <jason@redhat.com>
Wed, 27 Jun 2018 17:29:51 +0000 (13:29 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 27 Jun 2018 17:29:51 +0000 (13:29 -0400)
* name-lookup.c (do_pushtag): If we skip a class level, also skip
its template level.

From-SVN: r262188

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/template/friend66.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.law/visibility13.C

index 90d1545d7344f839ab406fb4e52ed02eb68b884e..05383b6003abf4a998959d4f0f4a5954dcc50a46 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-27  Jason Merrill  <jason@redhat.com>
+
+       * name-lookup.c (do_pushtag): If we skip a class level, also skip
+       its template level.
+
 2018-06-26  Jason Merrill  <jason@redhat.com>
 
        PR c++/86320 - memory-hog with std::array of pair
index a30c37428adb7ca637155d230a1f552128a44e40..e0500d83071113dd98573e6c64e2bbeb267821ec 100644 (file)
@@ -6509,20 +6509,30 @@ do_pushtag (tree name, tree type, tag_scope scope)
   tree decl;
 
   cp_binding_level *b = current_binding_level;
-  while (/* Cleanup scopes are not scopes from the point of view of
-           the language.  */
-        b->kind == sk_cleanup
-        /* Neither are function parameter scopes.  */
-        || b->kind == sk_function_parms
-        /* Neither are the scopes used to hold template parameters
-           for an explicit specialization.  For an ordinary template
-           declaration, these scopes are not scopes from the point of
-           view of the language.  */
-        || (b->kind == sk_template_parms
-            && (b->explicit_spec_p || scope == ts_global))
-        || (b->kind == sk_class
-            && scope != ts_current))
-    b = b->level_chain;
+  while (true)
+    {
+      if (/* Cleanup scopes are not scopes from the point of view of
+            the language.  */
+         b->kind == sk_cleanup
+         /* Neither are function parameter scopes.  */
+         || b->kind == sk_function_parms
+         /* Neither are the scopes used to hold template parameters
+            for an explicit specialization.  For an ordinary template
+            declaration, these scopes are not scopes from the point of
+            view of the language.  */
+         || (b->kind == sk_template_parms
+             && (b->explicit_spec_p || scope == ts_global)))
+       b = b->level_chain;
+      else if (b->kind == sk_class
+              && scope != ts_current)
+       {
+         b = b->level_chain;
+         if (b->kind == sk_template_parms)
+           b = b->level_chain;
+       }
+      else
+       break;
+    }
 
   gcc_assert (identifier_p (name));
 
diff --git a/gcc/testsuite/g++.dg/template/friend66.C b/gcc/testsuite/g++.dg/template/friend66.C
new file mode 100644 (file)
index 0000000..f8c95f8
--- /dev/null
@@ -0,0 +1,9 @@
+template <class T>
+struct A
+{
+  template <class U>
+  struct B
+  {
+    friend struct C;
+  };
+};
index 025b0b1ef54035a8a814a0dc27fc6c95fe44fa46..451ef1afaf8e2b31fcdba92811ab7829d24b8ef6 100644 (file)
@@ -15,9 +15,11 @@ using namespace std;
 
 const int ArraySize = 12;
 
+template <class> class Array_RC;
+
 template <class Type>
-class Array { // { dg-error "" } .struct Array_RC redecl.*
-friend class Array_RC;
+class Array {
+  friend class Array_RC<Type>;
 public:
     Array(const Type *ar, int sz) { init(ar,sz); }
     virtual ~Array() { delete [] ia; }
@@ -76,8 +78,8 @@ Array_RC<Type>::Array_RC(const Type *ar, int sz) : Array<Type>(ar, sz) {}
 
 template <class Type>
 Type &Array_RC<Type>::operator[](int ix) {
-    assert(ix >= 0 && ix < size);// { dg-error "" } member .size.*
-    return ia[ix];// { dg-error "" } member .ia.*
+    assert(ix >= 0 && ix < this->size);
+    return this->ia[ix];
 }
 
 //    -------------------   Test routine   ----------------------