summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog33
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/gxx.gperf4
-rw-r--r--gcc/cp/hash.h7
-rw-r--r--gcc/cp/parse.y227
-rw-r--r--gcc/cp/semantics.c286
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/new.C57
7 files changed, 417 insertions, 208 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 315feea3bd5..95fa40af7a9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,36 @@
+Mon May 11 00:03:34 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * cp-tree.h (finish_unary_op_expr): New function.
+ (finish_id_expr): Likewise.
+ (begin_new_placement): Likewise.
+ (finish_new_placement): Likewise.
+ (finish_declarator): Likewise.
+ (finish_translation_unit): Likewise.
+ (finish_parmlist): Likewise.
+ (begin_class_definition): Likewise.
+ (finish_class_definition): Likewise.
+ (finish_default_args): Likewise.
+ (finish_inline_definitions): Likewise.
+ * parse.y (GCC_ASM_KEYWORD): Remove.
+ (TYPENAME_ELLIPSIS): Likewise.
+ * parse.c: Regenerated.
+ Use new functions in semantics.c in the actions for many rules.
+ * gxx.gperf (GCC_ASM_KEYWORD): Just use ASM_KEYWORD.
+ * hash.h: Regenerated.
+ * semantics.c (finish_expr_stmt): Allow NULL expr.
+ (finish_unary_op_expr): New function, containing
+ code previously in parse.y.
+ (finish_id_expr): Likewise.
+ (begin_new_placement): Likewise.
+ (finish_new_placement): Likewise.
+ (finish_declarator): Likewise.
+ (finish_translation_unit): Likewise.
+ (finish_parmlist): Likewise.
+ (begin_class_definition): Likewise.
+ (finish_class_definition): Likewise.
+ (finish_default_args): Likewise.
+ (finish_inline_definitions): Likewise.
+
Sun May 10 23:43:13 1998 Mark Mitchell <mmitchell@usa.net>
* typeck.c (build_c_cast): Don't decay arrays and functions to
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 662ba152f96..f044553d9ff 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2634,10 +2634,21 @@ extern tree finish_qualified_object_call_expr PROTO((tree, tree, tree));
extern tree finish_pseudo_destructor_call_expr PROTO((tree, tree, tree));
extern tree finish_globally_qualified_member_call_expr PROTO ((tree, tree));
extern tree finish_label_address_expr PROTO((tree));
+extern tree finish_unary_op_expr PROTO((enum tree_code, tree));
+extern tree finish_id_expr PROTO((tree));
+extern int begin_new_placement PROTO((void));
+extern tree finish_new_placement PROTO((tree, int));
extern int begin_function_definition PROTO((tree, tree));
extern tree begin_constructor_declarator PROTO((tree, tree));
+extern tree finish_declarator PROTO((tree, tree, tree, tree, int));
+extern void finish_translation_unit PROTO((void));
extern tree finish_template_type_parm PROTO((tree, tree));
extern tree finish_template_template_parm PROTO((tree, tree));
+extern tree finish_parmlist PROTO((tree, int));
+extern tree begin_class_definition PROTO((tree));
+extern tree finish_class_definition PROTO((tree, tree, tree, int));
+extern void finish_default_args PROTO((void));
+extern void begin_inline_definitions PROTO((void));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));
diff --git a/gcc/cp/gxx.gperf b/gcc/cp/gxx.gperf
index d9cad4a6255..71538567c13 100644
--- a/gcc/cp/gxx.gperf
+++ b/gcc/cp/gxx.gperf
@@ -5,8 +5,8 @@ struct resword { char *name; short token; enum rid rid;};
%%
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
-__asm, GCC_ASM_KEYWORD, NORID
-__asm__, GCC_ASM_KEYWORD, NORID
+__asm, ASM_KEYWORD, NORID
+__asm__, ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID
__complex, TYPESPEC, RID_COMPLEX
diff --git a/gcc/cp/hash.h b/gcc/cp/hash.h
index 720890fd4c8..1e31a354724 100644
--- a/gcc/cp/hash.h
+++ b/gcc/cp/hash.h
@@ -1,5 +1,6 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gxx.gperf */
+/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ ../../../gcc/cp/gxx.gperf */
+/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
struct resword { char *name; short token; enum rid rid;};
#define TOTAL_KEYWORDS 103
@@ -72,7 +73,7 @@ is_reserved_word (str, len)
{"",},
{"true", CXX_TRUE, NORID,},
{"",},
- {"__asm__", GCC_ASM_KEYWORD, NORID},
+ {"__asm__", ASM_KEYWORD, NORID},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"this", THIS, NORID,},
{"",},
@@ -104,7 +105,7 @@ is_reserved_word (str, len)
{"short", TYPESPEC, RID_SHORT,},
{"__imag__", IMAGPART, NORID},
{"delete", DELETE, NORID,},
- {"__asm", GCC_ASM_KEYWORD, NORID},
+ {"__asm", ASM_KEYWORD, NORID},
{"xor", '^', NORID,},
{"not_eq", EQCOMPARE, NORID,},
{"xor_eq", ASSIGN, NORID,},
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 074f640f0ee..d9df9b8919f 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -129,7 +129,7 @@ empty_parms ()
/* the reserved words */
/* SCO include files test "ASM", so use something else. */
%token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
-%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD GCC_ASM_KEYWORD TYPEOF ALIGNOF
+%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token SIGOF
%token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART
@@ -228,7 +228,7 @@ empty_parms ()
%type <ftype> structsp typespecqual_reserved parm named_parm full_parm
/* C++ extensions */
-%token <ttype> TYPENAME_ELLIPSIS PTYPENAME
+%token <ttype> PTYPENAME
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
%type <ttype> component_constructor_declarator
@@ -328,15 +328,7 @@ parse_decl(declarator, specs_attrs, attributes, initialized, decl)
program:
/* empty */
| extdefs
- {
- /* In case there were missing closebraces,
- get us back to the global binding level. */
- while (! toplevel_bindings_p ())
- poplevel (0, 0, 0);
- while (current_namespace != global_namespace)
- pop_namespace ();
- finish_file ();
- }
+ { finish_translation_unit (); }
;
/* the reason for the strange actions in this rule
@@ -373,7 +365,6 @@ extension:
asm_keyword:
ASM_KEYWORD
- | GCC_ASM_KEYWORD
;
lang_extdef:
@@ -1010,11 +1001,7 @@ unary_expr:
| '~' cast_expr
{ $$ = build_x_unary_op (BIT_NOT_EXPR, $2); }
| unop cast_expr %prec UNARY
- { $$ = build_x_unary_op ($1, $2);
- if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST)
- TREE_NEGATED_INT ($$) = 1;
- overflow_warning ($$);
- }
+ { $$ = finish_unary_op_expr ($1, $2); }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
{ if (pedantic)
@@ -1075,13 +1062,15 @@ unary_expr:
;
new_placement:
- '(' nonnull_exprlist ')'
- { $$ = $2; }
- | '{' nonnull_exprlist '}'
- {
- $$ = $2;
- pedwarn ("old style placement syntax, use () instead");
- }
+ '('
+ { $<itype>$ = begin_new_placement (); }
+ nonnull_exprlist ')'
+ { $$ = finish_new_placement ($3, $<itype>1); }
+ | '{'
+ { cp_pedwarn ("old style placement syntax, use () instead");
+ $<itype>$ = begin_new_placement (); }
+ nonnull_exprlist '}'
+ { $$ = finish_new_placement ($3, $<itype>1); }
;
new_initializer:
@@ -1112,13 +1101,11 @@ new_initializer:
/* This is necessary to postpone reduction of `int ((int)(int)(int))'. */
regcast_or_absdcl:
'(' type_id ')' %prec EMPTY
- { $2.t = tree_cons (NULL_TREE, $2.t, void_list_node);
- TREE_PARMLIST ($2.t) = 1;
+ { $2.t = finish_parmlist (build_tree_list (NULL_TREE, $2.t), 0);
$$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $2); }
| regcast_or_absdcl '(' type_id ')' %prec EMPTY
- { $3.t = tree_cons (NULL_TREE, $3.t, void_list_node);
- TREE_PARMLIST ($3.t) = 1;
+ { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
$$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $3); }
;
@@ -1272,10 +1259,10 @@ direct_notype_declarator:
primary:
notype_unqualified_id
{
- if (TREE_CODE ($$) == BIT_NOT_EXPR)
- $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
- else if (TREE_CODE ($$) != TEMPLATE_ID_EXPR)
- $$ = do_identifier ($$, 1);
+ if (TREE_CODE ($1) == BIT_NOT_EXPR)
+ $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0));
+ else
+ $$ = finish_id_expr ($1);
}
| CONSTANT
| boolean.literal
@@ -2005,54 +1992,21 @@ structsp:
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly
opt.component_decl_list '}' maybe_attribute
- {
+ {
int semi;
- $<ttype>$ = $1;
-#if 0
- /* Need to rework class nesting in the
- presence of nested classes, etc. */
- shadow_tag (CLASSTYPE_AS_LIST ($1)); */
-#endif
if (yychar == YYEMPTY)
yychar = YYLEX;
semi = yychar == ';';
- /* finish_struct nukes this anyway; if
- finish_exception does too, then it can go. */
- if (semi)
- note_got_semicolon ($1);
-
- if (TREE_CODE ($1) == ENUMERAL_TYPE)
- ;
- else
- {
- $<ttype>$ = finish_struct ($1, $3, $5, semi);
- if (semi) note_got_semicolon ($<ttype>$);
- }
-
- pop_obstacks ();
- if (! semi)
- check_for_missing_semicolon ($1);
- if (current_scope () == current_function_decl)
- do_pending_defargs ();
+ $<ttype>$ = finish_class_definition ($1, $3, $5, semi);
}
pending_defargs
- {
- if (pending_inlines
- && current_scope () == current_function_decl)
- do_pending_inlines ();
- }
+ { finish_default_args (); }
pending_inlines
- {
- $$.t = $<ttype>6;
+ { $$.t = $<ttype>6;
$$.new_type_flag = 1;
- if (current_class_type == NULL_TREE)
- clear_inline_text_obstack ();
-
- /* Undo the begin_tree in left_curly. */
- end_tree ();
- }
+ begin_inline_definitions (); }
| class_head %prec EMPTY
{
$$.new_type_flag = 0;
@@ -2334,92 +2288,7 @@ base_class_access_list:
left_curly:
'{'
- { tree t = $<ttype>0;
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
- if (t == error_mark_node
- || ! IS_AGGR_TYPE (t))
- {
- t = $<ttype>0 = make_lang_type (RECORD_TYPE);
- pushtag (make_anon_name (), t, 0);
- }
- if (TYPE_SIZE (t))
- duplicate_tag_error (t);
- if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
- {
- t = make_lang_type (TREE_CODE (t));
- pushtag (TYPE_IDENTIFIER ($<ttype>0), t, 0);
- $<ttype>0 = t;
- }
- if (processing_template_decl && TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
- && ! current_class_type)
- push_template_decl (TYPE_STUB_DECL (t));
- pushclass (t, 0);
- TYPE_BEING_DEFINED (t) = 1;
- if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
- {
- if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
- && TYPE_SIZE (t) == NULL_TREE)
- {
- SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
- if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (t));
- }
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
- cp_error ("specialization after instantiation of `%T'", t);
- }
- /* Reset the interface data, at the earliest possible
- moment, as it might have been set via a class foo;
- before. */
- /* Don't change signatures. */
- if (! IS_SIGNATURE (t))
- {
- extern tree pending_vtables;
- int needs_writing;
- tree name = TYPE_IDENTIFIER (t);
-
- if (! ANON_AGGRNAME_P (name))
- {
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X
- (t, interface_unknown);
- }
-
- /* Record how to set the access of this class's
- virtual functions. If write_virtuals == 2 or 3, then
- inline virtuals are ``extern inline''. */
- switch (write_virtuals)
- {
- case 0:
- case 1:
- needs_writing = 1;
- break;
- case 2:
- needs_writing = !! value_member (name, pending_vtables);
- break;
- case 3:
- needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
- && CLASSTYPE_INTERFACE_KNOWN (t);
- break;
- default:
- needs_writing = 0;
- }
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
- }
-#if 0
- t = TYPE_IDENTIFIER ($<ttype>0);
- if (t && IDENTIFIER_TEMPLATE (t))
- overload_template_name (t, 1);
-#endif
- reset_specialization();
-
- /* In case this is a local class within a template
- function, we save the current tree structure so
- that we can get it back later. */
- begin_tree ();
- }
+ { $<ttype>0 = begin_class_definition ($<ttype>0); }
;
self_reference:
@@ -3497,8 +3366,7 @@ parmlist:
}
| complex_parmlist
| type_id
- { $$ = tree_cons (NULL_TREE, $1.t, void_list_node);
- TREE_PARMLIST ($$) = 1;
+ { $$ = finish_parmlist (build_tree_list (NULL_TREE, $1.t), 0);
check_for_new_type ("inside parameter list", $1); }
;
@@ -3506,49 +3374,24 @@ parmlist:
as it is ambiguous and must be disambiguated elsewhere. */
complex_parmlist:
parms
- {
- $$ = chainon ($$, void_list_node);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($$, 0); }
| parms_comma ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($1, 1); }
/* C++ allows an ellipsis without a separating ',' */
| parms ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist ($1, 1); }
| type_id ELLIPSIS
- {
- $$ = build_tree_list (NULL_TREE, $1.t);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist (build_tree_list (NULL_TREE,
+ $1.t), 1); }
| ELLIPSIS
- {
- $$ = NULL_TREE;
- }
- | TYPENAME_ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
- | parms TYPENAME_ELLIPSIS
- {
- TREE_PARMLIST ($$) = 1;
- }
- | type_id TYPENAME_ELLIPSIS
- {
- $$ = build_tree_list (NULL_TREE, $1.t);
- TREE_PARMLIST ($$) = 1;
- }
+ { $$ = finish_parmlist (NULL_TREE, 1); }
| parms ':'
{
/* This helps us recover from really nasty
parse errors, for example, a missing right
parenthesis. */
yyerror ("possibly missing ')'");
- $$ = chainon ($$, void_list_node);
- TREE_PARMLIST ($$) = 1;
+ $$ = finish_parmlist ($1, 0);
yyungetc (':', 0);
yychar = ')';
}
@@ -3558,8 +3401,8 @@ complex_parmlist:
parse errors, for example, a missing right
parenthesis. */
yyerror ("possibly missing ')'");
- $$ = tree_cons (NULL_TREE, $1.t, void_list_node);
- TREE_PARMLIST ($$) = 1;
+ $$ = finish_parmlist (build_tree_list (NULL_TREE,
+ $1.t), 0);
yyungetc (':', 0);
yychar = ')';
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5d526c01757..d58ba1db84b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -66,19 +66,23 @@ void
finish_expr_stmt (expr)
tree expr;
{
- if (!processing_template_decl)
+ if (expr != NULL_TREE)
{
- emit_line_note (input_filename, lineno);
- /* Do default conversion if safe and possibly important,
- in case within ({...}). */
- if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
- && lvalue_p (expr))
- || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
- expr = default_conversion (expr);
+ if (!processing_template_decl)
+ {
+ emit_line_note (input_filename, lineno);
+ /* Do default conversion if safe and possibly important,
+ in case within ({...}). */
+ if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+ && lvalue_p (expr))
+ || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
+ expr = default_conversion (expr);
+ }
+
+ cplus_expand_expr_stmt (expr);
+ clear_momentary ();
}
-
- cplus_expand_expr_stmt (expr);
- clear_momentary ();
+
finish_stmt ();
}
@@ -993,6 +997,58 @@ finish_label_address_expr (label)
return result;
}
+/* Finish an expression of the form CODE EXPR. */
+
+tree
+finish_unary_op_expr (code, expr)
+ enum tree_code code;
+ tree expr;
+{
+ tree result = build_x_unary_op (code, expr);
+ if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST)
+ TREE_NEGATED_INT (result) = 1;
+ overflow_warning (result);
+ return result;
+}
+
+/* Finish an id-expression. */
+
+tree
+finish_id_expr (expr)
+ tree expr;
+{
+ if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ expr = do_identifier (expr, 1);
+
+ return expr;
+}
+
+/* Begin a new-placement. */
+
+int
+begin_new_placement ()
+{
+ /* The arguments to a placement new might be passed to a
+ deallocation function, in the event that the allocation throws an
+ exception. Since we don't expand exception handlers until the
+ end of a function, we must make sure the arguments stay around
+ that long. */
+ return suspend_momentary ();
+}
+
+/* Finish a new-placement. The ARGS are the placement arguments. The
+ COOKIE is the value returned by the previous call to
+ begin_new_placement. */
+
+tree
+finish_new_placement (args, cookie)
+ tree args;
+ int cookie;
+{
+ resume_momentary (cookie);
+ return args;
+}
+
/* Begin a function defniition declared with DECL_SPECS and
DECLARATOR. Returns non-zero if the function-declaration is
legal. */
@@ -1031,6 +1087,35 @@ begin_constructor_declarator (scope, name)
return result;
}
+/* Finish an init-declarator. Returns a DECL. */
+
+tree
+finish_declarator (declarator, declspecs, attributes,
+ prefix_attributes, initialized)
+ tree declarator;
+ tree declspecs;
+ tree attributes;
+ tree prefix_attributes;
+ int initialized;
+{
+ return start_decl (declarator, declspecs, initialized, attributes,
+ prefix_attributes);
+}
+
+/* Finish a transltation unit. */
+
+void
+finish_translation_unit ()
+{
+ /* In case there were missing closebraces,
+ get us back to the global binding level. */
+ while (! toplevel_bindings_p ())
+ poplevel (0, 0, 0);
+ while (current_namespace != global_namespace)
+ pop_namespace ();
+ finish_file ();
+}
+
/* Finish a template type parameter, specified as AGGR IDENTIFIER.
Returns the parameter. */
@@ -1067,3 +1152,182 @@ finish_template_template_parm (aggr, identifier)
return finish_template_type_parm (aggr, tmpl);
}
+
+/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is
+ non-zero, the parameter list was terminated by a `...'. */
+
+tree
+finish_parmlist (parms, ellipsis)
+ tree parms;
+ int ellipsis;
+{
+ if (!ellipsis)
+ chainon (parms, void_list_node);
+ /* We mark the PARMS as a parmlist so that declarator processing can
+ disambiguate certain constructs. */
+ if (parms != NULL_TREE)
+ TREE_PARMLIST (parms) = 1;
+
+ return parms;
+}
+
+/* Begin a class definition, as indicated by T. */
+
+tree
+begin_class_definition (t)
+ tree t;
+{
+ tree new_type = t;
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ if (t == error_mark_node
+ || ! IS_AGGR_TYPE (t))
+ {
+ t = new_type = make_lang_type (RECORD_TYPE);
+ pushtag (make_anon_name (), t, 0);
+ }
+ if (TYPE_SIZE (t))
+ duplicate_tag_error (t);
+ if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
+ {
+ t = make_lang_type (TREE_CODE (t));
+ pushtag (TYPE_IDENTIFIER (t), t, 0);
+ new_type = t;
+ }
+ if (processing_template_decl && TYPE_CONTEXT (t)
+ && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
+ && ! current_class_type)
+ push_template_decl (TYPE_STUB_DECL (t));
+ pushclass (t, 0);
+ TYPE_BEING_DEFINED (t) = 1;
+ if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
+ && TYPE_SIZE (t) == NULL_TREE)
+ {
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (t));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ cp_error ("specialization after instantiation of `%T'", t);
+ }
+ /* Reset the interface data, at the earliest possible
+ moment, as it might have been set via a class foo;
+ before. */
+ /* Don't change signatures. */
+ if (! IS_SIGNATURE (t))
+ {
+ extern tree pending_vtables;
+ int needs_writing;
+ tree name = TYPE_IDENTIFIER (t);
+
+ if (! ANON_AGGRNAME_P (name))
+ {
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+ (t, interface_unknown);
+ }
+
+ /* Record how to set the access of this class's
+ virtual functions. If write_virtuals == 2 or 3, then
+ inline virtuals are ``extern inline''. */
+ switch (write_virtuals)
+ {
+ case 0:
+ case 1:
+ needs_writing = 1;
+ break;
+ case 2:
+ needs_writing = !! value_member (name, pending_vtables);
+ break;
+ case 3:
+ needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
+ && CLASSTYPE_INTERFACE_KNOWN (t);
+ break;
+ default:
+ needs_writing = 0;
+ }
+ CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
+ }
+#if 0
+ t = TYPE_IDENTIFIER ($<ttype>0);
+ if (t && IDENTIFIER_TEMPLATE (t))
+ overload_template_name (t, 1);
+#endif
+ reset_specialization();
+
+ /* In case this is a local class within a template
+ function, we save the current tree structure so
+ that we can get it back later. */
+ begin_tree ();
+
+ return new_type;
+}
+
+/* Finish a class definition T, with the indicated COMPONENTS, and
+ with the indicate ATTRIBUTES. If SEMI, the definition is
+ immediately followed by a semicolon. Returns the type. */
+
+tree
+finish_class_definition (t, components, attributes, semi)
+ tree t;
+ tree components;
+ tree attributes;
+ int semi;
+{
+#if 0
+ /* Need to rework class nesting in the presence of nested classes,
+ etc. */
+ shadow_tag (CLASSTYPE_AS_LIST (t)); */
+#endif
+
+ /* finish_struct nukes this anyway; if finish_exception does too,
+ then it can go. */
+ if (semi)
+ note_got_semicolon (t);
+
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ ;
+ else
+ {
+ t = finish_struct (t, components, attributes, semi);
+ if (semi)
+ note_got_semicolon (t);
+ }
+
+ pop_obstacks ();
+
+ if (! semi)
+ check_for_missing_semicolon (t);
+ if (current_scope () == current_function_decl)
+ do_pending_defargs ();
+
+ return t;
+}
+
+/* Finish processing the default argument expressions cached during
+ the processing of a class definition. */
+
+void
+finish_default_args ()
+{
+ if (pending_inlines
+ && current_scope () == current_function_decl)
+ do_pending_inlines ();
+}
+
+/* Finish processing the inline function definitions cached during the
+ processing of a class definition. */
+
+void
+begin_inline_definitions ()
+{
+ if (current_class_type == NULL_TREE)
+ clear_inline_text_obstack ();
+
+ /* Undo the begin_tree in begin_class_definition. */
+ end_tree ();
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/new.C b/gcc/testsuite/g++.old-deja/g++.other/new.C
new file mode 100644
index 00000000000..829db70e868
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/new.C
@@ -0,0 +1,57 @@
+// Build don't link:
+
+typedef unsigned int size_t;
+inline void *
+operator new(size_t alloc_sz, const char *fname, unsigned lineno)
+{
+}
+inline void *
+operator new[](size_t alloc_sz, const char *fname, unsigned lineno)
+{
+}
+inline void
+operator delete(void *ptr, const char *fname, unsigned lineno)
+{
+}
+inline void
+operator delete[](void *ptr, const char *fname, unsigned lineno)
+{
+}
+
+class DEF {
+public:
+ DEF( DEF *parent=0, const char *name=0 );
+};
+
+class ABC
+{
+public:
+ enum stuff { ID0, ID1 };
+ ABC( stuff, DEF *parent=0, const char *name=0 );
+};
+
+class GHI : public DEF
+{
+};
+
+class LMNFrame;
+class LMN : public DEF
+{
+ friend class LMNFrame;
+ public:
+public:
+ LMN();
+private:
+ LMNFrame *draw_area;
+
+ ABC *scroll_h;
+};
+class LMNFrame : public GHI {
+};
+LMN::LMN()
+{
+ draw_area = new ("abc", 69) LMNFrame;
+
+ scroll_h = new ("def", 71) ABC(ABC::ID0, this);
+}
+