class.c (instantiate_type): Handle object-relative template-id.
[platform/upstream/gcc.git] / gcc / cp / parse.y
index ef96a0b..ac053ab 100644 (file)
@@ -1,5 +1,6 @@
 /* YACC parser for C++ syntax.
-   Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1989, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -42,10 +43,11 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
+#include "ggc.h"
 
 /* Since parsers are distinct for each language, put the language string
    definition here.  (fnf) */
-char *language_string = "GNU C++";
+const char * const language_string = "GNU C++";
 
 extern struct obstack permanent_obstack;
 
@@ -61,18 +63,40 @@ extern int end_of_file;
    error message if the user supplies an empty conditional expression.  */
 static const char *cond_stmt_keyword;
 
-static tree empty_parms PROTO((void));
-static int parse_decl PROTO((tree, tree, tree, int, tree *));
-
 /* Nonzero if we have an `extern "C"' acting as an extern specifier.  */
 int have_extern_spec;
 int used_extern_spec;
 
+/* List of types and structure classes of the current declaration.  */
+static tree current_declspecs;
+
+/* List of prefix attributes in effect.
+   Prefix attributes are parsed by the reserved_declspecs and declmods
+   rules.  They create a list that contains *both* declspecs and attrs.  */
+/* ??? It is not clear yet that all cases where an attribute can now appear in
+   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;
+
+static tree empty_parms PARAMS ((void));
+static tree parse_decl0 PARAMS ((tree, tree, tree, tree, int));
+static tree parse_decl PARAMS ((tree, tree, int));
+static void parse_end_decl PARAMS ((tree, tree, tree));
+static tree parse_field0 PARAMS ((tree, tree, tree, tree, tree, tree));
+static tree parse_field PARAMS ((tree, tree, tree, tree));
+static tree parse_bitfield0 PARAMS ((tree, tree, tree, tree, tree));
+static tree parse_bitfield PARAMS ((tree, tree, tree));
+static tree parse_method PARAMS ((tree, tree, tree));
+static void frob_specs PARAMS ((tree, tree)); 
+
 /* Cons up an empty parameter list.  */
-#ifdef __GNUC__
-__inline
-#endif
-static tree
+static inline tree
 empty_parms ()
 {
   tree parms;
@@ -85,11 +109,123 @@ empty_parms ()
   return parms;
 }
 
+/* Record the decl-specifiers, attributes and type lookups from the
+   decl-specifier-seq in a declaration.  */
+
+static void
+frob_specs (specs_attrs, lookups)
+     tree specs_attrs, lookups;
+{
+  save_type_access_control (lookups);
+  split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
+  if (current_declspecs
+      && TREE_CODE (current_declspecs) != TREE_LIST)
+    current_declspecs = build_decl_list (NULL_TREE, current_declspecs);
+  if (have_extern_spec && !used_extern_spec)
+    {
+      current_declspecs = decl_tree_cons (NULL_TREE, 
+                                         get_identifier ("extern"), 
+                                         current_declspecs);
+      used_extern_spec = 1;
+    }
+}
+
+static tree
+parse_decl (declarator, attributes, initialized)
+     tree declarator, attributes;
+     int initialized;
+{
+  return start_decl (declarator, current_declspecs, initialized,
+                    attributes, prefix_attributes);
+}
+
+static tree
+parse_decl0 (declarator, specs_attrs, lookups, attributes, initialized)
+     tree declarator, specs_attrs, lookups, attributes;
+     int initialized;
+{
+  frob_specs (specs_attrs, lookups);
+  return parse_decl (declarator, attributes, initialized);
+}
+
+static void
+parse_end_decl (decl, init, asmspec)
+     tree decl, init, asmspec;
+{
+  /* If decl is NULL_TREE, then this was a variable declaration using
+     () syntax for the initializer, so we handled it in grokdeclarator.  */
+  if (decl)
+    decl_type_access_control (decl);
+  cp_finish_decl (decl, init, asmspec, init ? LOOKUP_ONLYCONVERTING : 0);
+}
+
+static tree
+parse_field (declarator, attributes, asmspec, init)
+     tree declarator, attributes, asmspec, init;
+{
+  tree d = grokfield (declarator, current_declspecs, init, asmspec,
+                     build_tree_list (attributes, prefix_attributes));
+  decl_type_access_control (d);
+  return d;
+}
+
+static tree
+parse_field0 (declarator, specs_attrs, lookups, attributes, asmspec, init)
+     tree declarator, specs_attrs, lookups, attributes, asmspec, init;
+{
+  frob_specs (specs_attrs, lookups);
+  return parse_field (declarator, attributes, asmspec, init);
+}
+
+static tree
+parse_bitfield (declarator, attributes, width)
+     tree declarator, attributes, width;
+{
+  tree d = grokbitfield (declarator, current_declspecs, width);
+  cplus_decl_attributes (d, attributes, prefix_attributes);
+  decl_type_access_control (d);
+  return d;
+}
+
+static tree
+parse_bitfield0 (declarator, specs_attrs, lookups, attributes, width)
+     tree declarator, specs_attrs, lookups, attributes, width;
+{
+  frob_specs (specs_attrs, lookups);
+  return parse_bitfield (declarator, attributes, width);
+}
+
+static tree
+parse_method (declarator, specs_attrs, lookups)
+     tree declarator, specs_attrs, lookups;
+{
+  tree d;
+  frob_specs (specs_attrs, lookups);
+  d = start_method (current_declspecs, declarator, prefix_attributes);
+  decl_type_access_control (d);
+  return d;
+}
+
+void
+cp_parse_init ()
+{
+  ggc_add_tree_root (&current_declspecs, 1);
+  ggc_add_tree_root (&prefix_attributes, 1);
+  ggc_add_tree_root (&current_aggr, 1);
+  ggc_add_tree_root (&current_enum_type, 1);
+}
 %}
 
 %start program
 
-%union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; }
+%union {
+  long itype; 
+  tree ttype; 
+  char *strtype; 
+  enum tree_code code; 
+  flagged_type_tree ftype; 
+  struct pending_inline *pi;
+}
 
 /* All identifiers that are not reserved words
    and are not declared typedefs in the current block */
@@ -192,9 +328,7 @@ empty_parms ()
 %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
 %type <ttype> reserved_declspecs boolean.literal
 %type <ttype> reserved_typespecquals
-%type <ttype> declmods 
 %type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
-%type <itype> initdecls notype_initdecls initdcl       /* C++ modification */
 %type <ttype> init initlist maybeasm maybe_init defarg defarg1
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
@@ -211,7 +345,6 @@ empty_parms ()
 %type <ttype> component_declarator component_declarator0
 %type <ttype> notype_component_declarator notype_component_declarator0
 %type <ttype> after_type_component_declarator after_type_component_declarator0
-%type <ttype> enumlist_opt enumlist enumerator
 %type <ttype> absdcl cv_qualifiers
 %type <ttype> direct_abstract_declarator conversion_declarator
 %type <ttype> new_declarator direct_new_declarator
@@ -230,15 +363,18 @@ empty_parms ()
 %type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
 %type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
 %type <ftype> structsp typespecqual_reserved parm named_parm full_parm
