(current_aggr): Define.
* decl.c (grokdeclarator): Make sure a friend class is an
elaborated type specifier.
* parse.y (current_aggr): Remove static definition.
(cp_parse_init): Adjust.
(structsp): Clear and restore current_aggr.
(component_decl_list): Clear current_aggr.
* error.c (dump_type, case TYPENAME_TYPE): Don't emit the
aggregate tag on the typename's context.
* pt.c (tsubst_friend_class): Return NULL, if parms becomes NULL.
(instantiate_class_template): Ignore NULL friend types.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35755
138bc75d-0d04-0410-961f-
82ee72b054a4
+2000-08-17 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (CPTR_AGGR_TAG): New global tree node.
+ (current_aggr): Define.
+ * decl.c (grokdeclarator): Make sure a friend class is an
+ elaborated type specifier.
+ * parse.y (current_aggr): Remove static definition.
+ (cp_parse_init): Adjust.
+ (structsp): Clear and restore current_aggr.
+ (component_decl_list): Clear current_aggr.
+
+ * error.c (dump_type, case TYPENAME_TYPE): Don't emit the
+ aggregate tag on the typename's context.
+
+ * pt.c (tsubst_friend_class): Return NULL, if parms becomes NULL.
+ (instantiate_class_template): Ignore NULL friend types.
+
2000-08-14 Nathan Sidwell <nathan@codesourcery.com>
* cvt.c (warn_ref_binding): New static function, broken out of ...
CPTI_TINFO_VAR_ID,
CPTI_ABORT_FNDECL,
CPTI_GLOBAL_DELETE_FNDECL,
+ CPTI_AGGR_TAG,
CPTI_ACCESS_DEFAULT,
CPTI_ACCESS_PUBLIC,
#define tinfo_var_id cp_global_trees[CPTI_TINFO_VAR_ID]
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
+#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
/* Define the sets of attributes that member functions and baseclasses
can have. These are sensible combinations of {public,private,protected}
cp_error ("`inline' specified for friend class declaration");
inlinep = 0;
}
+ if (!current_aggr && TREE_CODE (type) != TYPENAME_TYPE)
+ {
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ cp_error ("template parameters cannot be friends");
+ else
+ cp_error ("friend declaration requires `%#T'", type);
+ }
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
}
case TYPENAME_TYPE:
OB_PUTS ("typename ");
- dump_type (TYPE_CONTEXT (t), flags);
+ dump_type (TYPE_CONTEXT (t), flags & ~TS_AGGR_TAGS);
OB_PUTS ("::");
dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
break;
a declspec list have been updated. */
static tree prefix_attributes;
-/* When defining an aggregate, this is the kind of the most recent one
- being defined. (For example, this might be class_type_node.) */
-static tree current_aggr;
-
/* When defining an enumeration, this is the type of the enumeration. */
static tree current_enum_type;
{
ggc_add_tree_root (¤t_declspecs, 1);
ggc_add_tree_root (&prefix_attributes, 1);
- ggc_add_tree_root (¤t_aggr, 1);
ggc_add_tree_root (¤t_enum_type, 1);
}
%}
cp_pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head '{'
- { $1.t = begin_class_definition ($1.t); }
+ { $1.t = begin_class_definition ($1.t);
+ current_aggr = NULL_TREE; }
opt.component_decl_list '}' maybe_attribute
{
int semi;
+ tree t;
if (yychar == YYEMPTY)
yychar = YYLEX;
semi = yychar == ';';
- $<ttype>$ = finish_class_definition ($1.t, $6, semi,
- $1.new_type_flag);
+ t = finish_class_definition ($1.t, $6, semi,
+ $1.new_type_flag);
+ $<ttype>$ = t;
+
+ /* restore current_aggr */
+ current_aggr = TREE_CODE (t) != RECORD_TYPE
+ ? union_type_node
+ : CLASSTYPE_DECLARED_CLASS (t)
+ ? class_type_node : record_type_node;
}
pending_defargs
{
component_decl
{
finish_member_declaration ($1);
+ current_aggr = NULL_TREE;
}
| component_decl_list component_decl
{
finish_member_declaration ($2);
+ current_aggr = NULL_TREE;
}
;
/* FRIEND_TMPL is a friend TEMPLATE_DECL. ARGS is the vector of
template arguments, as for tsubst.
- Returns an appropriate tsbust'd friend type. */
+ Returns an appropriate tsbust'd friend type or error_mark_node on
+ failure. */
static tree
tsubst_friend_class (friend_tmpl, args)
tree parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
args, /*complain=*/1);
+ if (!parms)
+ return error_mark_node;
redeclare_class_template (TREE_TYPE (tmpl), parms);
friend_type = TREE_TYPE (tmpl);
}
information. */
++processing_template_decl;
- make_friend_class (type, new_friend_type);
+ if (new_friend_type != error_mark_node)
+ make_friend_class (type, new_friend_type);
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl;