📄 cp-parse.y
字号:
$$ = NULL_TREE; } else { if (TREE_CODE (type) == OFFSET_TYPE) type = TREE_TYPE (type); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_ARRAY_REF (type)) $$ = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp); else if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == ARRAY_TYPE) $$ = build_array_ref (array_expr, index_exp); else { type = TREE_TYPE (index_exp); if (TREE_CODE (type) == OFFSET_TYPE) type = TREE_TYPE (type); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_ARRAY_REF (type)) error ("array expression backwards"); else if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == ARRAY_TYPE) $$ = build_array_ref (index_exp, array_expr); else error("[] applied to non-pointer type"); } } } } | object identifier_or_opname %prec UNARY { $$ = build_component_ref ($$, $2, NULL_TREE, 1); } | object scoped_id identifier_or_opname %prec UNARY { tree basetype = $2; if (is_aggr_typedef (basetype, 1)) { basetype = IDENTIFIER_TYPE_VALUE (basetype); if ($$ == error_mark_node) ; else if (binfo_or_else (basetype, TREE_TYPE ($$))) $$ = build_component_ref (build_scoped_ref ($$, $2), $3, NULL_TREE, 1); else $$ = error_mark_node; } else $$ = error_mark_node; } | primary PLUSPLUS { $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | primary MINUSMINUS { $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } /* C++ extensions */ | THIS { if (current_class_decl) {#ifdef WARNING_ABOUT_CCD TREE_USED (current_class_decl) = 1;#endif $$ = current_class_decl; } else if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) { error ("`this' is unavailable for static member functions"); $$ = error_mark_node; } else { if (current_function_decl) error ("invalid use of `this' in non-member function"); else error ("invalid use of `this' at top level"); $$ = error_mark_node; } } | TYPE_QUAL '(' nonnull_exprlist ')' { tree type; tree id = $$; /* 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)); } } | typespec '(' nonnull_exprlist ')' { $$ = build_functional_cast ($$, $3); } | typespec LEFT_RIGHT { $$ = build_functional_cast ($$, NULL_TREE); } | SCOPE typespec '(' nonnull_exprlist ')' { $$ = build_functional_cast ($2, $4); } | SCOPE typespec LEFT_RIGHT { $$ = build_functional_cast ($2, NULL_TREE); } | SCOPE IDENTIFIER { do_scoped_id: $$ = IDENTIFIER_GLOBAL_VALUE ($2); if (yychar == YYEMPTY) yychar = YYLEX; if (! $$) { if (yychar == '(' || yychar == LEFT_RIGHT) $$ = implicitly_declare ($2); else { if (IDENTIFIER_GLOBAL_VALUE ($2) != error_mark_node) error ("undeclared variable `%s' (first use here)", IDENTIFIER_POINTER ($2)); $$ = error_mark_node; /* Prevent repeated error messages. */ IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node; } } else { assemble_external ($$); TREE_USED ($$) = 1; } if (TREE_CODE ($$) == CONST_DECL) { /* XXX CHS - should we set TREE_USED of the constant? */ $$ = DECL_INITIAL ($$); /* This is to prevent an enum whose value is 0 from being considered a null pointer constant. */ $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$); TREE_CONSTANT ($$) = 1; } } | SCOPE operator_name { if (TREE_CODE ($2) == IDENTIFIER_NODE) goto do_scoped_id; do_scoped_operator: $$ = $2; } | scoped_id identifier_or_opname %prec HYPERUNARY { $$ = build_offset_ref ($$, $2); } | scoped_id identifier_or_opname '(' nonnull_exprlist ')' { $$ = build_member_call ($$, $2, $4); } | scoped_id identifier_or_opname LEFT_RIGHT { $$ = build_member_call ($$, $2, NULL_TREE); } | object identifier_or_opname '(' nonnull_exprlist ')' { $$ = build_method_call ($$, $2, $4, NULL_TREE, (LOOKUP_NORMAL|LOOKUP_AGGR)); } | object identifier_or_opname LEFT_RIGHT { $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE, (LOOKUP_NORMAL|LOOKUP_AGGR)); } | object scoped_id identifier_or_opname '(' nonnull_exprlist ')' { $$ = build_scoped_method_call ($$, $2, $3, $5); } | object scoped_id identifier_or_opname LEFT_RIGHT { $$ = build_scoped_method_call ($$, $2, $3, NULL_TREE); } ;/* Not needed for now.primary_no_id: '(' expr ')' { $$ = $2; } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { if (pedantic) pedwarn ("ANSI C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($<ttype>2); } | primary_no_id '(' nonnull_exprlist ')' { $$ = build_x_function_call ($$, $3, current_class_decl); } | primary_no_id LEFT_RIGHT { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); } | primary_no_id '[' expr ']' { goto do_array; } | primary_no_id PLUSPLUS { $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | primary_no_id MINUSMINUS { $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } | SCOPE IDENTIFIER { goto do_scoped_id; } | SCOPE operator_name { if (TREE_CODE ($2) == IDENTIFIER_NODE) goto do_scoped_id; goto do_scoped_operator; } ;*/new: NEW { $$ = NULL_TREE; } | NEW '{' nonnull_exprlist '}' { $$ = $3; pedwarn ("old style placement syntax, use () instead"); } | NEW DYNAMIC %prec EMPTY { $$ = void_type_node; } | NEW DYNAMIC '(' string ')' { $$ = combine_strings ($4); } ;.scope: /* empty */ { $$ = 0; } | SCOPE { $$ = 1; } ;delete: DELETE { $$ = NULL_TREE; } | SCOPE delete { if ($2) error ("extra `::' before `delete' ignored"); $$ = error_mark_node; } ;/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */string: STRING | string STRING { $$ = chainon ($$, $2); } ;nodecls: /* empty */ { if (! current_function_parms_stored) store_parm_decls (); setup_vtbl_ptr (); } ;object: primary '.' { if ($$ == error_mark_node) ; else { tree type = TREE_TYPE ($$); if (! PROMOTES_TO_AGGR_TYPE (type, REFERENCE_TYPE)) { error ("object in '.' expression is not of aggregate type"); $$ = error_mark_node; } } } | primary POINTSAT { $$ = build_x_arrow ($$); } ;object_star: primary POINTSAT_STAR ;decl: typed_declspecs initdecls ';' { resume_momentary ($2); note_list_got_semicolon ($<ttype>$); } /* Normal case: make this fast. */ | typed_declspecs declarator ';' { tree d; int yes = suspend_momentary (); d = start_decl ($2, $<ttype>$, 0, NULL_TREE); finish_decl (d, NULL_TREE, NULL_TREE, 0); resume_momentary (yes); note_list_got_semicolon ($<ttype>$); } | declmods notype_initdecls ';' { resume_momentary ($2); } /* Normal case: make this fast. */ | declmods declarator ';' { tree d; int yes = suspend_momentary (); d = start_decl ($2, $<ttype>$, 0, NULL_TREE); finish_decl (d, NULL_TREE, NULL_TREE, 0); resume_momentary (yes); } | typed_declspecs ';' { shadow_tag ($<ttype>$); note_list_got_semicolon ($<ttype>$); } | declmods ';' { warning ("empty declaration"); } ;/* Any kind of declarator (thus, all declarators allowed after an explicit typespec). */declarator: after_type_declarator | notype_declarator | START_DECLARATOR after_type_declarator { $$ = $2; } | START_DECLARATOR notype_declarator { $$ = $2; } ;/* Declspecs which contain at least one type specifier or typedef name. (Just `const' or `volatile' is not enough.) A typedef'd name following these is taken as a name to be declared. */typed_declspecs: typespec %prec HYPERUNARY { $$ = list_hash_lookup_or_cons ($$); } | declmods typespec { $$ = hash_tree_chain ($2, $$); } | typespec reserved_declspecs %prec HYPERUNARY { $$ = hash_tree_chain ($$, $2); } | declmods typespec reserved_declspecs { $$ = hash_tree_chain ($2, hash_chainon ($3, $$)); } ;reserved_declspecs: /* empty { $$ = NULL_TREE; } */ typespecqual_reserved { $$ = build_decl_list (NULL_TREE, $$); } | SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($$)); $$ = build_decl_list (NULL_TREE, $$); } | reserved_declspecs typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | reserved_declspecs SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = decl_tree_cons (NULL_TREE, $2, $$); } ;/* List of just storage classes and type modifiers. A declaration can start with just this, but then it cannot be used to redeclare a typedef-name. */declmods: TYPE_QUAL { $$ = IDENTIFIER_AS_LIST ($$); TREE_STATIC ($$) = 1; } | SCSPEC { $$ = IDENTIFIER_AS_LIST ($$); } | declmods TYPE_QUAL { $$ = hash_tree_chain ($2, $$); TREE_STATIC ($$) = 1; } | declmods SCSPEC { if (extra_warnings && TREE_STATIC ($$)) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = hash_tree_chain ($2, $$); TREE_STATIC ($$) = TREE_STATIC ($1); } ;/* Used instead of declspecs where storage classes are not allowed (that is, for typenames and structure components). C++ can takes storage classes for structure components. Don't accept a typedef-name if anything but a modifier precedes it. */typed_typespecs: typespec %prec EMPTY { $$ = get_decl_list ($$); } | nonempty_type_quals typespec { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | typespec reserved_typespecquals { $$ = decl_tree_cons (NULL_TREE, $$, $2); } | nonempty_type_quals typespec reserved_typespecquals { $$ = decl_tree_cons (NULL_TREE, $2, hash_chainon ($3, $$)); } ;reserved_typespecquals: typespecqual_reserved { $$ = get_decl_list ($$); } | reserved_typespecquals typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2, $$); } ;/* A typespec (but not a type qualifier). Once we have seen one of these in a declaration, if a typedef name appears then it is being redeclared. */typespec: structsp | TYPESPEC %prec EMPTY | TYPENAME %prec EMPTY | scoped_typename | TYPEOF '(' expr ')' { $$ = TREE_TYPE ($3); if (pedantic) pedwarn ("ANSI C++ forbids `typeof'"); } | TYPEOF '(' typename ')' { $$ = groktypename ($3); if (pedantic) pedwarn ("ANSI C++ forbids `typeof'"); } | template_type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -