cp-tree.h (finish_unary_op_expr): New function.
authorMark Mitchell <mmitchell@usa.net>
Mon, 11 May 1998 00:07:25 +0000 (00:07 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 11 May 1998 00:07:25 +0000 (00:07 +0000)
* 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.

From-SVN: r19660

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/gxx.gperf
gcc/cp/hash.h
gcc/cp/parse.y
gcc/cp/semantics.c
gcc/testsuite/g++.old-deja/g++.other/new.C [new file with mode: 0644]

index 315feea3bd5dc14fe566d4115db9b5619349a486..95fa40af7a9cb2c48f6b62d903ef140089232d53 100644 (file)
@@ -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
index 662ba152f969bd863333c894ae30e9aeff5171d7..f044553d9ff339d856bb9fec35f4ad553837504e 100644 (file)
@@ -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));
index d9cad4a6255bfd74c45b73d144dac02b690af96c..71538567c135567122b353f1159601761f8b64e8 100644 (file)
@@ -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
index 720890fd4c883168b79a527213dbabb44de8118d..1e31a354724a80bcd71c790f69f7d96953c634f3 100644 (file)
@@ -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,},
index 074f640f0ee4f4a73b0612781c4a35532085cdd3..d9df9b8919fed3c39b8f48e6517efaa61a66c98a 100644 (file)
@@ -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 = ')';
                }
index 5d526c017578411643d99c776090ad6128b779fa..d58ba1db84b7c5060b04d20a0fcf9e55db018a31 100644 (file)
@@ -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 (file)
index 0000000..829db70
--- /dev/null
@@ -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);
+}
+