+%type <ftype> declmods
 
 %type <itype> extension
 
 /* C++ extensions */
 %token <ttype> PTYPENAME
-%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
+%token <ttype> EXTERN_LANG_STRING ALL
 %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
+%token <pi> PRE_PARSED_FUNCTION_DECL 
 %type <ttype> component_constructor_declarator
-%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
+%type <ttype> fn.def2 return_id constructor_declarator
+%type <pi> fn.defpen 
 %type <itype> ctor_initializer_opt function_try_block
 %type <ttype> named_class_head_sans_basetype
 %type <ftype> class_head named_class_head 
@@ -250,10 +386,10 @@ empty_parms ()
 %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
 %type <ttype> operator_name
 %type <ttype> object aggr
-%type <itype> new delete .begin_new_placement
+%type <itype> new delete
 /* %type <ttype> primary_no_id */
-%type <ttype> nonmomentary_expr maybe_parmlist
-%type <itype> initdcl0 notype_initdcl0 member_init_list initdcl0_innards
+%type <ttype> maybe_parmlist
+%type <itype> member_init_list
 %type <ttype> template_header template_parm_list template_parm
 %type <ttype> template_type_parm template_template_parm
 %type <code>  template_close_bracket
@@ -272,7 +408,7 @@ empty_parms ()
 %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
 %type <ttype> named_class_head_sans_basetype_defn
 %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
-
+%type <ttype> handler_args
 %type <ttype> self_template_type .finish_template_type
 
 %token NSNAME
