Commit 3d7de1fa by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (lang_type): Add documentation.

	* cp-tree.h (lang_type): Add documentation.
	* decl2.c (handle_class_head): Create template declarations here,
	as appropriate.
	* parse.y (class_head): Return whether or not we entered a new
	scope, as well as the type named.
	(named_class_head): Likewise.
	(named_complex_class_head_sans_basetype): Likewise.
	(structsp): Adjust accordingly.  Pop scope when required.
	* parse.c: Regenerated.
	* pt.c (check_default_tmpl_args): Robustify.
	(redeclare_class_template): Likewise.
	(instantiate_class_template): An instantiation of an
	anonymous union is itself an anonymous union.
	* semantics.c (begin_class_definition): Don't create template
	declarations here.

From-SVN: r26475
parent 08967681
1999-04-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_type): Add documentation.
* decl2.c (handle_class_head): Create template declarations here,
as appropriate.
* parse.y (class_head): Return whether or not we entered a new
scope, as well as the type named.
(named_class_head): Likewise.
(named_complex_class_head_sans_basetype): Likewise.
(structsp): Adjust accordingly. Pop scope when required.
* parse.c: Regenerated.
* pt.c (check_default_tmpl_args): Robustify.
(redeclare_class_template): Likewise.
(instantiate_class_template): An instantiation of an
anonymous union is itself an anonymous union.
* semantics.c (begin_class_definition): Don't create template
declarations here.
1999-04-15 Jason Merrill <jason@yorick.cygnus.com> 1999-04-15 Jason Merrill <jason@yorick.cygnus.com>
* parse.y (after_type_declarator_intern): New nonterminal. * parse.y (after_type_declarator_intern): New nonterminal.
...@@ -23,7 +41,7 @@ ...@@ -23,7 +41,7 @@
(pop_nested_class): Likewise. (pop_nested_class): Likewise.
* decl.c (poplevel_class): Declare it here, and make it static. * decl.c (poplevel_class): Declare it here, and make it static.
(poplevel): Handle class scopes. (poplevel): Handle class scopes.
(pop_level_class): Don't take an rgument. Simplify. (poplevel_class): Don't take an rgument. Simplify.
(pop_everything): Pass no arguments to pop_nested_class. (pop_everything): Pass no arguments to pop_nested_class.
(cp_finish_decl): Pass no arguments to popclass. (cp_finish_decl): Pass no arguments to popclass.
(grokdeclarator): Pass no arguments to pop_nested_class. (grokdeclarator): Pass no arguments to pop_nested_class.
......
...@@ -737,6 +737,9 @@ struct lang_type ...@@ -737,6 +737,9 @@ struct lang_type
unsigned is_partial_instantiation : 1; unsigned is_partial_instantiation : 1;
unsigned has_mutable : 1; unsigned has_mutable : 1;
unsigned com_interface : 1; unsigned com_interface : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template.
If so, make sure to copy it in instantiate_class_template! */
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
......
...@@ -5040,23 +5040,41 @@ mark_used (decl) ...@@ -5040,23 +5040,41 @@ mark_used (decl)
instantiate_decl (decl); instantiate_decl (decl);
} }
/* Helper function for named_class_head_sans_basetype nonterminal. */ /* Helper function for named_class_head_sans_basetype nonterminal. We
have just seen something of the form `AGGR SCOPE::ID'. Return a
TYPE_DECL for the type declared by ID in SCOPE. */
tree tree
handle_class_head (aggr, scope, id) handle_class_head (aggr, scope, id)
tree aggr, scope, id; tree aggr, scope, id;
{ {
if (TREE_CODE (id) == TYPE_DECL) tree decl;
return id;
if (DECL_CLASS_TEMPLATE_P (id))
return DECL_TEMPLATE_RESULT (id);
if (TREE_CODE (id) == TYPE_DECL)
decl = id;
else if (DECL_CLASS_TEMPLATE_P (id))
decl = DECL_TEMPLATE_RESULT (id);
else
{
if (scope) 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);
else else
cp_error ("no file-scope type named `%D'", id); cp_error ("no file-scope type named `%D'", id);
id = xref_tag decl = TYPE_MAIN_DECL (xref_tag (aggr, make_anon_name (), 1));
(aggr, make_anon_name (), 1); }
return TYPE_MAIN_DECL (id);
/* This syntax is only allowed when we're defining a type, so we
enter the SCOPE. */
push_scope (CP_DECL_CONTEXT (decl));
/* If we see something like:
template <typename T> struct S::I ....
we must create a TEMPLATE_DECL for the nested type. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
decl = push_template_decl (decl);
return decl;
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -239,10 +239,11 @@ empty_parms () ...@@ -239,10 +239,11 @@ empty_parms ()
%type <ttype> component_constructor_declarator %type <ttype> component_constructor_declarator
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator %type <ttype> fn.def2 return_id fn.defpen constructor_declarator
%type <itype> ctor_initializer_opt function_try_block %type <itype> ctor_initializer_opt function_try_block
%type <ttype> named_class_head named_class_head_sans_basetype %type <ttype> named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype %type <ftype> class_head named_class_head
%type <ftype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head %type <ttype> unnamed_class_head
%type <ttype> class_head base_class_list %type <ttype> base_class_list
%type <ttype> base_class_access_list %type <ttype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1 %type <ttype> base_class maybe_base_class_list base_class.1
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
...@@ -2140,7 +2141,7 @@ structsp: ...@@ -2140,7 +2141,7 @@ structsp:
cp_pedwarn ("using `typename' outside of template"); } cp_pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */ /* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head '{' | class_head '{'
{ $<ttype>1 = begin_class_definition ($<ttype>1); } { $1.t = begin_class_definition ($1.t); }
opt.component_decl_list '}' maybe_attribute opt.component_decl_list '}' maybe_attribute
{ {
int semi; int semi;
...@@ -2149,7 +2150,7 @@ structsp: ...@@ -2149,7 +2150,7 @@ structsp:
yychar = YYLEX; yychar = YYLEX;
semi = yychar == ';'; semi = yychar == ';';
$<ttype>$ = finish_class_definition ($1, $6, semi); $<ttype>$ = finish_class_definition ($1.t, $6, semi);
} }
pending_defargs pending_defargs
{ {
...@@ -2158,20 +2159,24 @@ structsp: ...@@ -2158,20 +2159,24 @@ structsp:
pending_inlines pending_inlines
{ {
finish_inline_definitions (); finish_inline_definitions ();
if ($1.new_type_flag)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($<ttype>7)));
$$.t = $<ttype>7; $$.t = $<ttype>7;
$$.new_type_flag = 1; $$.new_type_flag = 1;
} }
| class_head %prec EMPTY | class_head %prec EMPTY
{ {
if ($1.new_type_flag)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
$$.new_type_flag = 0; $$.new_type_flag = 0;
if (TYPE_BINFO ($1) == NULL_TREE) if (TYPE_BINFO ($1.t) == NULL_TREE)
{ {
cp_error ("%T is not a class type", $1); cp_error ("%T is not a class type", $1.t);
$$.t = error_mark_node; $$.t = error_mark_node;
} }
else else
{ {
$$.t = $1; $$.t = $1.t;
/* struct B: public A; is not accepted by the WP grammar. */ /* struct B: public A; is not accepted by the WP grammar. */
if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t) if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
&& ! TYPE_BEING_DEFINED ($$.t)) && ! TYPE_BEING_DEFINED ($$.t))
...@@ -2228,63 +2233,77 @@ named_complex_class_head_sans_basetype: ...@@ -2228,63 +2233,77 @@ named_complex_class_head_sans_basetype:
aggr nested_name_specifier identifier aggr nested_name_specifier identifier
{ {
current_aggr = $1; current_aggr = $1;
$$ = handle_class_head ($1, $2, $3); $$.t = handle_class_head ($1, $2, $3);
$$.new_type_flag = 1;
} }
| aggr global_scope nested_name_specifier identifier | aggr global_scope nested_name_specifier identifier
{ {
current_aggr = $1; current_aggr = $1;
$$ = handle_class_head ($1, $3, $4); $$.t = handle_class_head ($1, $3, $4);
$$.new_type_flag = 1;
} }
| aggr global_scope identifier | aggr global_scope identifier
{ {
current_aggr = $1; current_aggr = $1;
$$ = handle_class_head ($1, NULL_TREE, $3); $$.t = handle_class_head ($1, NULL_TREE, $3);
$$.new_type_flag = 1;
} }
| aggr apparent_template_type | aggr apparent_template_type
{ current_aggr = $$; $$ = $2; } {
current_aggr = $1;
$$.t = $2;
$$.new_type_flag = 0;
}
| aggr nested_name_specifier apparent_template_type | aggr nested_name_specifier apparent_template_type
{ current_aggr = $$; $$ = $3; } {
current_aggr = $1;
$$.t = $3;
if (CP_DECL_CONTEXT ($$.t))
push_scope (CP_DECL_CONTEXT ($$.t));
$$.new_type_flag = 1;
}
; ;
named_class_head: named_class_head:
named_class_head_sans_basetype %prec EMPTY named_class_head_sans_basetype %prec EMPTY
{ $$ = xref_tag (current_aggr, $1, 1); } {
$$.t = xref_tag (current_aggr, $1, 1);
$$.new_type_flag = 0;
}
| named_class_head_sans_basetype_defn | named_class_head_sans_basetype_defn
{ $<ttype>$ = xref_tag (current_aggr, $1, 0); } { $<ttype>$ = xref_tag (current_aggr, $1, 0); }
/* Class name is unqualified, so we look for base classes /* Class name is unqualified, so we look for base classes
in the current scope. */ in the current scope. */
maybe_base_class_list %prec EMPTY maybe_base_class_list %prec EMPTY
{ {
$$ = $<ttype>2; $$.t = $<ttype>2;
$$.new_type_flag = 0;
if ($3) if ($3)
xref_basetypes (current_aggr, $1, $<ttype>2, $3); xref_basetypes (current_aggr, $1, $<ttype>2, $3);
} }
| named_complex_class_head_sans_basetype | named_complex_class_head_sans_basetype
{
if ($1 != error_mark_node)
push_scope (CP_DECL_CONTEXT ($1));
}
maybe_base_class_list maybe_base_class_list
{ {
if ($1 != error_mark_node) if ($1.t != error_mark_node)
{ {
pop_scope (CP_DECL_CONTEXT ($1)); $$.t = TREE_TYPE ($1.t);
$$ = TREE_TYPE ($1); $$.new_type_flag = $1.new_type_flag;
if (current_aggr == union_type_node if (current_aggr == union_type_node
&& TREE_CODE ($$) != UNION_TYPE) && TREE_CODE ($$.t) != UNION_TYPE)
cp_pedwarn ("`union' tag used in declaring `%#T'", $$); cp_pedwarn ("`union' tag used in declaring `%#T'",
else if (TREE_CODE ($$) == UNION_TYPE $$.t);
else if (TREE_CODE ($$.t) == UNION_TYPE
&& current_aggr != union_type_node) && current_aggr != union_type_node)
cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$); cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
else if (TREE_CODE ($$) == RECORD_TYPE) else if (TREE_CODE ($$.t) == RECORD_TYPE)
/* We might be specializing a template with a different /* We might be specializing a template with a different
class-key; deal. */ class-key; deal. */
CLASSTYPE_DECLARED_CLASS ($$) = (current_aggr CLASSTYPE_DECLARED_CLASS ($$.t)
== class_type_node); = (current_aggr == class_type_node);
if ($3) if ($2)
{ {
maybe_process_partial_specialization ($$); maybe_process_partial_specialization ($$.t);
xref_basetypes (current_aggr, $1, $$, $3); xref_basetypes (current_aggr, $1.t, $$.t, $2);
} }
} }
} }
...@@ -2296,8 +2315,16 @@ unnamed_class_head: ...@@ -2296,8 +2315,16 @@ unnamed_class_head:
yyungetc ('{', 1); } yyungetc ('{', 1); }
; ;
/* The tree output of this nonterminal a declarationf or the type
named. If NEW_TYPE_FLAG is set, then the name used in this
class-head was explicitly qualified, e.g.: `struct X::Y'. We have
already called push_scope for X. */
class_head: class_head:
unnamed_class_head unnamed_class_head
{
$$.t = $1;
$$.new_type_flag = 0;
}
| named_class_head | named_class_head
; ;
......
...@@ -2170,6 +2170,7 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial) ...@@ -2170,6 +2170,7 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
if (current_class_type if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type) && !TYPE_BEING_DEFINED (current_class_type)
&& DECL_REAL_CONTEXT (decl) == current_class_type && DECL_REAL_CONTEXT (decl) == current_class_type
&& DECL_LANG_SPECIFIC (decl)
&& DECL_DEFINED_IN_CLASS_P (decl)) && DECL_DEFINED_IN_CLASS_P (decl))
/* We already checked these parameters when the template was /* We already checked these parameters when the template was
declared, so there's no need to do it again now. This is an declared, so there's no need to do it again now. This is an
...@@ -2495,10 +2496,17 @@ redeclare_class_template (type, parms) ...@@ -2495,10 +2496,17 @@ redeclare_class_template (type, parms)
tree type; tree type;
tree parms; tree parms;
{ {
tree tmpl = CLASSTYPE_TI_TEMPLATE (type); tree tmpl;
tree tmpl_parms; tree tmpl_parms;
int i; int i;
if (!TYPE_TEMPLATE_INFO (type))
{
cp_error ("`%T' is not a template type", type);
return;
}
tmpl = TYPE_TI_TEMPLATE (type);
if (!PRIMARY_TEMPLATE_P (tmpl)) if (!PRIMARY_TEMPLATE_P (tmpl))
/* The type is nested in some template class. Nothing to worry /* The type is nested in some template class. Nothing to worry
about here; there are no new template parameters for the nested about here; there are no new template parameters for the nested
...@@ -4816,6 +4824,8 @@ instantiate_class_template (type) ...@@ -4816,6 +4824,8 @@ instantiate_class_template (type)
TYPE_PACKED (type) = TYPE_PACKED (pattern); TYPE_PACKED (type) = TYPE_PACKED (pattern);
TYPE_ALIGN (type) = TYPE_ALIGN (pattern); TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */ TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
if (ANON_UNION_TYPE_P (pattern))
SET_ANON_UNION_TYPE_P (type);
/* We must copy the arguments to the permanent obstack since /* We must copy the arguments to the permanent obstack since
during the tsubst'ing below they may wind up in the during the tsubst'ing below they may wind up in the
......
...@@ -1290,11 +1290,6 @@ begin_class_definition (t) ...@@ -1290,11 +1290,6 @@ begin_class_definition (t)
pushtag (TYPE_IDENTIFIER (t), t, 0); pushtag (TYPE_IDENTIFIER (t), t, 0);
} }
maybe_process_partial_specialization (t); maybe_process_partial_specialization (t);
if (processing_template_decl
&& ! CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
&& TYPE_CONTEXT (t) && TYPE_P (TYPE_CONTEXT (t))
&& ! current_class_type)
push_template_decl (TYPE_STUB_DECL (t));
pushclass (t, 1); pushclass (t, 1);
TYPE_BEING_DEFINED (t) = 1; TYPE_BEING_DEFINED (t) = 1;
/* Reset the interface data, at the earliest possible /* Reset the interface data, at the earliest possible
......
// Origin: Mark Mitchell <mark@codesourcery.com>
int main()
{
typedef double I;
struct S1 {
typedef char I;
struct S2;
};
struct S1::S2 {
typedef I J;
};
return !(sizeof (S1::S2::J) == 1);
}
// Build don't link:
// Origin: David Mazieres <dm@amsterdam.lcs.mit.edu>
template<class T> struct vector_base {
typedef T elm_t;
protected:
union {
double alignment_hack;
char defbuf_space[2 * sizeof (elm_t)];
};
elm_t *def_basep () { return reinterpret_cast<elm_t *> (defbuf_space); }
};
template<class T> struct vector : public vector_base<T> {
vector () { def_basep (); }
};
vector<int> iv;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment