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
This commit is contained in:
parent
25846b5089
commit
8945521a50
4 changed files with 44 additions and 18 deletions
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
9
gcc/testsuite/g++.dg/template/friend66.C
Normal file
9
gcc/testsuite/g++.dg/template/friend66.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
template <class T>
|
||||
struct A
|
||||
{
|
||||
template <class U>
|
||||
struct B
|
||||
{
|
||||
friend struct C;
|
||||
};
|
||||
};
|
|
@ -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 ----------------------
|
||||
|
|
Loading…
Add table
Reference in a new issue