/* YACC parser for C++ syntax.
- Copyright (C) 1988, 89, 93, 94, 95, 1996 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.
#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 tree void_list_node;
extern struct obstack permanent_obstack;
extern int end_of_file;
/* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */
-static char *cond_stmt_keyword;
-
-static tree empty_parms PROTO((void));
+static const char *cond_stmt_keyword;
/* 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;
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, ¤t_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 (¤t_declspecs, 1);
+ ggc_add_tree_root (&prefix_attributes, 1);
+ ggc_add_tree_root (¤t_aggr, 1);
+ ggc_add_tree_root (¤t_enum_type, 1);
+}
%}
%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 */
/* 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 TYPEOF ALIGNOF
+%token BREAK CONTINUE RETURN_KEYWORD GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token SIGOF
%token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART
+%token REALPART IMAGPART VA_ARG
/* the reserved words... C++ extensions */
%token <ttype> AGGR
%left <code> POINTSAT_STAR DOT_STAR
%right <code> UNARY PLUSPLUS MINUSMINUS '~'
%left HYPERUNARY
-%left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
+%left <ttype> LEFT_RIGHT
%left <code> POINTSAT '.' '(' '['
%right SCOPE /* C++ extension */
%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
%type <ttype> compstmt implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator
+%type <ttype> notype_declarator_intern absdcl_intern
+%type <ttype> after_type_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
-
-%type <ttype> opt.component_decl_list component_decl_list
-%type <ttype> component_decl component_decl_1 components notype_components
-%type <ttype> component_declarator component_declarator0 self_reference
+%type <itype> components notype_components
+%type <ttype> component_decl component_decl_1
+%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 enumerator
%type <ttype> absdcl cv_qualifiers
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_declarator direct_new_declarator
%type <ttype> xexpr parmlist parms bad_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl
-%type <ttype> expr_or_declarator complex_notype_declarator
+%type <ttype> expr_or_declarator expr_or_declarator_intern
+%type <ttype> complex_notype_declarator
%type <ttype> notype_unqualified_id unqualified_id qualified_id
%type <ttype> template_id do_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
%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 <itype> ctor_initializer_opt
-%type <ttype> named_class_head named_class_head_sans_basetype
-%type <ttype> named_complex_class_head_sans_basetype
+%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
+%type <ftype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
-%type <ttype> class_head base_class_list
+%type <ttype> base_class_list
%type <ttype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1
%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
+%type <ttype> apparent_template_type
%type <ttype> template_type template_arg_list template_arg_list_opt
%type <ttype> template_arg
%type <ttype> condition xcond paren_cond_or_null
%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
%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 most recent one being defined. */
-static tree current_aggr;
-
/* 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, ¤t_declspecs, &prefix_attributes);
- if (current_declspecs
- && TREE_CODE (current_declspecs) != TREE_LIST)
- current_declspecs = get_decl_list (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
%%
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:
extension:
EXTENSION
- { $<itype>$ = pedantic;
+ { $$ = pedantic;
pedantic = 0; }
;
;
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 () && ! pseudo_global_level_p())
+ { if (! toplevel_bindings_p ())
pop_everything (); }
;
{ do_toplevel_using_decl ($1); }
| using_directive
| extension extdef
- { pedantic = $<itype>1; }
+ { pedantic = $1; }
;
namespace_alias:
{ if (pending_inlines) do_pending_inlines ();
pop_lang_context (); }
| extension template_extdef
- { pedantic = $<itype>1; }
+ { pedantic = $1; }
;
template_datadef:
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
- { }
+ { expand_body (finish_function (lineno, (int)$3)); }
| fn.def1 maybe_return_init error
{ }
;
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))
reduce/reduce conflict introduced by these rules. */
fn.def2:
declmods component_constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2);
+ { $$ = parse_method ($2, $1.t, $1.lookups);
rest_of_mdef:
if (! $$)
YYERROR1;
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| component_constructor_declarator
- { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; }
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ goto rest_of_mdef; }
| typed_declspecs declarator
- { tree specs = strip_attrs ($1.t);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| declmods notype_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| notype_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ goto rest_of_mdef; }
| declmods constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| constructor_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ goto rest_of_mdef; }
;
return_id:
- RETURN IDENTIFIER
+ RETURN_KEYWORD IDENTIFIER
{
if (! current_function_parms_stored)
store_parm_decls ();
return_init:
return_id maybe_init
- { store_return_init ($<ttype>$, $2); }
+ { finish_named_return_value ($<ttype>$, $2); }
| return_id '(' nonnull_exprlist ')'
- { store_return_init ($<ttype>$, $3); }
+ { finish_named_return_value ($<ttype>$, $3); }
| return_id LEFT_RIGHT
- { store_return_init ($<ttype>$, NULL_TREE); }
+ { finish_named_return_value ($<ttype>$, NULL_TREE); }
;
base_init:
if ($3 == 0)
error ("no base initializers given following ':'");
setup_vtbl_ptr ();
- /* Always keep the BLOCK node associated with the outermost
- pair of curley braces of a function. These are needed
- for correct operation of dwarfout.c. */
- keep_next_level ();
}
;
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))
| typename_sub LEFT_RIGHT
{ expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
void_type_node); }
+ | error
;
identifier:
| self_template_type
;
+apparent_template_type:
+ template_type
+ | identifier '<' template_arg_list_opt '>'
+ .finish_template_type
+ { $$ = $5; }
+
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
.finish_template_type
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 ')'
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 ')'
}
}
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);
- $$ = $<ttype>6;
+ 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", $$);
}
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
;
/* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY
{ $$ = $2;
- pedantic = $<itype>1; }
+ pedantic = $1; }
| '*' cast_expr %prec UNARY
{ $$ = build_x_indirect_ref ($2, "unary *"); }
| '&' cast_expr %prec UNARY
/* 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); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
- { $$ = c_sizeof (groktypename ($3.t)); }
+ { $$ = c_sizeof (groktypename ($3.t));
+ check_for_new_type ("sizeof", $3); }
| ALIGNOF unary_expr %prec UNARY
{ $$ = grok_alignof ($2); }
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
| 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); }
{ $$ = build_x_unary_op (REALPART_EXPR, $2); }
| IMAGPART cast_expr %prec UNARY
{ $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
+ | VA_ARG '(' expr_no_commas ',' type_id ')'
+ { $$ = 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:
| '=' 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;
}
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;
;
do_id:
- { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
+ {
+ /* If lastiddecl is a TREE_LIST, it's a baselink, which
+ means that we're in an expression like S::f<int>, so
+ don't do_identifier; we only do that for unqualified
+ identifiers. */
+ if (lastiddecl && TREE_CODE (lastiddecl) != TREE_LIST)
+ $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
+ else
+ $$ = $<ttype>-1;
+ }
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
| SELFNAME
;
+expr_or_declarator_intern:
+ expr_or_declarator
+ | attributes expr_or_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
expr_or_declarator:
notype_unqualified_id
- | '*' expr_or_declarator %prec UNARY
+ | '*' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
- | '&' expr_or_declarator %prec UNARY
+ | '&' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $$ = $2; }
;
to the Koenig lookup shift in primary, below. I hate yacc. */
| notype_unqualified_id %prec '('
| notype_template_declarator
- | '(' expr_or_declarator ')'
- { $$ = finish_decl_parsing ($2); }
+ | '(' expr_or_declarator_intern ')'
+ { $$ = finish_decl_parsing ($2); }
;
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. */
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); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $2 = reparse_decl_as_expr (NULL_TREE, $2);
$$ = finish_parenthesized_expr ($2); }
| '(' error ')'
{ $$ = error_mark_node; }
| '('
- { if (current_function_decl == 0)
+ { tree scope = current_scope ();
+ if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
{
error ("braced-group within expression allowed only inside a function");
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. */
{ $$ = finish_this_expr (); }
| CV_QUALIFIER '(' nonnull_exprlist ')'
{
- tree type = NULL_TREE;
- tree id = $$;
+ /* This is a C cast in C++'s `functional' notation
+ using the "implicit int" extension so that:
+ `const (3)' is equivalent to `const int (3)'. */
+ tree type;
- /* This is a C cast in C++'s `functional' notation. */
- if ($3 == error_mark_node)
- {
- $$ = error_mark_node;
- break;
- }
-#if 0
- if ($3 == NULL_TREE)
- {
- error ("cannot cast null list to type `%s'",
- IDENTIFIER_POINTER (TYPE_NAME (id)));
- $$ = error_mark_node;
- break;
- }
-#endif
-#if 0
- /* type is not set! (mrs) */
- if (type == error_mark_node)
- $$ = error_mark_node;
- else
-#endif
- {
- if (id == ridpointers[(int) RID_CONST])
- type = build_type_variant (integer_type_node, 1, 0);
- else if (id == ridpointers[(int) RID_VOLATILE])
- type = build_type_variant (integer_type_node, 0, 1);
-#if 0
- /* should not be able to get here (mrs) */
- else if (id == ridpointers[(int) RID_FRIEND])
- {
- error ("cannot cast expression to `friend' type");
- $$ = error_mark_node;
- break;
- }
-#endif
- else my_friendly_abort (79);
- $$ = 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 ')'
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);
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_globally_qualified_member_call_expr ($1, $3); }
+ { $$ = finish_qualified_call_expr ($1, $3); }
| overqualified_id LEFT_RIGHT
- { $$ = finish_globally_qualified_member_call_expr ($1, NULL_TREE); }
+ { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
{ $$ = 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 ')'
$<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); }
if (! current_function_parms_stored)
store_parm_decls ();
setup_vtbl_ptr ();
- /* Always keep the BLOCK node associated with the outermost
- pair of curley braces of a function. These are needed
- for correct operation of dwarfout.c. */
- keep_next_level ();
}
;
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);
| declmods ';'
{ warning ("empty declaration"); }
| extension decl
- { pedantic = $<itype>1; }
+ { pedantic = $1; }
;
/* Any kind of declarator (thus, all declarators allowed
NULL_TREE); }
;
-/* ANSI type-id (8.1) */
+/* ISO type-id (8.1) */
type_id:
typed_typespecs absdcl
{ $$.t = build_decl_list ($1.t, $2);
{ $$.t = build_decl_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
- { $$.t = build_decl_list (get_decl_list ($1.t), $2);
+ { $$.t = build_decl_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_typespecs %prec EMPTY
{ $$.t = build_decl_list ($1.t, NULL_TREE);
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);
{ $$.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; }
;
to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
+/* We use hash_tree_cons for lists of typeless declspecs so that they end
+ up on a persistent obstack. Otherwise, they could appear at the
+ beginning of something like
+
+ static const struct { int foo () { } } b;
+
+ and would be discarded after we finish compiling foo. We don't need to
+ worry once we see a type. */
+
declmods:
nonempty_cv_qualifiers %prec EMPTY
- { $$ = $1.t; TREE_STATIC ($$) = 1; }
+ { $$.lookups = NULL_TREE; TREE_STATIC ($$.t) = 1; }
| SCSPEC
- { $$ = IDENTIFIER_AS_LIST ($$); }
+ {
+ $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
+ $$.new_type_flag = 0; $$.lookups = NULL_TREE;
+ }
| declmods CV_QUALIFIER
- { $$ = decl_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));
- $$ = decl_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
- { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
- | attributes
- { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
+ { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t); }
+ | attributes %prec EMPTY
+ {
+ $$.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
typed_typespecs:
typespec %prec EMPTY
- { $$.t = get_decl_list ($1.t);
+ { $$.t = build_decl_list (NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
$$.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:
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 = TREE_TYPE ($3);
- $$.new_type_flag = 0; }
+ { $$.t = finish_typeof ($3);
+ $$.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");
| 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");
initdecls:
initdcl0
| initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
notype_initdecls:
notype_initdcl0
| notype_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
nomods_initdecls:
nomods_initdcl0
| nomods_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
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.
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:
notype_declarator maybeasm
{ /* Set things up as initdcl0_innards expects. */
- $<ttype>$ = $1;
+ $<ttype>2 = $1;
$1 = NULL_TREE; }
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
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, 1);
+ { 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, nested);
+ expand_body (finish_function (lineno, (int)$3 | 2));
process_next_inline ($1);
}
| fn.defpen maybe_return_init function_try_block
- { process_next_inline ($1); }
+ {
+ 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:
structsp:
ENUM identifier '{'
- { $<itype>3 = suspend_momentary ();
- $<ttype>$ = start_enum ($2); }
- enumlist maybecomma_warn '}'
- { TYPE_VALUES ($<ttype>4) = $5;
- $$.t = finish_enum ($<ttype>4);
- $$.new_type_flag = 1;
- resume_momentary ((int) $<itype>3);
- check_for_missing_semicolon ($<ttype>4); }
- | ENUM identifier '{' '}'
- { $$.t = finish_enum (start_enum ($2));
+ { $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum ($2); }
+ enumlist_opt '}'
+ { $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
+ current_enum_type = $<ttype>4;
check_for_missing_semicolon ($$.t); }
| ENUM '{'
- { $<itype>2 = suspend_momentary ();
- $<ttype>$ = start_enum (make_anon_name ()); }
- enumlist maybecomma_warn '}'
- { TYPE_VALUES ($<ttype>3) = $4;
- $$.t = finish_enum ($<ttype>3);
- resume_momentary ((int) $<itype>1);
- check_for_missing_semicolon ($<ttype>3);
- $$.new_type_flag = 1; }
- | ENUM '{' '}'
- { $$.t = finish_enum (start_enum (make_anon_name()));
+ { $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum (make_anon_name ()); }
+ enumlist_opt '}'
+ { $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
+ current_enum_type = $<ttype>3;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
{ $$.t = xref_tag (enum_type_node, $2, 1);
if (!processing_template_decl)
cp_pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
- | class_head left_curly
+ | class_head '{'
+ { $1.t = begin_class_definition ($1.t); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
yychar = YYLEX;
semi = yychar == ';';
- $<ttype>$ = finish_class_definition ($1, $3, $5, semi);
+ $<ttype>$ = finish_class_definition ($1.t, $6, semi,
+ $1.new_type_flag);
}
pending_defargs
- { finish_default_args (); }
+ {
+ begin_inline_definitions ();
+ }
pending_inlines
- { $$.t = $<ttype>6;
+ {
+ finish_inline_definitions ();
+ $$.t = $<ttype>7;
$$.new_type_flag = 1;
- begin_inline_definitions (); }
+ }
| class_head %prec EMPTY
{
+ if ($1.new_type_flag && $1.t != error_mark_node)
+ pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
$$.new_type_flag = 0;
- if (TYPE_BINFO ($1) == NULL_TREE)
+ if ($1.t == error_mark_node)
+ $$.t = $1.t;
+ else if (TYPE_BINFO ($1.t) == NULL_TREE)
{
- cp_error ("%T is not a class type", $1);
+ cp_error ("%T is not a class type", $1.t);
$$.t = error_mark_node;
}
else
{
- $$.t = $1;
- /* struct B: public A; is not accepted by the WP grammar. */
- if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
+ $$.t = $1.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);
named_class_head_sans_basetype:
aggr identifier
- { current_aggr = $$; $$ = $2; }
+ {
+ current_aggr = $1;
+ $$ = $2;
+ }
;
named_class_head_sans_basetype_defn:
aggr nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $2, $3);
+ $$.t = handle_class_head ($1, $2, $3);
+ $$.new_type_flag = 1;
}
| aggr global_scope nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $3, $4);
+ $$.t = handle_class_head ($1, $3, $4);
+ $$.new_type_flag = 1;
}
| aggr global_scope identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, NULL_TREE, $3);
+ $$.t = handle_class_head ($1, NULL_TREE, $3);
+ $$.new_type_flag = 1;
+ }
+ | aggr apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $2;
+ $$.new_type_flag = 0;
+ }
+ | aggr nested_name_specifier apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $3;
+ if (CP_DECL_CONTEXT ($$.t))
+ push_scope (CP_DECL_CONTEXT ($$.t));
+ $$.new_type_flag = 1;
}
- | aggr template_type
- { current_aggr = $$; $$ = $2; }
- | aggr nested_name_specifier template_type
- { current_aggr = $$; $$ = $3; }
- ;
-
-do_xref_defn:
- /* empty */ %prec EMPTY
- { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, 0); }
;
named_class_head:
named_class_head_sans_basetype %prec EMPTY
- { $$ = xref_tag (current_aggr, $1, 1); }
- | named_class_head_sans_basetype_defn do_xref_defn
+ {
+ $$.t = xref_tag (current_aggr, $1, 1);
+ $$.new_type_flag = 0;
+ }
+ | named_class_head_sans_basetype_defn
+ { $<ttype>$ = xref_tag (current_aggr, $1, 0); }
+ /* Class name is unqualified, so we look for base classes
+ in the current scope. */
maybe_base_class_list %prec EMPTY
{
- $$ = $<ttype>2;
+ $$.t = $<ttype>2;
+ $$.new_type_flag = 0;
if ($3)
xref_basetypes (current_aggr, $1, $<ttype>2, $3);
}
- | named_complex_class_head_sans_basetype maybe_base_class_list
+ | named_complex_class_head_sans_basetype
+ maybe_base_class_list
{
- $$ = TREE_TYPE ($1);
- if (TREE_INT_CST_LOW (current_aggr) == union_type
- && TREE_CODE ($$) != UNION_TYPE)
- cp_pedwarn ("`union' tag used in declaring `%#T'", $$);
- else if (TREE_CODE ($$) == UNION_TYPE
- && TREE_INT_CST_LOW (current_aggr) != union_type)
- cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
- if ($2)
+ if ($1.t != error_mark_node)
{
- maybe_process_partial_specialization ($$);
- xref_basetypes (current_aggr, $1, $$, $2);
+ $$.t = TREE_TYPE ($1.t);
+ $$.new_type_flag = $1.new_type_flag;
+ if (current_aggr == union_type_node
+ && TREE_CODE ($$.t) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'",
+ $$.t);
+ else if (TREE_CODE ($$.t) == UNION_TYPE
+ && current_aggr != union_type_node)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$.t) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key; deal. */
+ CLASSTYPE_DECLARED_CLASS ($$.t)
+ = (current_aggr == class_type_node);
+ if ($2)
+ {
+ maybe_process_partial_specialization ($$.t);
+ xref_basetypes (current_aggr, $1.t, $$.t, $2);
+ }
}
}
;
yyungetc ('{', 1); }
;
+/* The tree output of this nonterminal a declarationf or the type
+ named. If NEW_TYPE_FLAG is set, then the name used in this
+ class-head was explicitly qualified, e.g.: `struct X::Y'. We have
+ already called push_scope for X. */
class_head:
unnamed_class_head
+ {
+ $$.t = $1;
+ $$.new_type_flag = 0;
+ }
| named_class_head
;
base_class:
base_class.1
- { $$ = finish_base_specifier (access_default_node, $1,
- current_aggr
- == signature_type_node); }
+ { $$ = finish_base_specifier (access_default_node, $1); }
| base_class_access_list see_typename base_class.1
- { $$ = finish_base_specifier ($1, $3,
- current_aggr
- == signature_type_node); }
+ { $$ = finish_base_specifier ($1, $3); }
;
base_class.1:
typename_sub
- { $$ = TYPE_MAIN_DECL ($1); }
+ { if ($$ == error_mark_node)
+ ;
+ else if (!TYPE_P ($$))
+ $$ = error_mark_node;
+ else
+ $$ = TYPE_MAIN_DECL ($1); }
| nonnested_type
- | SIGOF '(' expr ')'
- {
- if (current_aggr == signature_type_node)
- {
- if (IS_AGGR_TYPE (TREE_TYPE ($3)))
- {
- sorry ("`sigof' as base signature specifier");
- $$ = TREE_TYPE ($3);
- }
- else
- {
- error ("`sigof' applied to non-aggregate expression");
- $$ = error_mark_node;
- }
- }
- else
- {
- error ("`sigof' in struct or class declaration");
- $$ = error_mark_node;
- }
- }
- | SIGOF '(' type_id ')'
- {
- if (current_aggr == signature_type_node)
- {
- if (IS_AGGR_TYPE (groktypename ($3.t)))
- {
- sorry ("`sigof' as base signature specifier");
- $$ = groktypename ($3.t);
- }
- else
- {
- error ("`sigof' applied to non-aggregate expression");
- $$ = error_mark_node;
- }
- }
- else
- {
- error ("`sigof' in struct or class declaration");
- $$ = error_mark_node;
- }
- }
;
base_class_access_list:
}
;
-left_curly:
- '{'
- { $<ttype>0 = begin_class_definition ($<ttype>0); }
- ;
-
-self_reference:
- /* empty */
- {
- $$ = build_self_reference ();
- }
- ;
-
opt.component_decl_list:
- self_reference
- { if ($$) $$ = build_tree_list (access_public_node, $$); }
- | self_reference component_decl_list
- {
- if (current_aggr == signature_type_node)
- $$ = build_tree_list (access_public_node, $2);
- else
- $$ = build_tree_list (access_default_node, $2);
- if ($1) $$ = tree_cons (access_public_node, $1, $$);
- }
- | opt.component_decl_list VISSPEC ':' component_decl_list
- {
- tree visspec = $2;
+ | component_decl_list
+ | opt.component_decl_list access_specifier component_decl_list
+ | opt.component_decl_list access_specifier
+ ;
- if (current_aggr == signature_type_node)
- {
- error ("access specifier not allowed in signature");
- visspec = access_public_node;
- }
- $$ = chainon ($$, build_tree_list (visspec, $4));
- }
- | opt.component_decl_list VISSPEC ':'
- {
- if (current_aggr == signature_type_node)
- error ("access specifier not allowed in signature");
- }
+access_specifier:
+ VISSPEC ':'
+ {
+ current_access_specifier = $1;
+ }
;
/* Note: we no longer warn about the semicolon after a component_decl_list.
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
- { if ($$ == void_type_node) $$ = NULL_TREE;
+ {
+ finish_member_declaration ($1);
}
| component_decl_list component_decl
- { /* In pushdecl, we created a reverse list of names
- in this binding level. Make sure that the chain
- of what we're trying to add isn't the item itself
- (which can happen with what pushdecl's doing). */
- if ($2 != NULL_TREE && $2 != void_type_node)
- {
- if (TREE_CHAIN ($2) != $$)
- $$ = chainon ($$, $2);
- else
- $$ = $2;
- }
+ {
+ finish_member_declaration ($2);
}
;
component_decl:
component_decl_1 ';'
- { }
| component_decl_1 '}'
{ error ("missing ';' before right brace");
yyungetc ('}', 0); }
{ $$ = finish_method ($$); }
| fn.def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 RETURN /* base_init compstmt */
+ | fn.def2 RETURN_KEYWORD /* base_init compstmt */
{ $$ = finish_method ($$); }
| fn.def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); }
{ $$ = NULL_TREE; }
| extension component_decl
{ $$ = $2;
- pedantic = $<itype>1; }
+ pedantic = $1; }
| template_header component_decl
- { $$ = finish_member_template_decl ($1, $2); }
+ {
+ if ($2)
+ $$ = finish_member_template_decl ($2);
+ else
+ /* The component was already processed. */
+ $$ = NULL_TREE;
+
+ finish_template_decl ($1);
+ }
| template_header typed_declspecs ';'
- { $$ = finish_member_class_template ($1, $2.t); }
+ {
+ $$ = finish_member_class_template ($2.t);
+ finish_template_decl ($1);
+ }
;
component_decl_1:
speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */
typed_declspecs components
- { $$ = grok_x_components ($1.t, $2); }
+ {
+ /* Most of the productions for component_decl only
+ allow the creation of one new member, so we call
+ finish_member_declaration in component_decl_list.
+ For this rule and the next, however, there can be
+ more than one member, e.g.:
+
+ int i, j;
+
+ and we need the first member to be fully
+ registered before the second is processed.
+ Therefore, the rules for components take care of
+ this processing. To avoid registering the
+ components more than once, we send NULL_TREE up
+ here; that lets finish_member_declaration know
+ that there is nothing to do. */
+ if (!$2)
+ grok_x_components ($1.t);
+ $$ = NULL_TREE;
+ }
| declmods notype_components
- { $$ = grok_x_components ($1, $2); }
+ {
+ if (!$2)
+ grok_x_components ($1.t);
+ $$ = NULL_TREE;
+ }
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
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
/* ??? Huh? ^^^ */
components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| components ',' component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
notype_components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| notype_component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| notype_components ',' notype_component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
after_type_component_declarator0:
after_type_declarator maybeasm maybe_attribute maybe_init
- { split_specs_attrs ($<ttype>0, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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
;
/* We chain the enumerators in reverse order.
enumlist:
enumerator
| enumlist ',' enumerator
- { TREE_CHAIN ($3) = $$; $$ = $3; }
;
enumerator:
identifier
- { $$ = build_enumerator ($$, NULL_TREE); }
+ { build_enumerator ($1, NULL_TREE, current_enum_type); }
| identifier '=' expr_no_commas
- { $$ = build_enumerator ($$, $3); }
+ { 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);
{ $$.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;
}
;
nonempty_cv_qualifiers:
CV_QUALIFIER
- { $$.t = IDENTIFIER_AS_LIST ($1);
+ { $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
- { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t);
+ { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
/* 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. */
+
+after_type_declarator_intern:
+ after_type_declarator
+ | attributes after_type_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
/* may all be followed by prec '.' */
after_type_declarator:
- '*' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' after_type_declarator %prec UNARY
+ | '*' after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' after_type_declarator %prec UNARY
+ | '&' after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers after_type_declarator
+ | ptr_to_mem cv_qualifiers after_type_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_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 '[' expr ']'
+ { $$ = build_parse_node (ARRAY_REF, $$, $3); }
+ | direct_after_type_declarator '[' ']'
+ { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
+ | '(' after_type_declarator_intern ')'
+ { $$ = $2; }
+ | nested_name_specifier type_name %prec EMPTY
+ { push_nested_class ($1, 3);
+ $$ = build_parse_node (SCOPE_REF, $$, $2);
+ TREE_COMPLEXITY ($$) = current_class_depth; }
+ | type_name %prec EMPTY
+ ;
+
nonnested_type:
type_name %prec EMPTY
{
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
$$ = lookup_name ($1, 1);
- if (current_class_type
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE ($1))
- {
- /* Remember that this name has been used in the class
- definition, as per [class.scope0] */
- pushdecl_class_level ($$);
- }
+ maybe_note_name_used_in_class ($1, $$);
}
else
$$ = $1;
{ $$ = get_type_decl ($2); }
;
-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 ']'
- { $$ = build_parse_node (ARRAY_REF, $$, $3); }
- | direct_after_type_declarator '[' ']'
- { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
- | '(' after_type_declarator ')'
- { $$ = $2; }
- | nested_name_specifier type_name %prec EMPTY
- { push_nested_class ($1, 3);
- $$ = build_parse_node (SCOPE_REF, $$, $2);
- TREE_COMPLEXITY ($$) = current_class_depth; }
- | type_name %prec EMPTY
- ;
-
/* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */
+notype_declarator_intern:
+ notype_declarator
+ | attributes notype_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' notype_declarator %prec UNARY
+ | '*' notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' notype_declarator %prec UNARY
+ | '&' notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
;
complex_notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
| '*' complex_notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' complex_notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
{ $$ = 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); }
functional_cast:
typespec '(' nonnull_exprlist ')'
{ $$ = build_functional_cast ($1.t, $3); }
- | typespec '(' expr_or_declarator ')'
+ | typespec '(' expr_or_declarator_intern ')'
{ $$ = reparse_decl_as_expr ($1.t, $3); }
| typespec fcast_or_absdcl %prec EMPTY
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
+
type_name:
TYPENAME
| SELFNAME
| 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
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
$$ = lastiddecl;
- /* Remember that this name has been used in the class
- definition, as per [class.scope0] */
- if (current_class_type
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE ($1))
- pushdecl_class_level ($$);
+ maybe_note_name_used_in_class ($1, $$);
}
- got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$));
+ got_scope = $$ =
+ complete_type (TYPE_MAIN_VARIANT (TREE_TYPE ($$)));
}
| SELFNAME SCOPE
{
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
| 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:
}
| 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
}
}
| 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:
{ 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); }
| 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); }
;
-/* ANSI abstract-declarator (8.1) */
+absdcl_intern:
+ absdcl
+ | attributes absdcl
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
+/* ISO abstract-declarator (8.1) */
absdcl:
- '*' nonempty_cv_qualifiers absdcl
+ '*' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '*' absdcl
+ | '*' absdcl_intern
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_pointer_declarator ($2.t, NULL_TREE); }
| '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
- | '&' nonempty_cv_qualifiers absdcl
+ | '&' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_reference_declarator ($2.t, $3); }
- | '&' absdcl
+ | '&' absdcl_intern
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_reference_declarator ($2.t, NULL_TREE); }
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | ptr_to_mem cv_qualifiers absdcl
+ | ptr_to_mem cv_qualifiers absdcl_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_abstract_declarator %prec EMPTY
;
-/* ANSI direct-abstract-declarator (8.1) */
+/* ISO direct-abstract-declarator (8.1) */
direct_abstract_declarator:
- '(' absdcl ')'
+ '(' absdcl_intern ')'
{ $$ = $2; }
/* `(typedef)1' is `int'. */
- | PAREN_STAR_PAREN
| direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
{ $$ = 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); }
{ 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); }
/* empty */
| label_decls
{ if (pedantic)
- pedwarn ("ANSI C++ forbids label declarations"); }
+ pedwarn ("ISO C++ forbids label declarations"); }
;
label_decls:
label_decl:
LABEL identifiers_or_typenames ';'
- { tree link;
- for (link = $2; link; link = TREE_CHAIN (link))
+ {
+ while ($2)
{
- tree label = shadow_label (TREE_VALUE (link));
- C_DECLARED_LABEL_FLAG (label) = 1;
- declare_nonlocal_label (label);
+ finish_label_decl (TREE_VALUE ($2));
+ $2 = TREE_CHAIN ($2);
}
}
;
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
{ finish_break_stmt (); }
| CONTINUE ';'
{ finish_continue_stmt (); }
- | RETURN ';'
+ | RETURN_KEYWORD ';'
{ finish_return_stmt (NULL_TREE); }
- | RETURN expr ';'
+ | RETURN_KEYWORD expr ';'
{ finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
{
/* 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
function_try_block:
TRY
- {
- if (! current_function_parms_stored)
- store_parm_decls ();
- expand_start_early_try_stmts ();
- }
+ { $<ttype>$ = begin_function_try_block (); }
ctor_initializer_opt compstmt
- {
- expand_start_all_catch ();
- }
+ { finish_function_try_block ($<ttype>2); }
handler_seq
{
- int nested = (hack_decl_function_context
- (current_function_decl) != NULL_TREE);
- expand_end_all_catch ();
- finish_function (lineno, (int)$3, nested);
+ finish_function_handler_sequence ($<ttype>2);
+ $$ = $3;
}
;
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:
handler_args:
'(' ELLIPSIS ')'
- { expand_start_catch_block (NULL_TREE, 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);
expand_start_catch_block ($2.t, $3); }
This allows reference parameters... */
| '(' parm ')'
- { check_for_new_type ("inside exception declarations", $2);
- expand_start_catch_block (TREE_PURPOSE ($2.t),
- TREE_VALUE ($2.t)); }
+ {
+ check_for_new_type ("inside exception declarations", $2);
+ $$ = start_handler_parms (TREE_PURPOSE ($2.t),
+ TREE_VALUE ($2.t));
+ }
;
label_colon:
IDENTIFIER ':'
- { tree label;
- do_label:
- label = define_label (input_filename, lineno, $1);
- if (label && ! minimal_parse_mode)
- expand_label (label);
- }
+ { finish_label_stmt ($1); }
| PTYPENAME ':'
- { goto do_label; }
+ { finish_label_stmt ($1); }
| TYPENAME ':'
- { goto do_label; }
+ { finish_label_stmt ($1); }
| SELFNAME ':'
- { goto do_label; }
+ { finish_label_stmt ($1); }
;
for.init.statement:
xexpr ';'
- { if ($1) cplus_expand_expr_stmt ($1); }
+ { finish_expr_stmt ($1); }
| decl
| '{' compstmtend
{ if (pedantic)
- pedwarn ("ANSI C++ forbids compound statements inside for initializations");
+ pedwarn ("ISO C++ forbids compound statements inside for initializations");
}
;
maybe_cv_qualifier:
/* empty */
- { emit_line_note (input_filename, lineno);
- $$ = NULL_TREE; }
+ { $$ = NULL_TREE; }
| CV_QUALIFIER
- { emit_line_note (input_filename, lineno); }
;
xexpr:
{ $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec declarator
- { $$.t = build_tree_list (get_decl_list ($1.t), $2);
+ { $$.t = build_tree_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
{ tree specs = strip_attrs ($1.t);
$$.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; }
;
| THROW '(' ansi_raise_identifiers ')' %prec EMPTY
{ $$ = $3; }
| THROW LEFT_RIGHT %prec EMPTY
- { $$ = build_decl_list (NULL_TREE, NULL_TREE); }
+ { $$ = empty_except_spec; }
;
ansi_raise_identifier:
type_id
- { $$ = build_decl_list (NULL_TREE, groktypename($1.t)); }
+ {
+ check_for_new_type ("exception specifier", $1);
+ $$ = groktypename ($1.t);
+ }
;
ansi_raise_identifiers:
ansi_raise_identifier
+ { $$ = add_exception_specifier (NULL_TREE, $1, 1); }
| ansi_raise_identifiers ',' ansi_raise_identifier
- {
- TREE_CHAIN ($3) = $$;
- $$ = $3;
- }
+ { $$ = add_exception_specifier ($1, $3, 1); }
;
conversion_declarator: