📄 parse.y
字号:
template_parm: /* The following rules introduce a new reduce/reduce conflict on the ',' and '>' input tokens: they are valid prefixes for a `structsp', which means they could match a nameless parameter. See 14.6, paragraph 3. By putting them before the `parm' rule, we get their match before considering them nameless parameter declarations. */ template_type_parm { $$ = build_tree_list (NULL_TREE, $$); } | template_type_parm '=' typespec { $$ = build_tree_list ($3, $$); } | full_parm ;overloaddef: OVERLOAD ov_identifiers ';' { warning ("use of `overload' is an anachronism"); } ;ov_identifiers: IDENTIFIER { declare_overloaded ($1); } | ov_identifiers ',' IDENTIFIER { declare_overloaded ($3); } ; template_def: /* Class template declarations go here; they aren't normal class declarations, because we can't process the bodies yet. */ template_header named_class_head_sans_basetype '{' { yychar = '{'; goto template1; } ';' | template_header named_class_head_sans_basetype_defn '{' { yychar = '{'; goto template1; } ';' | template_header named_class_head_sans_basetype ':' { yychar = ':'; goto template1; } ';' | template_header named_class_head_sans_basetype_defn ':' { yychar = ':'; template1: if (current_aggr == signature_type_node) sorry ("template type defining a signature"); /* Maybe pedantic warning for union? How about an enum? :-) */ end_template_decl ($1, $2, current_aggr, 1); reinit_parse_for_template (yychar, $1, $2); yychar = YYEMPTY; } ';' | template_header named_class_head_sans_basetype ';' { end_template_decl ($1, $2, current_aggr, 0); /* declare $2 as template name with $1 parm list */ } | template_header named_class_head_sans_basetype_defn ';' { end_template_decl ($1, $2, current_aggr, 0); /* declare $2 as template name with $1 parm list */ } | template_header /* notype_initdcl0 ';' */ notype_declarator exception_specification_opt maybeasm maybe_attribute fn_tmpl_end { tree d; int momentary; int def = ($6 != ';'); momentary = suspend_momentary (); d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0, $3); cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE); cp_finish_decl (d, NULL_TREE, $4, 0, 0); end_template_decl ($1, d, 0, def); if (def) reinit_parse_for_template ((int) $6, $1, d); resume_momentary (momentary); } | template_header typed_declspecs /*initdcl0*/ declarator exception_specification_opt maybeasm maybe_attribute fn_tmpl_end { tree d, specs, attrs; int momentary; int def = ($7 != ';'); split_specs_attrs ($2, &specs, &attrs); momentary = suspend_momentary (); d = start_decl ($<ttype>3, specs, 0, $<ttype>4); cplus_decl_attributes (d, $6, attrs); cp_finish_decl (d, NULL_TREE, $5, 0, 0); end_template_decl ($1, d, 0, def); if (def) { reinit_parse_for_template ((int) $7, $1, d); yychar = YYEMPTY; } note_list_got_semicolon ($<ttype>2); resume_momentary (momentary); } | template_header declmods notype_declarator fn_tmpl_end { tree d, specs, attrs; int def = ($4 != ';'); split_specs_attrs ($2, &specs, &attrs); d = start_decl ($<ttype>3, specs, 0, NULL_TREE); cplus_decl_attributes (d, NULL_TREE, attrs); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); end_template_decl ($1, d, 0, def); if (def) reinit_parse_for_template ((int) $4, $1, d); } /* Try to recover from syntax errors in templates. */ | template_header error '}' { end_template_decl ($1, 0, 0, 0); } | template_header error ';' { end_template_decl ($1, 0, 0, 0); } ;fn_tmpl_end: '{' { $$ = '{'; } | ':' { $$ = ':'; } | ';' { $$ = ';'; } | '=' { $$ = '='; } | RETURN { $$ = RETURN; } ;datadef: nomods_initdecls ';' {} | declmods notype_initdecls ';' {} /* Normal case to make fast: "const i;". */ | declmods notype_declarator ';' { tree d, specs, attrs; split_specs_attrs ($1, &specs, &attrs); d = start_decl ($<ttype>2, specs, 0, NULL_TREE); cplus_decl_attributes (d, NULL_TREE, attrs); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); } | typed_declspecs initdecls ';' { note_list_got_semicolon ($<ttype>$); } /* Normal case: make this fast. */ | typed_declspecs declarator ';' { tree d, specs, attrs; split_specs_attrs ($1, &specs, &attrs); d = start_decl ($<ttype>2, specs, 0, NULL_TREE); cplus_decl_attributes (d, NULL_TREE, attrs); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); note_list_got_semicolon ($<ttype>$); } | declmods ';' { pedwarn ("empty declaration"); } | explicit_instantiation ';' | typed_declspecs ';' { tree t, attrs; split_specs_attrs ($1, &t, &attrs); shadow_tag (t); if (TREE_CODE (t) == TREE_LIST && TREE_PURPOSE (t) == NULL_TREE) { t = TREE_VALUE (t); if (IS_AGGR_TYPE (t) && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t))) { if (CLASSTYPE_USE_TEMPLATE (t) == 0) SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t)) error ("override declaration for already-expanded template"); } } note_list_got_semicolon ($<ttype>$); } | error ';' | error '}' | ';' ;ctor_initializer_opt: nodecls { $$ = 0; } | base_init { $$ = 1; } ;maybe_return_init: /* empty */ | return_init | return_init ';' ;eat_saved_input: /* empty */ | END_OF_SAVED_INPUT ;fndef: fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error { finish_function (lineno, (int)$3, 0); if ($<ttype>$) process_next_inline ($<ttype>$); } | fn.def1 maybe_return_init function_try_block { if ($<ttype>$) process_next_inline ($<ttype>$); } eat_saved_input | typed_declspecs declarator error {} | declmods notype_declarator error {} | notype_declarator error {} ;fn.def1: typed_declspecs declarator exception_specification_opt { tree specs, attrs; split_specs_attrs ($1, &specs, &attrs); if (! start_function (specs, $2, $3, attrs, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | declmods notype_declarator exception_specification_opt { tree specs = strip_attrs ($1); if (! start_function (specs, $2, $3, NULL_TREE, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | notype_declarator exception_specification_opt { if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | PRE_PARSED_FUNCTION_DECL { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, NULL_TREE, 1); reinit_parse_for_function (); } ;/* more C++ complexity. See component_decl for a comment on the reduce/reduce conflict introduced by these rules. */fn.def2: typed_declspecs '(' parmlist ')' type_quals exception_specification_opt { tree specs = strip_attrs ($1); $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5); $$ = start_method (TREE_CHAIN (specs), $$, $6); rest_of_mdef: if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt { tree specs = strip_attrs ($1); $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), empty_parms (), $3); $$ = start_method (TREE_CHAIN (specs), $$, $4); goto rest_of_mdef; } | typed_declspecs declarator exception_specification_opt { tree specs = strip_attrs ($1); $$ = start_method (specs, $2, $3); goto rest_of_mdef; } | declmods notype_declarator exception_specification_opt { tree specs = strip_attrs ($1); $$ = start_method (specs, $2, $3); goto rest_of_mdef; } | notype_declarator exception_specification_opt { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; } ;return_id: RETURN IDENTIFIER { if (! current_function_parms_stored) store_parm_decls (); $$ = $2; } ;return_init: return_id maybe_init { store_return_init ($<ttype>$, $2); } | return_id '(' nonnull_exprlist ')' { store_return_init ($<ttype>$, $3); } | return_id LEFT_RIGHT { store_return_init ($<ttype>$, NULL_TREE); } ;base_init: ':' .set_base_init member_init_list { 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 (); } ;.set_base_init: /* empty */ { if (! current_function_parms_stored) 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); } else if (current_class_type == NULL_TREE) error ("base initializers not allowed for non-member functions"); else if (! DECL_CONSTRUCTOR_P (current_function_decl)) error ("only constructors take base initializers"); } ;member_init_list: /* empty */ { $$ = 0; } | member_init { $$ = 1; } | member_init_list ',' member_init | member_init_list error ;member_init: '(' nonnull_exprlist ')' { if (current_class_name && !flag_traditional) pedwarn ("anachronistic old style base class initializer"); expand_member_init (C_C_D, NULL_TREE, $2); } | LEFT_RIGHT { if (current_class_name && !flag_traditional) pedwarn ("anachronistic old style base class initializer"); expand_member_init (C_C_D, NULL_TREE, void_type_node); } | notype_identifier '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $<ttype>$, $3); } | notype_identifier LEFT_RIGHT { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | complete_type_name '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $<ttype>$, $3); } | complete_type_name LEFT_RIGHT { expand_member_init (C_C_D, $<ttype>$, void_type_node); } /* GNU extension */ | notype_qualified_id '(' nonnull_exprlist ')' { do_member_init (OP0 ($1), OP1 ($1), $3); } | notype_qualified_id LEFT_RIGHT { do_member_init (OP0 ($1), OP1 ($1), void_type_node); } ;identifier: IDENTIFIER | TYPENAME | PTYPENAME | NSNAME ;notype_identifier: IDENTIFIER | PTYPENAME | NSNAME %prec EMPTY ;identifier_defn: IDENTIFIER_DEFN | TYPENAME_DEFN | PTYPENAME_DEFN ;explicit_instantiation: TEMPLATE specialization template_instantiation { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); } | TEMPLATE typed_declspecs declarator { tree specs = strip_attrs ($2); do_function_instantiation (specs, $3, NULL_TREE); } | TEMPLATE notype_declarator { do_function_instantiation (NULL_TREE, $2, NULL_TREE); } | SCSPEC TEMPLATE specialization template_instantiation { do_type_instantiation ($4 ? $4 : $3, $1); } | SCSPEC TEMPLATE typed_declspecs declarator { tree specs = strip_attrs ($3); do_function_instantiation (specs, $4, $1); } | SCSPEC TEMPLATE notype_declarator { do_function_instantiation (NULL_TREE, $3, $1); } ;template_type: template_type_name tmpl.2 template_instantiation { if ($3) $$ = $3; } ;template_type_name: PTYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3, NULL_TREE); } | PTYPENAME '<' '>' { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); } | TYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3, NULL_TREE); } ;tmpl.2: /* empty */ %prec EMPTY { $$ = instantiate_class_template ($<ttype>0, 1); } ;template_arg_list: template_arg { $$ = build_tree_list (NULL_TREE, $$); } | template_arg_list ',' template_arg { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } ;template_arg: type_id { $$ = groktypename ($$); } | expr_no_commas %prec UNARY ;template_instantiate_once: PRE_PARSED_CLASS_DECL maybe_base_class_list { tree t, decl, tmpl; tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE ($1)); t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, $1, $2, 0); set_current_level_tags_transparency (1); my_friendly_assert (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE, 257); $<ttype>$ = t; /* Now, put a copy of the decl in global scope, to avoid recursive expansion. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -