📄 cp-parse.y
字号:
interface_unknown = 1; $$ = finish_struct ($<ttype>3, $5, 0, 0); pop_obstacks (); end_template_instantiation ($1, $<ttype>3); /* Now go after the methods & class data. */ old_interface = interface_unknown; interface_unknown = 1; instantiate_member_templates ($1); interface_unknown = old_interface; CLASSTYPE_GOT_SEMICOLON ($$) = 1; } ;template_instantiation: /* empty */ { $$ = NULL_TREE; } | template_instantiate_once { $$ = $1; } ;template_instantiate_some: /* empty */ { $$ = NULL_TREE; /* never used from here... */} | template_instantiate_once template_instantiate_some { $$ = $1; /*???*/ } ;unop: '-' { $$ = NEGATE_EXPR; } | '+' { $$ = CONVERT_EXPR; } | PLUSPLUS { $$ = PREINCREMENT_EXPR; } | MINUSMINUS { $$ = PREDECREMENT_EXPR; } | '!' { $$ = TRUTH_NOT_EXPR; } ;expr: nonnull_exprlist { $$ = build_x_compound_expr ($$); } /* Ugly, but faster. */ | expr_no_commas ;nonnull_exprlist: expr_no_commas { $$ = build_tree_list (NULL_TREE, $$); } | nonnull_exprlist ',' expr_no_commas { chainon ($$, build_tree_list (NULL_TREE, $3)); } | nonnull_exprlist ',' error { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); } ;unary_expr: primary %prec UNARY { if (TREE_CODE ($$) == TYPE_EXPR) $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1); } /* __extension__ turns off -pedantic for following primary. */ | EXTENSION { $<itype>1 = pedantic; pedantic = 0; } cast_expr %prec UNARY { $$ = $3; pedantic = $<itype>1; } | '*' cast_expr %prec UNARY { $$ = build_x_indirect_ref ($2, "unary *"); } | '&' cast_expr %prec UNARY { $$ = build_x_unary_op (ADDR_EXPR, $2); } | '~' cast_expr %prec UNARY { $$ = build_x_unary_op (BIT_NOT_EXPR, $2); } | unop cast_expr %prec UNARY { $$ = build_x_unary_op ($$, $2); if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST) TREE_NEGATED_INT ($$) = 1; } /* Refer to the address of a label as a pointer. */ | ANDAND identifier { tree label = lookup_label ($2); TREE_USED (label) = 1; $$ = build1 (ADDR_EXPR, ptr_type_node, label); TREE_CONSTANT ($$) = 1; } | SIZEOF unary_expr %prec UNARY { if (TREE_CODE ($2) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) error ("sizeof applied to a bit-field"); /* ANSI says arrays and functions are converted inside comma. But we can't really convert them in build_compound_expr because that would break commas in lvalues. So do the conversion here if operand was a comma. */ if (TREE_CODE ($2) == COMPOUND_EXPR && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) $2 = default_conversion ($2); $$ = c_sizeof (TREE_TYPE ($2)); } | SIZEOF '(' typename ')' %prec HYPERUNARY { $$ = c_sizeof (groktypename ($3)); } | ALIGNOF unary_expr %prec UNARY { if (TREE_CODE ($2) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) error ("`__alignof' applied to a bit-field"); if (TREE_CODE ($2) == INDIRECT_REF) { tree t = TREE_OPERAND ($2, 0); tree best = t; int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); while (TREE_CODE (t) == NOP_EXPR && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) { int thisalign; t = TREE_OPERAND (t, 0); thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); if (thisalign > bestalign) best = t, bestalign = thisalign; } $$ = c_alignof (TREE_TYPE (TREE_TYPE (best))); } else { /* ANSI says arrays and fns are converted inside comma. But we can't convert them in build_compound_expr because that would break commas in lvalues. So do the conversion here if operand was a comma. */ if (TREE_CODE ($2) == COMPOUND_EXPR && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) $2 = default_conversion ($2); $$ = c_alignof (TREE_TYPE ($2)); } } | ALIGNOF '(' typename ')' %prec HYPERUNARY { $$ = c_alignof (groktypename ($3)); } | .scope new typename %prec '=' { $$ = build_new ($2, $3, NULL_TREE, $$); } | .scope new '(' nonnull_exprlist ')' typename %prec '=' { $$ = build_new ($4, $6, NULL_TREE, $$); } | .scope new typespec '(' nonnull_exprlist ')' { $$ = build_new ($2, $3, $5, $$); } | .scope new '(' nonnull_exprlist ')' typespec '(' nonnull_exprlist ')' { $$ = build_new ($4, $6, $8, $$); } | .scope new typespec LEFT_RIGHT { $$ = build_new ($2, $3, NULL_TREE, $$); } | .scope new '(' nonnull_exprlist ')' typespec LEFT_RIGHT { $$ = build_new ($4, $6, NULL_TREE, $$); } | .scope new typename '=' init %prec '=' { $$ = build_new ($2, $3, $5, $$); } | .scope new '(' nonnull_exprlist ')' typename '=' init %prec '=' { $$ = build_new ($4, $6, $8, $$); } /* I am not going to add placement syntax to the below complex rules because Ken says the syntax is illegal. (mrs) */ /* I'm not sure why this is disallowed. But since it is, and it doesn't seem difficult to catch it, let's give a message, so the programmer can fix it. --Ken Raeburn */ | .scope new '(' typed_typespecs absdcl ')' '[' nonmomentary_expr ']' { tree absdcl, typename; illegal_new_array: absdcl = build_parse_node (ARRAY_REF, $5, $8); typename = build_decl_list ($4, absdcl); pedwarn ("ANSI C++ forbids array dimensions with parenthesized type"); $$ = build_new ($2, typename, NULL_TREE, $$); } | .scope new '(' nonempty_type_quals absdcl ')' '[' nonmomentary_expr ']' { goto illegal_new_array; } | .scope new '(' typed_typespecs absdcl ')' { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } | .scope new '(' nonnull_exprlist ')' '(' typed_typespecs absdcl ')' { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } | .scope new '(' nonempty_type_quals absdcl ')' { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } | .scope new '(' nonnull_exprlist ')' '(' nonempty_type_quals absdcl ')' { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } /* Unswallow a ':' which is probably meant for ?: expression. */ | .scope new TYPENAME_COLON { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$); } | .scope new '(' nonnull_exprlist ')' TYPENAME_COLON { yyungetc (':', 1); $$ = build_new ($4, $6, NULL_TREE, $$); } | delete cast_expr %prec UNARY { tree expr = stabilize_reference (convert_from_reference ($2)); tree type = TREE_TYPE (expr); if (TREE_CODE (type) != POINTER_TYPE) { error ("non-pointer type to `delete'"); $$ = error_mark_node; break; } else if (integer_zerop (expr)) { /* ANSI C++ June 5 1992 WP 5.3.4. Deleting a pointer with the value zero is legal and has no effect. */ $$ = build1 (NOP_EXPR, void_type_node, expr); break; } else if (TREE_READONLY (TREE_TYPE (type))) { error ("`const *' cannot be deleted"); $$ = error_mark_node; break; } $$ = build_delete (type, expr, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)), 0); } | delete '[' ']' cast_expr %prec UNARY { tree exp = stabilize_reference (convert_from_reference ($4)); tree type = TREE_TYPE (exp); tree elt_size = c_sizeof (type); if (yychar == YYEMPTY) yychar = YYLEX; if (TREE_CODE (type) == POINTER_TYPE && TREE_READONLY (TREE_TYPE (type))) { error ("`const *' cannot be deleted"); $$ = error_mark_node; break; } $$ = build_vec_delete (exp, NULL_TREE, elt_size, NULL_TREE, integer_one_node, integer_two_node); } | delete '[' expr ']' cast_expr %prec UNARY { tree maxindex = build_binary_op (MINUS_EXPR, $3, integer_one_node); tree exp = stabilize_reference (convert_from_reference ($5)); tree type = TREE_TYPE (exp); tree elt_size = c_sizeof (type); if (yychar == YYEMPTY) yychar = YYLEX; if (! flag_traditional) pedwarn ("ANSI C++ forbids array size in vector delete"); if (TREE_CODE (type) == POINTER_TYPE && TREE_READONLY (TREE_TYPE (type))) { error ("`const *' cannot be deleted"); $$ = error_mark_node; break; } $$ = build_vec_delete (exp, maxindex, elt_size, NULL_TREE, integer_one_node, integer_two_node); } ;cast_expr: unary_expr | '(' typename ')' expr_no_commas %prec UNARY { tree type = groktypename ($2); $$ = build_c_cast (type, $4); } | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY { tree type = groktypename ($2); tree init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)); if (pedantic) pedwarn ("ANSI C++ forbids constructor-expressions"); /* Indicate that this was a GNU C constructor expression. */ TREE_HAS_CONSTRUCTOR (init) = 1; $$ = digest_init (type, init, 0); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { int failure = complete_array_type (type, $$, 1); if (failure) my_friendly_abort (78); } } | HEADOF '(' expr ')' { $$ = build_headof ($3); } | CLASSOF '(' expr ')' { $$ = build_classof ($3); } | CLASSOF '(' TYPENAME ')' { if (is_aggr_typedef ($3, 1)) { tree type = IDENTIFIER_TYPE_VALUE ($3); $$ = CLASSTYPE_DOSSIER (type); } else $$ = error_mark_node; } ;expr_no_commas: cast_expr | expr_no_commas '+' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '-' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '*' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '/' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '%' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas LSHIFT expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas RSHIFT expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas ARITHCOMPARE expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '<' expr_no_commas { $$ = build_x_binary_op (LT_EXPR, $$, $3); } | expr_no_commas '>' expr_no_commas { $$ = build_x_binary_op (GT_EXPR, $$, $3); } | expr_no_commas EQCOMPARE expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas MIN_MAX expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '&' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '|' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '^' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas ANDAND expr_no_commas { $$ = build_x_binary_op (TRUTH_ANDIF_EXPR, $$, $3); } | expr_no_commas OROR expr_no_commas { $$ = build_x_binary_op (TRUTH_ORIF_EXPR, $$, $3); } | expr_no_commas '?' xexpr ':' expr_no_commas { $$ = build_x_conditional_expr ($$, $3, $5); } | expr_no_commas '=' expr_no_commas { $$ = build_modify_expr ($$, NOP_EXPR, $3); } | expr_no_commas ASSIGN expr_no_commas { register tree rval; if (rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3, make_node ($2))) $$ = rval; else $$ = build_modify_expr ($$, $2, $3); } | primary DOT_STAR expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_indirect_ref ($3, 0)); } /* Handle general members. */ | object_star expr_no_commas %prec UNARY { $$ = build_x_binary_op (MEMBER_REF, $$, $2); }/* These extensions are not defined. | object '&' expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); } | object unop expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); } | object '(' typename ')' expr_no_commas %prec UNARY { tree type = groktypename ($3); $$ = build_m_component_ref ($$, build_c_cast (type, $5)); } | object primary_no_id %prec UNARY { $$ = build_m_component_ref ($$, $2); }*/ ;primary: IDENTIFIER { $$ = do_identifier ($$); } | operator_name { tree op = $$; if (TREE_CODE (op) != IDENTIFIER_NODE) $$ = op; else { $$ = lookup_name (op, 0); if ($$ == NULL_TREE) { error ("operator %s not defined", operator_name_string (op)); $$ = error_mark_node; } } } | CONSTANT | string { $$ = combine_strings ($$); } | '(' expr ')' { $$ = $2; } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } keep_next_level (); $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { tree rtl_exp; if (pedantic) pedwarn ("ANSI C++ forbids braced-groups within expressions"); rtl_exp = expand_end_stmt_expr ($<ttype>2); /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; /* Make a BIND_EXPR for the BLOCK already made. */ $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), NULL_TREE, rtl_exp, $3); /* Remove the block from the tree at this point. It gets put back at the proper place when the BIND_EXPR is expanded. */ delete_block ($3); } | primary '(' nonnull_exprlist ')' { /* [eichin:19911016.1902EST] */ $<ttype>$ = build_x_function_call ($1, $3, current_class_decl); /* here we instantiate_class_template as needed... */ do_pending_templates (); } template_instantiate_some { if (TREE_CODE ($<ttype>5) == CALL_EXPR && TREE_TYPE ($<ttype>5) != void_type_node) $$ = require_complete_type ($<ttype>5); else $$ = $<ttype>5; } | primary LEFT_RIGHT { if ($$ != error_mark_node) { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); if (TREE_CODE ($$) == CALL_EXPR && TREE_TYPE ($$) != void_type_node) $$ = require_complete_type ($$); } } | primary '[' expr ']' { do_array: { tree array_expr = $$; tree index_exp = $3; tree type = TREE_TYPE (array_expr); if (type == error_mark_node || index_exp == error_mark_node) $$ = error_mark_node; else if (type == NULL_TREE) { /* Something has gone very wrong. Assume we are mistakenly reducing an expression instead of a declaration. */ error ("parser may be lost: is there a '{' missing somewhere?");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -