📄 lex.c
字号:
char *buf; tree arg; reinit_parse_for_expr (&inline_text_obstack); len = obstack_object_size (&inline_text_obstack); buf = obstack_finish (&inline_text_obstack); push_obstacks (&inline_text_obstack, &inline_text_obstack); arg = make_node (DEFAULT_ARG); DEFARG_LENGTH (arg) = len - 1; DEFARG_POINTER (arg) = buf; pop_obstacks (); return arg;}/* Called from grokfndecl to note a function decl with unparsed default arguments for later processing. Also called from grokdeclarator for function types with unparsed defargs; the call from grokfndecl will always come second, so we can overwrite the entry from the type. */voidadd_defarg_fn (decl) tree decl;{ if (TREE_CODE (decl) == FUNCTION_DECL) TREE_VALUE (defarg_fns) = decl; else { push_obstacks (&inline_text_obstack, &inline_text_obstack); defarg_fns = tree_cons (current_class_type, decl, defarg_fns); pop_obstacks (); }}/* Helper for do_pending_defargs. Starts the parsing of a default arg. */static voidfeed_defarg (f, p) tree f, p;{ tree d = TREE_PURPOSE (p); feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d)); if (TREE_CODE (f) == FUNCTION_DECL) { lineno = DECL_SOURCE_LINE (f); input_filename = DECL_SOURCE_FILE (f); } yychar = DEFARG_MARKER; yylval.ttype = p;}/* Helper for do_pending_defargs. Ends the parsing of a default arg. */static voidfinish_defarg (){ if (yychar == YYEMPTY) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) { error ("parse error at end of saved function text"); /* restore_pending_input will abort unless yychar is either END_OF_SAVED_INPUT or YYEMPTY; since we already know we're hosed, feed back YYEMPTY. We also need to discard nextchar, since that may have gotten set as well. */ nextchar = -1; } yychar = YYEMPTY; end_input ();} /* Main function for deferred parsing of default arguments. Called from the parser. */voiddo_pending_defargs (){ if (defarg_parm) finish_defarg (); for (; defarg_fns; defarg_fns = TREE_CHAIN (defarg_fns)) { tree defarg_fn = TREE_VALUE (defarg_fns); if (defarg_parm == NULL_TREE) { push_nested_class (TREE_PURPOSE (defarg_fns), 1); pushlevel (0); if (is_member_template (defarg_fn)) begin_member_template_processing (defarg_fn); if (TREE_CODE (defarg_fn) == FUNCTION_DECL) {#if 0 tree p; for (p = DECL_ARGUMENTS (defarg_fn); p; p = TREE_CHAIN (p)) pushdecl (copy_node (p));#endif defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn)); } else defarg_parm = TYPE_ARG_TYPES (defarg_fn); } else defarg_parm = TREE_CHAIN (defarg_parm); for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm)) if (TREE_PURPOSE (defarg_parm) && TREE_CODE (TREE_PURPOSE (defarg_parm)) == DEFAULT_ARG) { feed_defarg (defarg_fn, defarg_parm); /* Return to the parser, which will process this defarg and call us again. */ return; } if (is_member_template (defarg_fn)) end_member_template_processing (); poplevel (0, 0, 0); pop_nested_class (1); }}/* Build a default function named NAME for type TYPE. KIND says what to build. When KIND == 0, build default destructor. When KIND == 1, build virtual destructor. When KIND == 2, build default constructor. When KIND == 3, build default X(const X&) constructor. When KIND == 4, build default X(X&) constructor. When KIND == 5, build default operator = (const X&). When KIND == 6, build default operator = (X&). */treecons_up_default_function (type, full_name, kind) tree type, full_name; int kind;{ extern tree void_list_node; tree declspecs = NULL_TREE; tree fn, args; tree argtype; int retref = 0; tree name = constructor_name (full_name); switch (kind) { /* Destructors. */ case 1: declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]); /* Fall through... */ case 0: name = build_parse_node (BIT_NOT_EXPR, name); args = void_list_node; break; case 2: /* Default constructor. */ args = void_list_node; break; case 3: type = build_type_variant (type, 1, 0); /* Fall through... */ case 4: /* According to ARM $12.8, the default copy ctor will be declared, but not defined, unless it's needed. */ argtype = build_reference_type (type); args = tree_cons (NULL_TREE, build_tree_list (hash_tree_chain (argtype, NULL_TREE), get_identifier ("_ctor_arg")), void_list_node); break; case 5: case 6: retref = 1; declspecs = build_decl_list (NULL_TREE, type); if (kind == 5) type = build_type_variant (type, 1, 0); name = ansi_opname [(int) MODIFY_EXPR]; argtype = build_reference_type (type); args = tree_cons (NULL_TREE, build_tree_list (hash_tree_chain (argtype, NULL_TREE), get_identifier ("_ctor_arg")), void_list_node); break; default: my_friendly_abort (59); } declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE], declspecs); TREE_PARMLIST (args) = 1; { tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE); int saved_processing_specialization; if (retref) declarator = build_parse_node (ADDR_EXPR, declarator); /* The following is in case we're generating the default implementation in the midst of handling a specialization. */ saved_processing_specialization = processing_specialization; processing_specialization = 0; fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); processing_specialization = saved_processing_specialization; } if (fn == void_type_node) return fn; if (kind > 2) SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));#if 0 if (processing_template_defn) { SET_DECL_IMPLICIT_INSTANTIATION (fn); repo_template_used (fn); }#endif#if 0 if (CLASSTYPE_INTERFACE_KNOWN (type)) { DECL_INTERFACE_KNOWN (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = (!CLASSTYPE_INTERFACE_ONLY (type) && flag_implement_inlines); } else#endif DECL_NOT_REALLY_EXTERN (fn) = 1; mark_inline_for_output (fn);#ifdef DEBUG_DEFAULT_FUNCTIONS { char *fn_type = NULL; tree t = name; switch (kind) { case 0: fn_type = "default destructor"; break; case 1: fn_type = "virtual destructor"; break; case 2: fn_type = "default constructor"; break; case 3: fn_type = "default X(const X&)"; break; case 4: fn_type = "default X(X&)"; break; } if (fn_type) { if (TREE_CODE (name) == BIT_NOT_EXPR) t = TREE_OPERAND (name, 0); fprintf (stderr, "[[[[ %s for %s:\n%s]]]]\n", fn_type, IDENTIFIER_POINTER (t), func_buf); } }#endif /* DEBUG_DEFAULT_FUNCTIONS */ /* Show that this function was generated by the compiler. */ SET_DECL_ARTIFICIAL (fn); return fn;}/* Heuristic to tell whether the user is missing a semicolon after a struct or enum declaration. Emit an error message if we know the user has blown it. */voidcheck_for_missing_semicolon (type) tree type;{ if (yychar < 0) yychar = yylex (); if ((yychar > 255 && yychar != SCSPEC && yychar != IDENTIFIER && yychar != TYPENAME && yychar != CV_QUALIFIER && yychar != SELFNAME) || end_of_file) { if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) error ("semicolon missing after %s declaration", TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct"); else cp_error ("semicolon missing after declaration of `%T'", type); shadow_tag (build_tree_list (0, type)); } /* Could probably also hack cases where class { ... } f (); appears. */ clear_anon_tags ();}voidnote_got_semicolon (type) tree type;{ if (TREE_CODE_CLASS (TREE_CODE (type)) != 't') my_friendly_abort (60); if (IS_AGGR_TYPE (type)) CLASSTYPE_GOT_SEMICOLON (type) = 1;}voidnote_list_got_semicolon (declspecs) tree declspecs;{ tree link; for (link = declspecs; link; link = TREE_CHAIN (link)) { tree type = TREE_VALUE (link); if (TREE_CODE_CLASS (TREE_CODE (type)) == 't') note_got_semicolon (type); } clear_anon_tags ();}/* If C is not whitespace, return C. Otherwise skip whitespace and return first nonwhite char read. */static intskip_white_space (c) register int c;{ for (;;) { switch (c) { case '\n': c = check_newline (); break; case ' ': case '\t': case '\f': case '\r': case '\v': case '\b': do c = getch (); while (c == ' ' || c == '\t'); break; case '\\': c = getch (); if (c == '\n') lineno++; else error ("stray '\\' in program"); c = getch (); break; default: return (c); } }}/* Make the token buffer longer, preserving the data in it. P should point to just beyond the last valid character in the old buffer. The value we return is a pointer to the new buffer at a place corresponding to P. */static char *extend_token_buffer (p) char *p;{ int offset = p - token_buffer; maxtoken = maxtoken * 2 + 10; token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2); return token_buffer + offset;}static intget_last_nonwhite_on_line (){ register int c; /* Is this the last nonwhite stuff on the line? */ if (nextchar >= 0) c = nextchar, nextchar = -1; else c = getch (); while (c == ' ' || c == '\t') c = getch (); return c;}/* At the beginning of a line, increment the line number and process any #-directive on this line. If the line is a #-directive, read the entire line and return a newline. Otherwise, return the line's first non-whitespace character. */int linemode;#ifdef HANDLE_SYSV_PRAGMAstatic int handle_sysv_pragma PROTO((FILE *, int));#endifstatic int handle_cp_pragma PROTO((char *));static intcheck_newline (){ register int c; register int token; /* Read first nonwhite char on the line. Do this before incrementing the line number, in case we're at the end of saved text. */ do c = getch (); while (c == ' ' || c == '\t'); lineno++; if (c != '#') { /* If not #, return it so caller will use it. */ return c; } /* Don't read beyond this line. */ linemode = 1; /* Read first nonwhite char after the `#'. */ do c = getch (); while (c == ' ' || c == '\t'); /* If a letter follows, then if the word here is `line', skip it and ignore it; otherwise, ignore the line, with an error if the word isn't `pragma'. */ if ((c >= 'a' && c <= '
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -