decl.c (lookup_tag): Remove code no longer needed after name-lookup improvements.
* decl.c (lookup_tag): Remove code no longer needed after name-lookup improvements. * decl2.c (handle_class_head): Make error-recovery more robust. * friend.c (make_friend_class): Reject templated typename types. * lex.c (is_global): A template parameter isn't global. * parse.y (class_head): Robustify. * parse.c: Regenerated. From-SVN: r27117
This commit is contained in:
parent
480e228634
commit
8bcc97de27
@ -1,3 +1,13 @@
|
||||
1999-05-24 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* decl.c (lookup_tag): Remove code no longer needed after
|
||||
name-lookup improvements.
|
||||
* decl2.c (handle_class_head): Make error-recovery more robust.
|
||||
* friend.c (make_friend_class): Reject templated typename types.
|
||||
* lex.c (is_global): A template parameter isn't global.
|
||||
* parse.y (class_head): Robustify.
|
||||
* parse.c: Regenerated.
|
||||
|
||||
1999-05-22 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* pt.c (for_each_template_parm): Walk into TYPENAME_TYPEs,
|
||||
|
@ -5251,59 +5251,6 @@ lookup_tag (form, name, binding_level, thislevel_only)
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (current_class_type && level->level_chain->namespace_p)
|
||||
{
|
||||
/* Try looking in this class's tags before heading into
|
||||
global binding level. */
|
||||
tree context = current_class_type;
|
||||
while (context)
|
||||
{
|
||||
switch (TREE_CODE_CLASS (TREE_CODE (context)))
|
||||
{
|
||||
tree these_tags;
|
||||
case 't':
|
||||
these_tags = CLASSTYPE_TAGS (context);
|
||||
if (ANON_AGGRNAME_P (name))
|
||||
while (these_tags)
|
||||
{
|
||||
if (TYPE_IDENTIFIER (TREE_VALUE (these_tags))
|
||||
== name)
|
||||
return TREE_VALUE (tail);
|
||||
these_tags = TREE_CHAIN (these_tags);
|
||||
}
|
||||
else
|
||||
while (these_tags)
|
||||
{
|
||||
if (TREE_PURPOSE (these_tags) == name)
|
||||
{
|
||||
if (TREE_CODE (TREE_VALUE (these_tags)) != form)
|
||||
{
|
||||
cp_error ("`%#D' redeclared as %C in class scope",
|
||||
TREE_VALUE (tail), form);
|
||||
return NULL_TREE;
|
||||
}
|
||||
return TREE_VALUE (tail);
|
||||
}
|
||||
these_tags = TREE_CHAIN (these_tags);
|
||||
}
|
||||
/* If this type is not yet complete, then don't
|
||||
look at its context. */
|
||||
if (TYPE_SIZE (context) == NULL_TREE)
|
||||
goto no_context;
|
||||
/* Go to next enclosing type, if any. */
|
||||
context = DECL_CONTEXT (TYPE_MAIN_DECL (context));
|
||||
break;
|
||||
case 'd':
|
||||
context = DECL_CONTEXT (context);
|
||||
break;
|
||||
default:
|
||||
my_friendly_abort (10);
|
||||
}
|
||||
continue;
|
||||
no_context:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
@ -5257,7 +5257,10 @@ handle_class_head (aggr, scope, id)
|
||||
else
|
||||
{
|
||||
if (scope)
|
||||
cp_error ("`%T' does not have a nested type named `%D'", scope, id);
|
||||
{
|
||||
cp_error ("`%T' does not have a nested type named `%D'", scope, id);
|
||||
return error_mark_node;
|
||||
}
|
||||
else
|
||||
cp_error ("no file-scope type named `%D'", id);
|
||||
|
||||
|
@ -266,7 +266,7 @@ make_friend_class (type, friend_type)
|
||||
friend_type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (processing_template_decl > template_class_depth (type))
|
||||
/* If the TYPE is a template then it makes sense for it to be
|
||||
friends with itself; this means that each instantiation is
|
||||
@ -281,6 +281,26 @@ make_friend_class (type, friend_type)
|
||||
else
|
||||
is_template_friend = 0;
|
||||
|
||||
if (is_template_friend
|
||||
&& TREE_CODE (friend_type) == TYPENAME_TYPE)
|
||||
{
|
||||
/* [temp.friend]
|
||||
|
||||
A friend of a class or class template can be a function or
|
||||
class template, a specialization of a function template or
|
||||
class template, or an ordinary (nontemplate) function or
|
||||
class.
|
||||
|
||||
But, we're looking at something like:
|
||||
|
||||
template <class T> friend typename S<T>::X;
|
||||
|
||||
which isn't any of these. */
|
||||
cp_error ("typename type `%T' declare `friend'",
|
||||
friend_type);
|
||||
return;
|
||||
}
|
||||
|
||||
GNU_xref_hier (type, friend_type, 0, 0, 1);
|
||||
|
||||
if (is_template_friend)
|
||||
|
@ -2831,6 +2831,12 @@ is_global (d)
|
||||
case TREE_LIST: d = TREE_VALUE (d); continue;
|
||||
default:
|
||||
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629);
|
||||
|
||||
/* A template parameter is not really global, even though it
|
||||
has no enclosing scope. */
|
||||
if (DECL_TEMPLATE_PARM_P (d))
|
||||
return 0;
|
||||
|
||||
d = CP_DECL_CONTEXT (d);
|
||||
return TREE_CODE (d) == NAMESPACE_DECL;
|
||||
}
|
||||
|
762
gcc/cp/parse.c
762
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
@ -2165,10 +2165,12 @@ structsp:
|
||||
}
|
||||
| class_head %prec EMPTY
|
||||
{
|
||||
if ($1.new_type_flag)
|
||||
if ($1.new_type_flag && $1.t != error_mark_node)
|
||||
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
|
||||
$$.new_type_flag = 0;
|
||||
if (TYPE_BINFO ($1.t) == NULL_TREE)
|
||||
if ($1.t == error_mark_node)
|
||||
$$.t = $1.t;
|
||||
else if (TYPE_BINFO ($1.t) == NULL_TREE)
|
||||
{
|
||||
cp_error ("%T is not a class type", $1.t);
|
||||
$$.t = error_mark_node;
|
||||
|
24
gcc/testsuite/g++.old-deja/g++.pt/crash43.C
Normal file
24
gcc/testsuite/g++.old-deja/g++.pt/crash43.C
Normal file
@ -0,0 +1,24 @@
|
||||
// Build don't link:
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
template <int T>
|
||||
struct S {
|
||||
struct X {};
|
||||
struct Y {};
|
||||
|
||||
template <int U>
|
||||
friend struct S<U>::X; // ERROR - typename as friend
|
||||
|
||||
template <int U>
|
||||
friend typename S<U>::Y; // ERROR - typename as friend
|
||||
};
|
||||
|
||||
struct T {
|
||||
template <int T>
|
||||
friend struct S<T>::X; // ERROR - typename as friend
|
||||
};
|
||||
|
||||
struct U {
|
||||
template <int T>
|
||||
friend typename S<T>::X; // ERROR - typename as friend
|
||||
};
|
Loading…
Reference in New Issue
Block a user