@@ -286,55 +422,9 @@ empty_parms ()
 %token END_OF_SAVED_INPUT
 \f
 %{
-/* List of types and structure classes of the current declaration.  */
-static tree current_declspecs;
-
-/* List of prefix attributes in effect.
-   Prefix attributes are parsed by the reserved_declspecs and declmods
-   rules.  They create a list that contains *both* declspecs and attrs.  */
-/* ??? It is not clear yet that all cases where an attribute can now appear in
-   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;
-
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
-
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint                    PROTO((FILE *, int, YYSTYPE));
-extern tree combine_strings            PROTO((tree));
-
-static int
-parse_decl(declarator, specs_attrs, attributes, initialized, decl)
-  tree declarator;
-  tree specs_attrs;
-  tree attributes;
-  int initialized;
-  tree* decl;
-{
-  int  sm;
-
-  split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
-  if (current_declspecs
-      && TREE_CODE (current_declspecs) != TREE_LIST)
-    current_declspecs = build_decl_list (NULL_TREE, current_declspecs);
-  if (have_extern_spec && !used_extern_spec)
-    {
-      current_declspecs = decl_tree_cons (NULL_TREE, 
-                                         get_identifier ("extern"), 
-                                         current_declspecs);
-      used_extern_spec = 1;
-    }
-  sm = suspend_momentary ();
-  *decl = start_decl (declarator, current_declspecs, initialized,
-                     attributes, prefix_attributes);
-  return sm;
-}
+extern void yyprint                    PARAMS ((FILE *, int, YYSTYPE));
 %}
 \f
 %%
@@ -351,9 +441,9 @@ program:
 extdefs:
                { $<ttype>$ = NULL_TREE; }
          lang_extdef
-               { $<ttype>$ = NULL_TREE; }
+               { $<ttype>$ = NULL_TREE; ggc_collect (); }
        | extdefs lang_extdef
-               { $<ttype>$ = NULL_TREE; }
+               { $<ttype>$ = NULL_TREE; ggc_collect (); }
        ;
 
 extdefs_opt:
@@ -381,7 +471,8 @@ asm_keyword:
        ;
 
 lang_extdef:
-               { if (pending_lang_change) do_pending_lang_change(); }
+               { if (pending_lang_change) do_pending_lang_change();
+                 type_lookups = NULL_TREE; }
          extdef
                { if (! toplevel_bindings_p ())
                  pop_everything (); }
@@ -641,13 +732,9 @@ eat_saved_input:
 
 fndef:
          fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
-               { finish_function (lineno, (int)$3, 0); }
+               { expand_body (finish_function (lineno, (int)$3)); }
        | fn.def1 maybe_return_init function_try_block
-               { 
-                 int nested = (hack_decl_function_context
-                               (current_function_decl) != NULL_TREE);
-                 finish_function (lineno, (int)$3, nested); 
-               }
+               { expand_body (finish_function (lineno, (int)$3)); }
        | fn.def1 maybe_return_init error
                { }
        ;
@@ -689,16 +776,17 @@ constructor_declarator:
 
 fn.def1:
          typed_declspecs declarator
-               { if (!begin_function_definition ($1.t, $2))
+               { check_for_new_type ("return type", $1);
+                 if (!begin_function_definition ($1.t, $2))
                    YYERROR1; }
        | declmods notype_declarator
-               { if (!begin_function_definition ($1, $2))
+               { if (!begin_function_definition ($1.t, $2))
                    YYERROR1; }
        | notype_declarator
                { if (!begin_function_definition (NULL_TREE, $1))
                    YYERROR1; }
        | declmods constructor_declarator
-               { if (!begin_function_definition ($1, $2))
+               { if (!begin_function_definition ($1.t, $2))
                    YYERROR1; }
        | constructor_declarator
                { if (!begin_function_definition (NULL_TREE, $1))
@@ -720,10 +808,7 @@ component_constructor_declarator:
    reduce/reduce conflict introduced by these rules.  */
 fn.def2:
          declmods component_constructor_declarator
-               { tree specs, attrs;
-                 split_specs_attrs ($1, &specs, &attrs);
-                 attrs = build_tree_list (attrs, NULL_TREE);
-                 $$ = start_method (specs, $2, attrs);
+               { $$ = parse_method ($2, $1.t, $1.lookups);
                 rest_of_mdef:
                  if (! $$)
                    YYERROR1;
@@ -731,28 +816,19 @@ fn.def2:
                    yychar = YYLEX;
                  reinit_parse_for_method (yychar, $$); }
        | component_constructor_declarator
-               { $$ = start_method (NULL_TREE, $1, NULL_TREE); 
+               { $$ = parse_method ($1, NULL_TREE, NULL_TREE); 
                  goto rest_of_mdef; }
        | typed_declspecs declarator
-               { tree specs, attrs;
-                 split_specs_attrs ($1.t, &specs, &attrs);
-                 attrs = build_tree_list (attrs, NULL_TREE);
-                 $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
+               { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
        | declmods notype_declarator
-               { tree specs, attrs;
-                 split_specs_attrs ($1, &specs, &attrs);
-                 attrs = build_tree_list (attrs, NULL_TREE);
-                 $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
+               { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
        | notype_declarator
-               { $$ = start_method (NULL_TREE, $$, NULL_TREE); 
+               { $$ = parse_method ($1, NULL_TREE, NULL_TREE); 
                  goto rest_of_mdef; }
        | declmods constructor_declarator
-               { tree specs, attrs;
-                 split_specs_attrs ($1, &specs, &attrs);
-                 attrs = build_tree_list (attrs, NULL_TREE);
-                 $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
+               { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
        | constructor_declarator
-               { $$ = start_method (NULL_TREE, $$, NULL_TREE); 
+               { $$ = parse_method ($1, NULL_TREE, NULL_TREE); 
                  goto rest_of_mdef; }
        ;
 
@@ -790,12 +866,8 @@ base_init:
                    store_parm_decls ();
 
                  if (DECL_CONSTRUCTOR_P (current_function_decl))
-                   {
-                     /* Make a contour for the initializer list.  */
-                     pushlevel (0);
-                     clear_last_expr ();
-                     expand_start_bindings (0);
-                   }
+                   /* Make a contour for the initializer list.  */
+                   do_pushlevel ();
                  else if (current_class_type == NULL_TREE)
                    error ("base initializers not allowed for non-member functions");
                  else if (! DECL_CONSTRUCTOR_P (current_function_decl))
@@ -839,6 +911,7 @@ member_init:
        | typename_sub LEFT_RIGHT
                { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
                                      void_type_node); }
+        | error
        ;
 
 identifier:
@@ -986,7 +1059,7 @@ expr:
 
 paren_expr_or_null:
        LEFT_RIGHT
-               { error ("ANSI C++ forbids an empty condition for `%s'",
+               { error ("ISO C++ forbids an empty condition for `%s'",
                         cond_stmt_keyword);
                  $$ = integer_zero_node; }
        | '(' expr ')'
@@ -995,7 +1068,7 @@ paren_expr_or_null:
 
 paren_cond_or_null:
        LEFT_RIGHT
-               { error ("ANSI C++ forbids an empty condition for `%s'",
+               { error ("ISO C++ forbids an empty condition for `%s'",
                         cond_stmt_keyword);
                  $$ = integer_zero_node; }
        | '(' condition ')'
@@ -1024,14 +1097,11 @@ condition:
                    }
                  }
                  current_declspecs = $1.t;
-                 $<itype>5 = suspend_momentary ();
-                 $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1,
-                                         $4, /*prefix_attributes*/ NULL_TREE);
+                 $<ttype>$ = parse_decl ($<ttype>2, $4, 1);
                }
          init
                { 
-                 cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING);
-                 resume_momentary ($<itype>5);
+                 parse_end_decl ($<ttype>6, $7, $4);
                  $$ = convert_from_reference ($<ttype>6); 
                  if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
                    cp_error ("definition of array `%#D' in condition", $$); 
@@ -1057,20 +1127,20 @@ already_scoped_stmt:
 
 nontrivial_exprlist:
          expr_no_commas ',' expr_no_commas
-               { $$ = expr_tree_cons (NULL_TREE, $$, 
-                                 build_expr_list (NULL_TREE, $3)); }
+               { $$ = tree_cons (NULL_TREE, $$, 
+                                 build_tree_list (NULL_TREE, $3)); }
        | expr_no_commas ',' error
-               { $$ = expr_tree_cons (NULL_TREE, $$, 
-                                 build_expr_list (NULL_TREE, error_mark_node)); }
+               { $$ = tree_cons (NULL_TREE, $$, 
+                                 build_tree_list (NULL_TREE, error_mark_node)); }
        | nontrivial_exprlist ',' expr_no_commas
-               { chainon ($$, build_expr_list (NULL_TREE, $3)); }
+               { chainon ($$, build_tree_list (NULL_TREE, $3)); }
        | nontrivial_exprlist ',' error
-               { chainon ($$, build_expr_list (NULL_TREE, error_mark_node)); }
+               { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); }
        ;
 
 nonnull_exprlist:
          expr_no_commas
-               { $$ = build_expr_list (NULL_TREE, $$); }
+               { $$ = build_tree_list (NULL_TREE, $$); }
        | nontrivial_exprlist
        ;
 
@@ -1092,7 +1162,7 @@ unary_expr:
        /* Refer to the address of a label as a pointer.  */
        | ANDAND identifier
                { if (pedantic)
-                   pedwarn ("ANSI C++ forbids `&&'");
+                   pedwarn ("ISO C++ forbids `&&'");
                  $$ = finish_label_address_expr ($2); }
        | SIZEOF unary_expr  %prec UNARY
                { $$ = expr_sizeof ($2); }
@@ -1119,32 +1189,20 @@ unary_expr:
        | new new_placement new_type_id new_initializer
                { $$ = build_new ($2, $3.t, $4, $1); 
                  check_for_new_type ("new", $3); }
-        /* The .begin_new_placement in the following rules is
-          necessary to avoid shift/reduce conflicts that lead to
-          mis-parsing some expressions.  Of course, these constructs
-          are not really new-placement and it is bogus to call
-          begin_new_placement.  But, the parser cannot always tell at this
-          point whether the next thing is an expression or a type-id,
-          so there is nothing we can do.  Fortunately,
-          begin_new_placement does nothing harmful.  When we rewrite
-          the parser, this lossage should be removed, of course.  */
-       | new '(' .begin_new_placement type_id .finish_new_placement
+       | new '(' type_id ')'
             %prec EMPTY
-               { $$ = build_new (NULL_TREE, groktypename($4.t),
+               { $$ = build_new (NULL_TREE, groktypename($3.t),
                                  NULL_TREE, $1); 
+                 check_for_new_type ("new", $3); }
+       | new '(' type_id ')' new_initializer
+               { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1); 
+                 check_for_new_type ("new", $3); }
+       | new new_placement '(' type_id ')' %prec EMPTY
+               { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1); 
                  check_for_new_type ("new", $4); }
-       | new '(' .begin_new_placement type_id .finish_new_placement
-            new_initializer
-               { $$ = build_new (NULL_TREE, groktypename($4.t), $6, $1); 
+       | new new_placement '(' type_id ')' new_initializer
+               { $$ = build_new ($2, groktypename($4.t), $6, $1); 
                  check_for_new_type ("new", $4); }
-       | new new_placement '(' .begin_new_placement type_id
-           .finish_new_placement   %prec EMPTY
-               { $$ = build_new ($2, groktypename($5.t), NULL_TREE, $1); 
-                 check_for_new_type ("new", $5); }
-       | new new_placement '(' .begin_new_placement type_id
-           .finish_new_placement  new_initializer
-               { $$ = build_new ($2, groktypename($5.t), $7, $1); 
-                 check_for_new_type ("new", $5); }
 
        | delete cast_expr  %prec UNARY
                { $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
@@ -1161,28 +1219,16 @@ unary_expr:
        | IMAGPART cast_expr %prec UNARY
                { $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
        | VA_ARG '(' expr_no_commas ',' type_id ')'
-               { $$ = build_va_arg ($3, groktypename ($5.t));
+               { $$ = build_x_va_arg ($3, groktypename ($5.t));
                  check_for_new_type ("__builtin_va_arg", $5); }
        ;
 
-        /* Note this rule is not suitable for use in new_placement
-          since it uses NULL_TREE as the argument to
-          finish_new_placement.  This rule serves only to avoid
-          reduce/reduce conflicts in unary_expr.  See the comments
-          there on the use of begin/finish_new_placement.  */
-.finish_new_placement:
-         ')'
-                { finish_new_placement (NULL_TREE, $<itype>-1); }
-
-.begin_new_placement:
-                { $$ = begin_new_placement (); }
-
 new_placement:
-         '(' .begin_new_placement nonnull_exprlist ')'
-                { $$ = finish_new_placement ($3, $2); }
-       | '{' .begin_new_placement nonnull_exprlist '}'
+         '(' nonnull_exprlist ')'
+                { $$ = $2; }
+       | '{' nonnull_exprlist '}'
                 { cp_pedwarn ("old style placement syntax, use () instead");
-                 $$ = finish_new_placement ($3, $2); }
+                 $$ = $2; }
        ;
 
 new_initializer:
@@ -1201,10 +1247,10 @@ new_initializer:
        | '=' init
                {
                  if (pedantic)
-                   pedwarn ("ANSI C++ forbids initialization of new expression with `='");
+                   pedwarn ("ISO C++ forbids initialization of new expression with `='");
                  if (TREE_CODE ($2) != TREE_LIST
                      && TREE_CODE ($2) != CONSTRUCTOR)
-                   $$ = build_expr_list (NULL_TREE, $2);
+                   $$ = build_tree_list (NULL_TREE, $2);
                  else
                    $$ = $2;
                }
@@ -1231,7 +1277,7 @@ cast_expr:
                  tree init = build_nt (CONSTRUCTOR, NULL_TREE,
                                        nreverse ($3)); 
                  if (pedantic)
-                   pedwarn ("ANSI C++ forbids constructor-expressions");
+                   pedwarn ("ISO C++ forbids constructor-expressions");
                  /* Indicate that this was a GNU C constructor expression.  */
                  TREE_HAS_CONSTRUCTOR (init) = 1;
 
@@ -1403,8 +1449,6 @@ primary:
        | boolean.literal
        | string
                {
-                 if (processing_template_decl)
-                   push_obstacks (&permanent_obstack, &permanent_obstack);
                  $$ = combine_strings ($$);
                  /* combine_strings doesn't set up TYPE_MAIN_VARIANT of
                     a const array the way we want, so fix it.  */
@@ -1412,8 +1456,6 @@ primary:
                    TREE_TYPE ($$) = build_cplus_array_type
                      (TREE_TYPE (TREE_TYPE ($$)),
                       TYPE_DOMAIN (TREE_TYPE ($$)));
-                 if (processing_template_decl)
-                   pop_obstacks ();
                }
        | '(' expr ')'
                { $$ = finish_parenthesized_expr ($2); }
@@ -1430,11 +1472,11 @@ primary:
                      YYERROR;
                    }
                  if (pedantic)
-                   pedwarn ("ANSI C++ forbids braced-groups within expressions");  
+                   pedwarn ("ISO C++ forbids braced-groups within expressions");  
                  $<ttype>$ = begin_stmt_expr (); 
                }
          compstmt ')'
-               { $$ = finish_stmt_expr ($<ttype>2, $3); }
+               { $$ = finish_stmt_expr ($<ttype>2); }
         /* Koenig lookup support
            We could store lastiddecl in $1 to avoid another lookup,
            but that would result in many additional reduce/reduce conflicts. */
@@ -1462,15 +1504,9 @@ primary:
                     `const (3)' is equivalent to `const int (3)'.  */
                  tree type;
 
-                 if ($3 == error_mark_node)
-                   {
-                     $$ = error_mark_node;
-                     break;
-                   }
-
-                 type = cp_build_qualified_type (integer_type_node,
-                                                 cp_type_qual_from_rid ($1));
-                 $$ = build_c_cast (type, build_compound_expr ($3));
+                 type = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
+                 type = groktypename (build_decl_list (type, NULL_TREE));
+                 $$ = build_functional_cast (type, $3);
                }
        | functional_cast
        | DYNAMIC_CAST '<' type_id '>' '(' expr ')'
@@ -1490,7 +1526,7 @@ primary:
                  check_for_new_type ("const_cast", $3);
                  $$ = build_const_cast (type, $6); }
        | TYPEID '(' expr ')'
-               { $$ = build_x_typeid ($3); }
+               { $$ = build_typeid ($3); }
        | TYPEID '(' type_id ')'
                { tree type = groktypename ($3.t);
                  check_for_new_type ("typeid", $3);
@@ -1525,7 +1561,7 @@ primary:
                { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
        | object overqualified_id  %prec UNARY
                { if (processing_template_decl)
-                   $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
+                   $$ = build_min_nt (COMPONENT_REF, $1, $2);
                  else
                    $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
        | object unqualified_id '(' nonnull_exprlist ')'
@@ -1563,7 +1599,7 @@ primary_no_id:
                  $<ttype>$ = expand_start_stmt_expr (); }
          compstmt ')'
                { if (pedantic)
-                   pedwarn ("ANSI C++ forbids braced-groups within expressions");
+                   pedwarn ("ISO C++ forbids braced-groups within expressions");
                  $$ = expand_end_stmt_expr ($<ttype>2); }
        | primary_no_id '(' nonnull_exprlist ')'
                { $$ = build_x_function_call ($$, $3, current_class_ref); }
@@ -1635,17 +1671,15 @@ object:
 decl:
          typespec initdecls ';'
                {
-                 resume_momentary ($2);
                  if ($1.t && IS_AGGR_TYPE_CODE (TREE_CODE ($1.t)))
                    note_got_semicolon ($1.t);
                }
        | typed_declspecs initdecls ';'
                {
-                 resume_momentary ($2);
                  note_list_got_semicolon ($1.t);
                }
        | declmods notype_initdecls ';'
-               { resume_momentary ($2); }
+                {}
        | typed_declspecs ';'
                {
                  shadow_tag ($1.t);
@@ -1675,7 +1709,7 @@ fcast_or_absdcl:
                                             NULL_TREE); }
        ;
 
-/* ANSI type-id (8.1) */
+/* ISO type-id (8.1) */
 type_id:
          typed_typespecs absdcl
                { $$.t = build_decl_list ($1.t, $2); 
@@ -1702,12 +1736,14 @@ type_id:
 
 typed_declspecs:
          typed_typespecs  %prec EMPTY
+               { $$.lookups = type_lookups; }
        | typed_declspecs1
+               { $$.lookups = type_lookups; }
        ;
 
 typed_declspecs1:
          declmods typespec
-               { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1); 
+               { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t); 
                  $$.new_type_flag = $2.new_type_flag; }
        | typespec reserved_declspecs  %prec HYPERUNARY
                { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); 
@@ -1716,14 +1752,14 @@ typed_declspecs1:
                { $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3)); 
                  $$.new_type_flag = $1.new_type_flag; }
        | declmods typespec reserved_declspecs
-               { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); 
+               { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
                  $$.new_type_flag = $2.new_type_flag; }
        | declmods typespec reserved_typespecquals
-               { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); 
+               { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
                  $$.new_type_flag = $2.new_type_flag; }
        | declmods typespec reserved_typespecquals reserved_declspecs
                { $$.t = decl_tree_cons (NULL_TREE, $2.t,
-                                        chainon ($3, chainon ($4, $1))); 
+                                        chainon ($3, chainon ($4, $1.t))); 
                  $$.new_type_flag = $2.new_type_flag; }
        ;
 
@@ -1762,22 +1798,32 @@ reserved_declspecs:
 
 declmods:
          nonempty_cv_qualifiers  %prec EMPTY
-               { $$ = $1.t; TREE_STATIC ($$) = 1; }
+               { $$.lookups = NULL_TREE; TREE_STATIC ($$.t) = 1; }
        | SCSPEC
-               { $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
+               {
+                 $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
+                 $$.new_type_flag = 0; $$.lookups = NULL_TREE;
+               }
        | declmods CV_QUALIFIER
-               { $$ = hash_tree_cons (NULL_TREE, $2, $$);
-                 TREE_STATIC ($$) = 1; }
+               {
+                 $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
+                 TREE_STATIC ($$.t) = 1;
+               }
        | declmods SCSPEC
-               { if (extra_warnings && TREE_STATIC ($$))
+               {
+                 if (extra_warnings && TREE_STATIC ($$.t))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
-                 $$ = hash_tree_cons (NULL_TREE, $2, $$);
-                 TREE_STATIC ($$) = TREE_STATIC ($1); }
+                 $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
+                 TREE_STATIC ($$.t) = TREE_STATIC ($1.t);
+               }
        | declmods attributes
-               { $$ = hash_tree_cons ($2, NULL_TREE, $1); }
+               { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t); }
        | attributes  %prec EMPTY
-               { $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
+               {
+                 $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
+                 $$.new_type_flag = 0; $$.lookups = NULL_TREE;
+               }
        ;
 
 /* Used instead of declspecs where storage classes are not allowed
@@ -1798,7 +1844,7 @@ typed_typespecs:
                  $$.new_type_flag = $1.new_type_flag; }
        | nonempty_cv_qualifiers typespec reserved_typespecquals
                { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
-                 $$.new_type_flag = $1.new_type_flag; }
+                 $$.new_type_flag = $2.new_type_flag; }
        ;
 
 reserved_typespecquals:
@@ -1814,20 +1860,21 @@ reserved_typespecquals:
 
 typespec:
          structsp
+               { $$.lookups = NULL_TREE; }
        | TYPESPEC  %prec EMPTY
-               { $$.t = $1; $$.new_type_flag = 0; }
+               { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
        | complete_type_name
-               { $$.t = $1; $$.new_type_flag = 0; }
+               { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
        | TYPEOF '(' expr ')'
                { $$.t = finish_typeof ($3);
-                 $$.new_type_flag = 0; }
+                 $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
        | TYPEOF '(' type_id ')'
                { $$.t = groktypename ($3.t);
-                 $$.new_type_flag = 0; }
+                 $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
        | SIGOF '(' expr ')'
                { tree type = TREE_TYPE ($3);
 
-                  $$.new_type_flag = 0;
+                  $$.new_type_flag = 0; $$.lookups = NULL_TREE;
                  if (IS_AGGR_TYPE (type))
                    {
                      sorry ("sigof type specifier");
@@ -1842,7 +1889,7 @@ typespec:
        | SIGOF '(' type_id ')'
                { tree type = groktypename ($3.t);
 
-                  $$.new_type_flag = 0;
+                  $$.new_type_flag = 0; $$.lookups = NULL_TREE;
                  if (IS_AGGR_TYPE (type))
                    {
                      sorry ("sigof type specifier");
@@ -1893,15 +1940,15 @@ maybeasm:
 
 initdcl:
          declarator maybeasm maybe_attribute '='
-               { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
-                                         $3, prefix_attributes); }
+               { $<ttype>$ = parse_decl ($<ttype>1, $3, 1); }
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
-               { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); }
+               { parse_end_decl ($<ttype>5, $6, $2); }
        | declarator maybeasm maybe_attribute
-               { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
-                                         $3, prefix_attributes);
-                 cp_finish_decl ($<ttype>$, NULL_TREE, $2, 1, 0); }
+               {
+                 $<ttype>$ = parse_decl ($<ttype>1, $3, 0);
+                 parse_end_decl ($<ttype>$, NULL_TREE, $2);
+               }
        ;
 
         /* This rule assumes a certain configuration of the parser stack.
@@ -1912,27 +1959,26 @@ initdcl:
           we need that reduce so we prefer fn.def1 when appropriate.  */
 initdcl0_innards:
          maybe_attribute '='
-               { $<itype>2 = parse_decl ($<ttype>-1, $<ttype>-2, 
-                                          $1, 1, &$<ttype>$); }
+               { $<ttype>$ = parse_decl0 ($<ttype>-1, $<ftype>-2.t,
+                                          $<ftype>-2.lookups, $1, 1); }
           /* Note how the declaration of the variable is in effect
             while its init is parsed! */ 
          init
-               { cp_finish_decl ($<ttype>3, $4, $<ttype>0, 1,
-                                 LOOKUP_ONLYCONVERTING);
-                 $$ = $<itype>2; }
+               { parse_end_decl ($<ttype>3, $4, $<ttype>0); }
        | maybe_attribute
-               { tree d;
-                 $$ = parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
-                 cp_finish_decl (d, NULL_TREE, $<ttype>0, 1, 0); }
+               { tree d = parse_decl0 ($<ttype>-1, $<ftype>-2.t,
+                                       $<ftype>-2.lookups, $1, 0);
+                 parse_end_decl (d, NULL_TREE, $<ttype>0); }
        ;
   
 initdcl0:
          declarator maybeasm initdcl0_innards
-            { $$ = $3; }
-  
+                {}
+       ;
+
 notype_initdcl0:
           notype_declarator maybeasm initdcl0_innards
-            { $$ = $3; }
+                {}
         ;
   
 nomods_initdcl0:
@@ -1943,9 +1989,8 @@ nomods_initdcl0:
           initdcl0_innards 
             {}
        | constructor_declarator maybeasm maybe_attribute
-               { tree d;
-                 parse_decl($1, NULL_TREE, $3, 0, &d);
-                 cp_finish_decl (d, NULL_TREE, $2, 1, 0); }
+               { tree d = parse_decl0 ($1, NULL_TREE, NULL_TREE, $3, 0);
+                 parse_end_decl (d, NULL_TREE, $2); }
        ;
 
 /* the * rules are dummies to accept the Apollo extended syntax
@@ -2037,39 +2082,38 @@ initlist:
          init
                { $$ = build_tree_list (NULL_TREE, $$); }
        | initlist ',' init
-               { $$ = expr_tree_cons (NULL_TREE, $3, $$); }
+               { $$ = tree_cons (NULL_TREE, $3, $$); }
        /* These are for labeled elements.  */
        | '[' expr_no_commas ']' init
-               { $$ = build_expr_list ($2, $4); }
+               { $$ = build_tree_list ($2, $4); }
        | identifier ':' init
-               { $$ = build_expr_list ($$, $3); }
+               { $$ = build_tree_list ($$, $3); }
        | initlist ',' identifier ':' init
-               { $$ = expr_tree_cons ($3, $5, $$); }
+               { $$ = tree_cons ($3, $5, $$); }
        ;
 
 fn.defpen:
        PRE_PARSED_FUNCTION_DECL
-               { start_function (NULL_TREE, TREE_VALUE ($1),
-                                 NULL_TREE, 2);
+               { start_function (NULL_TREE, $1->fndecl, NULL_TREE, 
+                                 (SF_DEFAULT | SF_PRE_PARSED 
+                                  | SF_INCLASS_INLINE));
                  reinit_parse_for_function (); }
 
 pending_inline:
          fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
                {
-                 int nested = (hack_decl_function_context
-                               (current_function_decl) != NULL_TREE);
-                 finish_function (lineno, (int)$3 | 2, nested);
+                 expand_body (finish_function (lineno, (int)$3 | 2));
                  process_next_inline ($1);
                }
        | fn.defpen maybe_return_init function_try_block
                { 
-                 int nested = (hack_decl_function_context
-                               (current_function_decl) != NULL_TREE);
-                 finish_function (lineno, (int)$3 | 2, nested); 
+                 expand_body (finish_function (lineno, (int)$3 | 2)); 
                   process_next_inline ($1);
                }
        | fn.defpen maybe_return_init error
-               { process_next_inline ($1); }
+               { 
+                 finish_function (lineno, 2); 
+                 process_next_inline ($1); }
        ;
 
 pending_inlines:
@@ -2095,26 +2139,20 @@ pending_defargs:
 
 structsp:
          ENUM identifier '{'
-               { $<itype>3 = suspend_momentary ();
-                 $<ttype>$ = current_enum_type;
+               { $<ttype>$ = current_enum_type;
                  current_enum_type = start_enum ($2); }
          enumlist_opt '}'
-               { TYPE_VALUES (current_enum_type) = $5;
-                 $$.t = finish_enum (current_enum_type);
+               { $$.t = finish_enum (current_enum_type);
                  $$.new_type_flag = 1;
                  current_enum_type = $<ttype>4;
-                 resume_momentary ((int) $<itype>3);
                  check_for_missing_semicolon ($$.t); }
        | ENUM '{'
-               { $<itype>2 = suspend_momentary ();
-                 $<ttype>$ = current_enum_type;
+               { $<ttype>$ = current_enum_type;
                  current_enum_type = start_enum (make_anon_name ()); }
          enumlist_opt '}'
-                { TYPE_VALUES (current_enum_type) = $4;
-                 $$.t = finish_enum (current_enum_type);
+                { $$.t = finish_enum (current_enum_type);
                  $$.new_type_flag = 1;
                  current_enum_type = $<ttype>3;
-                 resume_momentary ((int) $<itype>1);
                  check_for_missing_semicolon ($$.t); }
        | ENUM identifier
                { $$.t = xref_tag (enum_type_node, $2, 1); 
@@ -2166,8 +2204,10 @@ structsp:
                  else
                    {
                      $$.t = $1.t;
-                     /* struct B: public A; is not accepted by the WP grammar.  */
-                     if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
+                     /* struct B: public A; is not accepted by the standard grammar.  */
+                     if (CLASS_TYPE_P ($$.t)
+                         && TYPE_BINFO_BASETYPES ($$.t) 
+                         && !COMPLETE_TYPE_P ($$.t)
                          && ! TYPE_BEING_DEFINED ($$.t))
                        cp_error ("base clause without member specification for `%#T'",
                                  $$.t);
@@ -2341,7 +2381,12 @@ base_class:
 
 base_class.1:
          typename_sub
-               { if ($$ != error_mark_node) $$ = TYPE_MAIN_DECL ($1); }
+               { if ($$ == error_mark_node)
+                   ;
+                  else if (!TYPE_P ($$))
+                   $$ = error_mark_node;
+                 else 
+                   $$ = TYPE_MAIN_DECL ($1); }
        | nonnested_type
        ;
 
@@ -2467,7 +2512,7 @@ component_decl_1:
        | declmods notype_components
                { 
                  if (!$2)
-                   grok_x_components ($1);
+                   grok_x_components ($1.t);
                  $$ = NULL_TREE; 
                }
        | notype_declarator maybeasm maybe_attribute maybe_init
@@ -2491,7 +2536,7 @@ component_decl_1:
           parmlist? */
        | declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
                { tree specs, attrs;
-                 split_specs_attrs ($1, &specs, &attrs);
+                 split_specs_attrs ($1.t, &specs, &attrs);
                  $$ = grokfield ($2, specs, $5, $3,
                                  build_tree_list ($4, attrs)); }
        | component_constructor_declarator maybeasm maybe_attribute maybe_init
@@ -2554,71 +2599,47 @@ component_declarator:
 
 after_type_component_declarator0:
          after_type_declarator maybeasm maybe_attribute maybe_init
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokfield ($$, current_declspecs, $4, $2,
-                                 build_tree_list ($3, prefix_attributes)); }
+               { $$ = parse_field0 ($1, $<ftype>0.t, $<ftype>0.lookups,
+                                    $3, $2, $4); }
        | TYPENAME ':' expr_no_commas maybe_attribute
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokbitfield ($$, current_declspecs, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = parse_bitfield0 ($1, $<ftype>0.t, $<ftype>0.lookups,
+                                       $4, $3); }
        ;
 
 notype_component_declarator0:
          notype_declarator maybeasm maybe_attribute maybe_init
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokfield ($$, current_declspecs, $4, $2,
-                                 build_tree_list ($3, prefix_attributes)); }
+               { $$ = parse_field0 ($1, $<ftype>0.t, $<ftype>0.lookups,
+                                    $3, $2, $4); }
        | constructor_declarator maybeasm maybe_attribute maybe_init
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokfield ($$, current_declspecs, $4, $2,
-                                 build_tree_list ($3, prefix_attributes)); }
+               { $$ = parse_field0 ($1, $<ftype>0.t, $<ftype>0.lookups,
+                                    $3, $2, $4); }
        | IDENTIFIER ':' expr_no_commas maybe_attribute
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokbitfield ($$, current_declspecs, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = parse_bitfield0 ($1, $<ftype>0.t, $<ftype>0.lookups,
+                                       $4, $3); }
        | ':' expr_no_commas maybe_attribute
-               { split_specs_attrs ($<ttype>0, &current_declspecs,
-                                    &prefix_attributes);
-                 $<ttype>0 = current_declspecs;
-                 $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
-                 cplus_decl_attributes ($$, $3, prefix_attributes); }
+               { $$ = parse_bitfield0 (NULL_TREE, $<ftype>0.t,
+                                       $<ftype>0.lookups, $3, $2); }
        ;
 
 after_type_component_declarator:
          after_type_declarator maybeasm maybe_attribute maybe_init
-               { $$ = grokfield ($$, current_declspecs, $4, $2,
-                                 build_tree_list ($3, prefix_attributes)); }
+               { $$ = parse_field ($1, $3, $2, $4); }
        | TYPENAME ':' expr_no_commas maybe_attribute
-               { $$ = grokbitfield ($$, current_declspecs, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = parse_bitfield ($1, $4, $3); }
        ;
 
 notype_component_declarator:
          notype_declarator maybeasm maybe_attribute maybe_init
-               { $$ = grokfield ($$, current_declspecs, $4, $2,
-                                 build_tree_list ($3, prefix_attributes)); }
+               { $$ = parse_field ($1, $3, $2, $4); }
        | IDENTIFIER ':' expr_no_commas maybe_attribute
-               { $$ = grokbitfield ($$, current_declspecs, $3);
-                 cplus_decl_attributes ($$, $4, prefix_attributes); }
+               { $$ = parse_bitfield ($1, $4, $3); }
        | ':' expr_no_commas maybe_attribute
-               { $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
-                 cplus_decl_attributes ($$, $3, prefix_attributes); }
+               { $$ = parse_bitfield (NULL_TREE, $3, $2); }
        ;
 
 enumlist_opt:
          enumlist maybecomma_warn
        | maybecomma_warn
-         { $$ = NULL_TREE; }
        ;
 
 /* We chain the enumerators in reverse order.
@@ -2628,17 +2649,16 @@ enumlist_opt:
 enumlist:
          enumerator
        | enumlist ',' enumerator
-               { TREE_CHAIN ($3) = $$; $$ = $3; }
        ;
 
 enumerator:
          identifier
-               { $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
+               { build_enumerator ($1, NULL_TREE, current_enum_type); }
        | identifier '=' expr_no_commas
-               { $$ = build_enumerator ($$, $3, current_enum_type); }
+               { build_enumerator ($1, $3, current_enum_type); }
        ;
 
-/* ANSI new-type-id (5.3.4) */
+/* ISO new-type-id (5.3.4) */
 new_type_id:
          type_specifier_seq new_declarator
                { $$.t = build_decl_list ($1.t, $2); 
@@ -2647,16 +2667,14 @@ new_type_id:
                { $$.t = build_decl_list ($1.t, NULL_TREE); 
                  $$.new_type_flag = $1.new_type_flag; }
        /* GNU extension to allow arrays of arbitrary types with
-          non-constant dimension.  For the use of begin_new_placement
-          here, see the comments in unary_expr above.  */
-       | '(' .begin_new_placement type_id .finish_new_placement
-             '[' expr ']'
+          non-constant dimension.  */
+       | '(' type_id ')' '[' expr ']'
                {
                  if (pedantic)
-                   pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
-                 $$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($3.t), $6);
-                 $$.t = build_decl_list (TREE_PURPOSE ($3.t), $$.t);
-                 $$.new_type_flag = $3.new_type_flag;
+                   pedwarn ("ISO C++ forbids array dimensions with parenthesized type in new");
+                 $$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($2.t), $5);
+                 $$.t = build_decl_list (TREE_PURPOSE ($2.t), $$.t);
+                 $$.new_type_flag = $2.new_type_flag;
                }
        ;
 
@@ -2679,26 +2697,16 @@ nonempty_cv_qualifiers:
 /* These rules must follow the rules for function declarations
    and component declarations.  That way, longer rules are preferred.  */
 
-suspend_mom:
-         /* empty */
-               { $<itype>$ = suspend_momentary (); } 
-
-/* An expression which will not live on the momentary obstack.  */
-nonmomentary_expr:
-         suspend_mom expr
-               { resume_momentary ((int) $<itype>1); $$ = $2; }
-       ;
-
 /* An expression which will not live on the momentary obstack.  */
 maybe_parmlist:
-         suspend_mom '(' nonnull_exprlist ')'
-               { resume_momentary ((int) $<itype>1); $$ = $3; }
-       | suspend_mom '(' parmlist ')'
-               { resume_momentary ((int) $<itype>1); $$ = $3; }
-       | suspend_mom LEFT_RIGHT
-               { resume_momentary ((int) $<itype>1); $$ = empty_parms (); }
-       | suspend_mom '(' error ')'
-               { resume_momentary ((int) $<itype>1); $$ = NULL_TREE; }
+         '(' nonnull_exprlist ')'
+               { $$ = $2; }
+       | '(' parmlist ')'
+               { $$ = $2; }
+       | LEFT_RIGHT
+               { $$ = empty_parms (); }
+       | '(' error ')'
+               { $$ = NULL_TREE; }
        ;
 
 /* A declarator that is allowed only after an explicit typespec.  */
@@ -2733,7 +2741,7 @@ after_type_declarator:
 direct_after_type_declarator:
          direct_after_type_declarator maybe_parmlist cv_qualifiers exception_specification_opt  %prec '.'
                { $$ = make_call_declarator ($$, $2, $3, $4); }
-       | direct_after_type_declarator '[' nonmomentary_expr ']'
+       | direct_after_type_declarator '[' expr ']'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
        | direct_after_type_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
@@ -2829,7 +2837,7 @@ complex_direct_notype_declarator:
                { $$ = make_call_declarator ($$, $2, $3, $4); }
        | '(' complex_notype_declarator ')'
                { $$ = $2; }
-       | direct_notype_declarator '[' nonmomentary_expr ']'
+       | direct_notype_declarator '[' expr ']'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
        | direct_notype_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
@@ -2874,6 +2882,7 @@ functional_cast:
        | typespec fcast_or_absdcl  %prec EMPTY
                { $$ = reparse_absdcl_as_expr ($1.t, $2); }
        ;
+
 type_name:
          TYPENAME
        | SELFNAME
@@ -2885,7 +2894,8 @@ nested_name_specifier:
        | nested_name_specifier nested_name_specifier_1
                { $$ = $2; }
        | nested_name_specifier TEMPLATE explicit_template_type SCOPE
-               { got_scope = $$ = make_typename_type ($1, $3); }
+                { got_scope = $$ 
+                   = make_typename_type ($1, $3, /*complain=*/1); }
        ;
 
 /* Why the @#$%^& do type_name and notype_identifier need to be expanded
@@ -2936,8 +2946,8 @@ typename_sub:
 typename_sub0:
          typename_sub1 identifier %prec EMPTY
                {
-                 if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
-                   $$ = make_typename_type ($1, $2);
+                 if (TYPE_P ($1))
+                   $$ = make_typename_type ($1, $2, /*complain=*/1);
                  else if (TREE_CODE ($2) == IDENTIFIER_NODE)
                    cp_error ("`%T' is not a class or namespace", $2);
                  else
@@ -2950,9 +2960,9 @@ typename_sub0:
        | typename_sub1 template_type %prec EMPTY
                { $$ = TREE_TYPE ($2); }
        | typename_sub1 explicit_template_type %prec EMPTY
-               { $$ = make_typename_type ($1, $2); }
+                { $$ = make_typename_type ($1, $2, /*complain=*/1); }
        | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
-               { $$ = make_typename_type ($1, $3); }
+                { $$ = make_typename_type ($1, $3, /*complain=*/1); }
        ;
 
 typename_sub1:
@@ -2963,8 +2973,8 @@ typename_sub1:
                }
        | typename_sub1 typename_sub2
                {
-                 if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
-                   $$ = make_typename_type ($1, $2);
+                 if (TYPE_P ($1))
+                   $$ = make_typename_type ($1, $2, /*complain=*/1);
                  else if (TREE_CODE ($2) == IDENTIFIER_NODE)
                    cp_error ("`%T' is not a class or namespace", $2);
                  else
@@ -2975,9 +2985,11 @@ typename_sub1:
                    }
                }
        | typename_sub1 explicit_template_type SCOPE
-               { got_scope = $$ = make_typename_type ($1, $2); }
+                { got_scope = $$ 
+                   = make_typename_type ($1, $2, /*complain=*/1); }
        | typename_sub1 TEMPLATE explicit_template_type SCOPE
-               { got_scope = $$ = make_typename_type ($1, $3); }
+                { got_scope = $$ 
+                   = make_typename_type ($1, $3, /*complain=*/1); }
        ;
 
 typename_sub2:
@@ -3044,7 +3056,7 @@ global_scope:
                { got_scope = void_type_node; }
        ;
 
-/* ANSI new-declarator (5.3.4) */
+/* ISO new-declarator (5.3.4) */
 new_declarator:
          '*' cv_qualifiers new_declarator
                { $$ = make_pointer_declarator ($2, $3); }
@@ -3065,11 +3077,11 @@ new_declarator:
        | direct_new_declarator  %prec EMPTY
        ;
 
-/* ANSI direct-new-declarator (5.3.4) */
+/* ISO direct-new-declarator (5.3.4) */
 direct_new_declarator:
          '[' expr ']'
                { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
-       | direct_new_declarator '[' nonmomentary_expr ']'
+       | direct_new_declarator '[' expr ']'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
        ;
 
@@ -3083,7 +3095,7 @@ absdcl_intern:
                }
        ;
        
-/* ANSI abstract-declarator (8.1) */
+/* ISO abstract-declarator (8.1) */
 absdcl:
          '*' nonempty_cv_qualifiers absdcl_intern
                { $$ = make_pointer_declarator ($2.t, $3); }
@@ -3112,7 +3124,7 @@ absdcl:
        | direct_abstract_declarator  %prec EMPTY
        ;
 
-/* ANSI direct-abstract-declarator (8.1) */
+/* ISO direct-abstract-declarator (8.1) */
 direct_abstract_declarator:
          '(' absdcl_intern ')'
                { $$ = $2; }
@@ -3121,7 +3133,7 @@ direct_abstract_declarator:
                { $$ = make_call_declarator ($$, $3, $5, $6); }
        | direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt  %prec '.'
                { $$ = make_call_declarator ($$, empty_parms (), $3, $4); }
-       | direct_abstract_declarator '[' nonmomentary_expr ']'  %prec '.'
+       | direct_abstract_declarator '[' expr ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
        | direct_abstract_declarator '[' ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
@@ -3131,7 +3143,7 @@ direct_abstract_declarator:
                { set_quals_and_spec ($$, $2, $3); }
        | fcast_or_absdcl cv_qualifiers exception_specification_opt  %prec '.'
                { set_quals_and_spec ($$, $2, $3); }
-       | '[' nonmomentary_expr ']'  %prec '.'
+       | '[' expr ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
        | '[' ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, NULL_TREE, NULL_TREE); }
@@ -3158,7 +3170,7 @@ maybe_label_decls:
          /* empty */
        | label_decls
                { if (pedantic)
-                   pedwarn ("ANSI C++ forbids label declarations"); }
+                   pedwarn ("ISO C++ forbids label declarations"); }
        ;
 
 label_decls:
@@ -3260,11 +3272,11 @@ simple_stmt:
          already_scoped_stmt
                 { finish_for_stmt ($9, $<ttype>2); }
        | SWITCH 
-                { begin_switch_stmt (); }
+                { $<ttype>$ = begin_switch_stmt (); }
            '(' condition ')'
-                { $<ttype>$ = finish_switch_cond ($4); }
+                { finish_switch_cond ($4, $<ttype>2); }
          implicitly_scoped_stmt
-                { finish_switch_stmt ($4, $<ttype>6); }
+                { finish_switch_stmt ($4, $<ttype>2); }
        | CASE expr_no_commas ':'
                 { finish_case_label ($2, NULL_TREE); }
          stmt
@@ -3296,24 +3308,30 @@ simple_stmt:
        /* This is the case with input operands as well.  */
        | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';'
                { finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
+       | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ')' ';'
+               { finish_asm_stmt ($2, $4, NULL_TREE, $6, NULL_TREE); }
        /* This is the case with clobbered registers as well.  */
        | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
          asm_operands ':' asm_clobbers ')' ';'
                { finish_asm_stmt ($2, $4, $6, $8, $10); }
+       | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ':'
+         asm_clobbers ')' ';'
+               { finish_asm_stmt ($2, $4, NULL_TREE, $6, $8); }
+       | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands SCOPE
+         asm_clobbers ')' ';'
+               { finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
        | GOTO '*' expr ';'
                 { 
                  if (pedantic)
-                   pedwarn ("ANSI C++ forbids computed gotos");
+                   pedwarn ("ISO C++ forbids computed gotos");
                  finish_goto_stmt ($3);
                }
        | GOTO identifier ';'
                 { finish_goto_stmt ($2); }
        | label_colon stmt
-               { finish_stmt (); }
        | label_colon '}'
                { error ("label must be followed by statement");
-                 yyungetc ('}', 0);
-                 finish_stmt (); }
+                 yyungetc ('}', 0); }
        | ';'
                { finish_stmt (); }
        | try_block
@@ -3353,9 +3371,9 @@ handler:
          CATCH
                 { $<ttype>$ = begin_handler(); }
           handler_args
-                { finish_handler_parms ($<ttype>2); }
+                { $<ttype>$ = finish_handler_parms ($3, $<ttype>2); }
          compstmt
-                { finish_handler ($<ttype>2); }
+                { finish_handler ($<ttype>4, $<ttype>2); }
        ;
 
 type_specifier_seq:
@@ -3365,7 +3383,7 @@ type_specifier_seq:
 
 handler_args:
          '(' ELLIPSIS ')'
-               { expand_start_catch_block (NULL_TREE); }
+               { $$ = NULL_TREE; }
        /* This doesn't allow reference parameters, the below does.
        | '(' type_specifier_seq absdcl ')'
                { check_for_new_type ("inside exception declarations", $2);
@@ -3383,8 +3401,8 @@ handler_args:
        | '(' parm ')'
                { 
                  check_for_new_type ("inside exception declarations", $2);
-                 start_handler_parms (TREE_PURPOSE ($2.t),
-                                      TREE_VALUE ($2.t));
+                 $$ = start_handler_parms (TREE_PURPOSE ($2.t),
+                                           TREE_VALUE ($2.t));
                }
        ;
 
@@ -3405,7 +3423,7 @@ for.init.statement:
        | decl
        | '{' compstmtend
                { if (pedantic)
-                   pedwarn ("ANSI C++ forbids compound statements inside for initializations");
+                   pedwarn ("ISO C++ forbids compound statements inside for initializations");
                }
        ;
 
@@ -3413,10 +3431,8 @@ for.init.statement:
 
 maybe_cv_qualifier:
          /* empty */
-               { emit_line_note (input_filename, lineno);
-                 $$ = NULL_TREE; }
+               { $$ = NULL_TREE; }
        | CV_QUALIFIER
-               { emit_line_note (input_filename, lineno); }
        ;
 
 xexpr:
@@ -3570,7 +3586,7 @@ named_parm:
                  $$.t = build_tree_list (specs, NULL_TREE); 
                  $$.new_type_flag = $1.new_type_flag; }
        | declmods notype_declarator
-               { tree specs = strip_attrs ($1);
+               { tree specs = strip_attrs ($1.t);
                  $$.t = build_tree_list (specs, $2); 
                  $$.new_type_flag = 0; }
        ;