From: Jason Merrill Date: Wed, 27 Jun 2018 17:29:51 +0000 (-0400) Subject: Avoid crash on friend in nested class template. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8945521a50a7dd26ffebdee20a82e323141dfd8b;p=gcc.git Avoid crash on friend in nested class template. * name-lookup.c (do_pushtag): If we skip a class level, also skip its template level. From-SVN: r262188 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 90d1545d734..05383b6003a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2018-06-27 Jason Merrill + + * name-lookup.c (do_pushtag): If we skip a class level, also skip + its template level. + 2018-06-26 Jason Merrill PR c++/86320 - memory-hog with std::array of pair diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index a30c37428ad..e0500d83071 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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 index 00000000000..f8c95f844b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend66.C @@ -0,0 +1,9 @@ +template +struct A +{ + template + struct B + { + friend struct C; + }; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C index 025b0b1ef54..451ef1afaf8 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C +++ b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C @@ -15,9 +15,11 @@ using namespace std; const int ArraySize = 12; +template class Array_RC; + template -class Array { // { dg-error "" } .struct Array_RC redecl.* -friend class Array_RC; +class Array { + friend class Array_RC; public: Array(const Type *ar, int sz) { init(ar,sz); } virtual ~Array() { delete [] ia; } @@ -76,8 +78,8 @@ Array_RC::Array_RC(const Type *ar, int sz) : Array(ar, sz) {} template Type &Array_RC::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 ----------------------