aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parse.y')
-rw-r--r--gcc/cp/parse.y237
1 files changed, 138 insertions, 99 deletions
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 2def8f7a7e1..9d010726508 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -1,5 +1,5 @@
/* YACC parser for C++ syntax.
- Copyright (C) 1988, 89, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -59,9 +59,10 @@ 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 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;
@@ -202,6 +203,7 @@ empty_parms ()
%type <ttype> compstmt implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator
+%type <ttype> notype_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
%type <itype> components notype_components
%type <ttype> component_decl component_decl_1
@@ -215,7 +217,8 @@ empty_parms ()
%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
@@ -233,7 +236,7 @@ empty_parms ()
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
%type <ttype> component_constructor_declarator
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
-%type <itype> ctor_initializer_opt
+%type <itype> ctor_initializer_opt function_try_block
%type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
@@ -250,6 +253,7 @@ empty_parms ()
%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
@@ -644,7 +648,11 @@ fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ finish_function (lineno, (int)$3, 0); }
| 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);
+ }
| fn.def1 maybe_return_init error
{ }
;
@@ -717,8 +725,10 @@ component_constructor_declarator:
reduce/reduce conflict introduced by these rules. */
fn.def2:
declmods component_constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2);
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs);
rest_of_mdef:
if (! $$)
YYERROR1;
@@ -726,20 +736,29 @@ fn.def2:
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| component_constructor_declarator
- { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $1, NULL_TREE);
+ goto rest_of_mdef; }
| typed_declspecs declarator
- { tree specs = strip_attrs ($1.t);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { 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; }
| declmods notype_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { 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; }
| notype_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
| declmods constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { 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; }
| constructor_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
;
return_id:
@@ -903,6 +922,12 @@ template_type:
| 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
@@ -1016,7 +1041,7 @@ condition:
{
cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING);
resume_momentary ($<itype>5);
- $$ = $<ttype>6;
+ $$ = convert_from_reference ($<ttype>6);
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
cp_error ("definition of array `%#D' in condition", $$);
}
@@ -1081,7 +1106,8 @@ unary_expr:
| 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
@@ -1300,7 +1326,16 @@ notype_unqualified_id:
;
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
@@ -1325,13 +1360,23 @@ unqualified_id:
| 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; }
;
@@ -1348,8 +1393,8 @@ direct_notype_declarator:
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:
@@ -1378,7 +1423,7 @@ primary:
}
| '(' 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 ')'
@@ -1418,47 +1463,20 @@ primary:
{ $$ = 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 = cp_build_qualified_type (integer_type_node,
+ cp_type_qual_from_rid ($1));
+ $$ = build_c_cast (type, build_compound_expr ($3));
}
| functional_cast
| DYNAMIC_CAST '<' type_id '>' '(' expr ')'
@@ -1801,7 +1819,7 @@ typespec:
| complete_type_name
{ $$.t = $1; $$.new_type_flag = 0; }
| TYPEOF '(' expr ')'
- { $$.t = TREE_TYPE ($3);
+ { $$.t = finish_typeof ($3);
$$.new_type_flag = 0; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
@@ -2032,7 +2050,7 @@ initlist:
fn.defpen:
PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($1),
- NULL_TREE, 1);
+ NULL_TREE, 2);
reinit_parse_for_function (); }
pending_inline:
@@ -2040,11 +2058,16 @@ pending_inline:
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
- finish_function (lineno, (int)$3, nested);
+ finish_function (lineno, (int)$3 | 2, nested);
process_next_inline ($1);
}
| fn.defpen maybe_return_init function_try_block
- { process_next_inline ($1); }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3 | 2, nested);
+ process_next_inline ($1);
+ }
| fn.defpen maybe_return_init error
{ process_next_inline ($1); }
;
@@ -2094,7 +2117,7 @@ structsp:
{ TYPE_VALUES (current_enum_type) = $4;
$$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
- current_enum_type = $<ttype>4;
+ current_enum_type = $<ttype>3;
resume_momentary ((int) $<itype>1);
check_for_missing_semicolon ($$.t); }
| ENUM '{' '}'
@@ -2209,9 +2232,9 @@ named_complex_class_head_sans_basetype:
current_aggr = $1;
$$ = handle_class_head ($1, NULL_TREE, $3);
}
- | aggr template_type
+ | aggr apparent_template_type
{ current_aggr = $$; $$ = $2; }
- | aggr nested_name_specifier template_type
+ | aggr nested_name_specifier apparent_template_type
{ current_aggr = $$; $$ = $3; }
;
@@ -2220,25 +2243,41 @@ named_class_head:
{ $$ = xref_tag (current_aggr, $1, 1); }
| 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;
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
+ {
+ if ($1 != error_mark_node)
+ push_scope (CP_DECL_CONTEXT ($1));
+ }
+ 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 != error_mark_node)
{
- maybe_process_partial_specialization ($$);
- xref_basetypes (current_aggr, $1, $$, $2);
+ pop_scope (CP_DECL_CONTEXT ($1));
+ $$ = TREE_TYPE ($1);
+ if (current_aggr == union_type_node
+ && TREE_CODE ($$) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$) == UNION_TYPE
+ && current_aggr != union_type_node)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key; deal. */
+ CLASSTYPE_DECLARED_CLASS ($$) = (current_aggr
+ == class_type_node);
+ if ($3)
+ {
+ maybe_process_partial_specialization ($$);
+ xref_basetypes (current_aggr, $1, $$, $3);
+ }
}
}
;
@@ -2364,16 +2403,8 @@ left_curly:
{ $<ttype>0 = begin_class_definition ($<ttype>0); }
;
-self_reference:
- /* empty */
- {
- finish_member_declaration (build_self_reference ());
- }
- ;
-
opt.component_decl_list:
- self_reference
- | self_reference component_decl_list
+ | component_decl_list
| opt.component_decl_list access_specifier component_decl_list
| opt.component_decl_list access_specifier
;
@@ -2774,16 +2805,26 @@ direct_after_type_declarator:
/* 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);
}
@@ -2791,15 +2832,15 @@ notype_declarator:
;
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);
}
@@ -2851,7 +2892,7 @@ overqualified_id:
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); }
@@ -3314,10 +3355,8 @@ function_try_block:
}
handler_seq
{
- int nested = (hack_decl_function_context
- (current_function_decl) != NULL_TREE);
expand_end_all_catch ();
- finish_function (lineno, (int)$3, nested);
+ $$ = $3;
}
;