?? c-parse.y
字號(hào):
pedwarn ("ANSI C forbids `&&'"); if (label == 0) $$ = null_pointer_node; else { TREE_USED (label) = 1; $$ = build1 (ADDR_EXPR, ptr_type_node, label); TREE_CONSTANT ($$) = 1; } }/* This seems to be impossible on some machines, so let's turn it off. You can use __builtin_next_arg to find the anonymous stack args. | '&' ELLIPSIS { tree types = TYPE_ARG_TYPES (TREE_TYPE (current_function_decl)); $$ = error_mark_node; if (TREE_VALUE (tree_last (types)) == void_type_node) error ("`&...' used in function with fixed number of arguments"); else { if (pedantic) pedwarn ("ANSI C forbids `&...'"); $$ = tree_last (DECL_ARGUMENTS (current_function_decl)); $$ = build_unary_op (ADDR_EXPR, $$, 0); } }*/ | 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"); $$ = c_sizeof (TREE_TYPE ($2)); } | SIZEOF '(' typename ')' %prec HYPERUNARY { $$ = c_sizeof (groktypename ($3)); } | ALIGNOF unary_expr %prec UNARY { $$ = c_alignof_expr ($2); } | ALIGNOF '(' typename ')' %prec HYPERUNARY { $$ = c_alignof (groktypename ($3)); } | REALPART cast_expr %prec UNARY { $$ = build_unary_op (REALPART_EXPR, $2, 0); } | IMAGPART cast_expr %prec UNARY { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); } ;cast_expr: unary_expr | '(' typename ')' cast_expr %prec UNARY { tree type = groktypename ($2); $$ = build_c_cast (type, $4); } | '(' typename ')' '{' { start_init (NULL_TREE, NULL, 0); $2 = groktypename ($2); really_start_incremental_init ($2); } initlist_maybe_comma '}' %prec UNARY { char *name; tree result = pop_init_level (0); tree type = $2; finish_init (); if (pedantic) pedwarn ("ANSI C forbids constructor expressions"); if (TYPE_NAME (type) != 0) { if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) name = IDENTIFIER_POINTER (TYPE_NAME (type)); else name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); } else name = ""; $$ = result; if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { int failure = complete_array_type (type, $$, 1); if (failure) abort (); } } ;expr_no_commas: cast_expr | expr_no_commas '+' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '-' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '*' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '/' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '%' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas LSHIFT expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas RSHIFT expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas ARITHCOMPARE expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas EQCOMPARE expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '&' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '|' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '^' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas ANDAND expr_no_commas { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); } | expr_no_commas OROR expr_no_commas { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); } | expr_no_commas '?' xexpr ':' expr_no_commas { $$ = build_conditional_expr ($1, $3, $5); } | expr_no_commas '=' expr_no_commas { $$ = build_modify_expr ($1, NOP_EXPR, $3); C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } | expr_no_commas ASSIGN expr_no_commas { $$ = build_modify_expr ($1, $2, $3); /* This inhibits warnings in truthvalue_conversion. */ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } ;primary: IDENTIFIER { $$ = lastiddecl; if (!$$ || $$ == error_mark_node) { if (yychar == YYEMPTY) yychar = YYLEX; if (yychar == '(') { { /* Ordinary implicit function declaration. */ $$ = implicitly_declare ($1); assemble_external ($$); TREE_USED ($$) = 1; } } else if (current_function_decl == 0) { error ("`%s' undeclared here (not in a function)", IDENTIFIER_POINTER ($1)); $$ = error_mark_node; } else { { if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl) { error ("`%s' undeclared (first use this function)", IDENTIFIER_POINTER ($1)); if (! undeclared_variable_notice) { error ("(Each undeclared identifier is reported only once"); error ("for each function it appears in.)"); undeclared_variable_notice = 1; } } $$ = error_mark_node; /* Prevent repeated error messages. */ IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl; } } } else if (TREE_TYPE ($$) == error_mark_node) $$ = error_mark_node; else if (C_DECL_ANTICIPATED ($$)) { /* The first time we see a build-in function used, if it has not been declared. */ C_DECL_ANTICIPATED ($$) = 0; if (yychar == YYEMPTY) yychar = YYLEX; if (yychar == '(') { /* Omit the implicit declaration we would ordinarily do, so we don't lose the actual built in type. But print a diagnostic for the mismatch. */ if (TREE_CODE ($$) != FUNCTION_DECL) error ("`%s' implicitly declared as function", IDENTIFIER_POINTER (DECL_NAME ($$))); else if ((TYPE_MODE (TREE_TYPE (TREE_TYPE ($$))) != TYPE_MODE (integer_type_node)) && (TREE_TYPE (TREE_TYPE ($$)) != void_type_node)) pedwarn ("type mismatch in implicit declaration for built-in function `%s'", IDENTIFIER_POINTER (DECL_NAME ($$))); /* If it really returns void, change that to int. */ if (TREE_TYPE (TREE_TYPE ($$)) == void_type_node) TREE_TYPE ($$) = build_function_type (integer_type_node, TYPE_ARG_TYPES (TREE_TYPE ($$))); } else pedwarn ("built-in function `%s' used without declaration", IDENTIFIER_POINTER (DECL_NAME ($$))); /* Do what we would ordinarily do when a fn is used. */ assemble_external ($$); TREE_USED ($$) = 1; } else { assemble_external ($$); TREE_USED ($$) = 1; } if (TREE_CODE ($$) == CONST_DECL) { $$ = 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; } } | CONSTANT | string { $$ = combine_strings ($1); } | '(' expr ')' { char class = TREE_CODE_CLASS (TREE_CODE ($2)); if (class == 'e' || class == '1' || class == '2' || class == '<') C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK); $$ = $2; } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } /* We must force a BLOCK for this level so that, if it is not expanded later, there is a way to turn off the entire subtree of blocks that are contained in it. */ keep_next_level (); push_iterator_stack (); push_label_level (); $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { tree rtl_exp; if (pedantic) pedwarn ("ANSI C forbids braced-groups within expressions"); pop_iterator_stack (); pop_label_level (); rtl_exp = expand_end_stmt_expr ($<ttype>2); /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; if (TREE_CODE ($3) == BLOCK) { /* 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); } else $$ = $3; } | primary '(' exprlist ')' %prec '.' { $$ = build_function_call ($1, $3); } | primary '[' expr ']' %prec '.' { $$ = build_array_ref ($1, $3); } | primary '.' identifier { $$ = build_component_ref ($1, $3); } | primary POINTSAT identifier { tree expr = build_indirect_ref ($1, "->"); $$ = build_component_ref (expr, $3); } | primary PLUSPLUS { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } | primary MINUSMINUS { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); } ;/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */string: STRING | string STRING { $$ = chainon ($1, $2); } ;xdecls: /* empty */ | datadecls | datadecls ELLIPSIS /* ... is used here to indicate a varargs function. */ { c_mark_varargs (); if (pedantic) pedwarn ("ANSI C does not permit use of `varargs.h'"); } ;/* The following are analogous to lineno_decl, decls and decl except that they do not allow nested functions. They are used for old-style parm decls. */lineno_datadecl: save_filename save_lineno datadecl { } ;datadecls: lineno_datadecl | errstmt | datadecls lineno_datadecl | lineno_datadecl errstmt ;datadecl: typed_declspecs setspecs initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs ';' { shadow_tag_warned ($1, 1); pedwarn ("empty declaration"); } | declmods ';' { pedwarn ("empty declaration"); } ;/* This combination which saves a lineno before a decl is the normal thing to use, rather than decl itself. This is to avoid shift/reduce conflicts in contexts where statement labels are allowed. */lineno_decl: save_filename save_lineno decl { } ;decls: lineno_decl | errstmt | decls lineno_decl | lineno_decl errstmt ;/* records the type and storage class specs to use for processing the declarators that follow. Maintains a stack of outer-level values of current_declspecs, for the sake of parm declarations nested in function declarators. */setspecs: /* empty */ { $$ = suspend_momentary (); pending_xref_error (); declspec_stack = tree_cons (prefix_attributes, current_declspecs, declspec_stack); current_declspecs = $<ttype>0; prefix_attributes = NULL_TREE; } ;setattrs: /* empty */ { prefix_attributes = chainon (prefix_attributes, $<ttype>0); } ;decl: typed_declspecs setspecs initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs setspecs nested_function { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_nested_function { current_declspecs = TREE_VALUE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs ';' { shadow_tag ($1); } | declmods ';' { pedwarn ("empty declaration"); } ;/* 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 reserved_declspecs { $$ = tree_cons (NULL_TREE, $1, $2); } | declmods typespec reserved_declspecs { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } ;reserved_declspecs: /* empty */ { $$ = NULL_TREE; } | reserved_declspecs typespecqual_reserved { $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs SCSPEC
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -