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:
Mark Mitchell 1999-05-24 00:47:01 +00:00 committed by Mark Mitchell
parent 480e228634
commit 8bcc97de27
8 changed files with 451 additions and 437 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

View 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
};