📄 cp-lex.c
字号:
static voidstore_pending_inline (decl, t) tree decl; struct pending_inline *t;{ extern int processing_template_defn; int delay_to_eof = 0; struct pending_inline **inlines; t->fndecl = decl; /* Default: compile right away, and no extra bindings are needed. */ t->parm_vec = t->bindings = 0; if (processing_template_defn) { tree type = current_class_type; /* Assumption: In this (possibly) nested class sequence, only one name will have template parms. */ while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't') { tree decl = TYPE_NAME (type); tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl)); if (tmpl) { t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec; t->bindings = TREE_VALUE (tmpl); } type = DECL_CONTEXT (decl); } if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) { if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type, 233); /* Inline functions can be compiled immediately. Other functions will be output separately, so if we're in interface-only mode, punt them now, or output them now if we're doing implementations and we know no overrides will exist. Otherwise, we delay until end-of-file, to see if the definition is really required. */ if (DECL_INLINE (decl)) /* delay_to_eof == 0 */; else if (current_class_type && !interface_unknown) { if (interface_only) {#if 0 print_node_brief (stderr, "\ndiscarding text for ", decl, 0);#endif if (t->can_free) obstack_free (&inline_text_obstack, t->buf); DECL_PENDING_INLINE_INFO (decl) = 0; return; } } /* Don't delay the processing of virtual functions. */ else if (DECL_VINDEX (decl) == NULL_TREE) delay_to_eof = 1; } else my_friendly_abort (58); } if (delay_to_eof) { extern struct pending_inline *pending_template_expansions; if (t->can_free) { char *free_to = t->buf; t->buf = (char *) obstack_copy (&permanent_obstack, t->buf, t->len + 1); t = (struct pending_inline *) obstack_copy (&permanent_obstack, (char *)t, sizeof (*t)); obstack_free (&inline_text_obstack, free_to); } inlines = &pending_template_expansions; t->can_free = 0; } else { inlines = &pending_inlines; DECL_PENDING_INLINE_INFO (decl) = t; } /* Because we use obstacks, we must process these in precise order. */ t->next = *inlines; *inlines = t;}void reinit_parse_for_block ();voidreinit_parse_for_method (yychar, decl) int yychar; tree decl;{ int len; int starting_lineno = lineno; char *starting_filename = input_filename; reinit_parse_for_block (yychar, &inline_text_obstack, 0); len = obstack_object_size (&inline_text_obstack); current_base_init_list = NULL_TREE; current_member_init_list = NULL_TREE; if (decl == void_type_node || (current_class_type && TYPE_REDEFINED (current_class_type))) { /* Happens when we get two declarations of the same function in the same scope. */ char *buf = obstack_finish (&inline_text_obstack); obstack_free (&inline_text_obstack, buf); return; } else { struct pending_inline *t; char *buf = obstack_finish (&inline_text_obstack); t = (struct pending_inline *) obstack_alloc (&inline_text_obstack, sizeof (struct pending_inline)); t->buf = buf; t->len = len; t->lineno = starting_lineno; t->filename = starting_filename; t->token = YYEMPTY; t->can_free = 1; t->deja_vu = 0; t->interface = ((interface_unknown || processing_template_defn) ? 1 : (interface_only ? 0 : 2)); store_pending_inline (decl, t); }}/* Consume a block -- actually, a method or template definition beginning with `:' or `{' -- and save it away on the specified obstack. Argument IS_TEMPLATE indicates which set of error messages should be output if something goes wrong. This should really be cleaned up somehow, without loss of clarity. */voidreinit_parse_for_block (yychar, obstackp, is_template) int yychar; struct obstack *obstackp; int is_template;{ register int c = 0; int blev = 1; int starting_lineno = lineno; char *starting_filename = input_filename; int len; int look_for_semicolon = 0; if (yychar == '{') obstack_1grow (obstackp, '{'); else if (yychar == '=') { look_for_semicolon = 1; } else { if (yychar != ':' && (yychar != RETURN || is_template)) { yyerror (is_template ? "parse error in template specification" : "parse error in method specification"); yychar = '{'; } obstack_1grow (obstackp, yychar); while (c >= 0) { int this_lineno = lineno; c = yynextch (); /* Don't lose our cool if there are lots of comments. */ if (lineno == this_lineno) ; else if (lineno - this_lineno < 10 /* + strlen (input_filename) */) { int i; for (i = lineno - this_lineno; i > 0; i--) obstack_1grow (obstackp, '\n'); } else { char buf[12]; sprintf (buf, "\n# %d \"", lineno); len = strlen (buf); obstack_grow (obstackp, buf, len); len = strlen (input_filename); obstack_grow (obstackp, input_filename, len); obstack_1grow (obstackp, '\"'); obstack_1grow (obstackp, '\n'); } /* strings must be read differently than text. */ if (c == '\"') { obstack_1grow (obstackp, c); consume_string (obstackp); c = yynextch (); } while (c > ' ') /* ASCII dependent! */ { obstack_1grow (obstackp, c); if (c == '{') goto main_loop; if (c == '\"') consume_string (obstackp); if (c == ';') { error (is_template ? "template body missing" : "function body for constructor missing"); obstack_1grow (obstackp, '{'); obstack_1grow (obstackp, '}'); len += 2; goto done; } c = getch (); } if (c == '\n') lineno++; obstack_1grow (obstackp, c); } if (c == EOF) { error_with_file_and_line (starting_filename, starting_lineno, "end of file read inside definition"); } } main_loop: while (c >= 0) { int this_lineno = lineno; c = skip_white_space (getch ()); /* Don't lose our cool if there are lots of comments. */ if (lineno - this_lineno) if (lineno - this_lineno == 1) obstack_1grow (obstackp, '\n'); else { char buf[12]; sprintf (buf, "\n# %d \"", lineno); len = strlen (buf); obstack_grow (obstackp, buf, len); len = strlen (input_filename); obstack_grow (obstackp, input_filename, len); obstack_1grow (obstackp, '\"'); obstack_1grow (obstackp, '\n'); } while (c > ' ') { obstack_1grow (obstackp, c); if (c == '{') blev++; else if (c == '}') { blev--; if (blev == 0 && !look_for_semicolon) goto done; } else if (c == '\"') consume_string (obstackp); else if (c == ';' && look_for_semicolon && blev == 0) goto done; c = getch (); } if (c == '\n') lineno++; obstack_1grow (obstackp, c); } done: obstack_1grow (obstackp, '\0');}/* 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. */treecons_up_default_function (type, name, kind) tree type, name; int kind;{ extern tree void_list_node, constructor_name (); int len; tree declspecs = NULL_TREE; tree fn, args; tree argtype; name = constructor_name (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); /* Fall through... */ case 2: /* Default constructor. */ args = void_list_node; break; case 3: type = build_type_variant (type, 1, 0); /* Fall through... */ case 4: argtype = build_reference_type (type); args = tree_cons (NULL_TREE, build_tree_list (hash_tree_chain (argtype, NULL_TREE), get_identifier ("arg")), void_list_node); break; default: my_friendly_abort (59); } fn = start_method (declspecs, build_parse_node (CALL_EXPR, name, args, NULL_TREE), NULL_TREE); if (fn == void_type_node) return fn; current_base_init_list = NULL_TREE; current_member_init_list = NULL_TREE; len = 3; { struct pending_inline *t; t = (struct pending_inline *) obstack_alloc (&inline_text_obstack, sizeof (struct pending_inline)); t->buf = default_def; t->len = len; t->lineno = lineno; t->filename = input_filename; t->token = YYEMPTY; t->can_free = 0; t->deja_vu = 0; t->interface = ((interface_unknown || processing_template_defn) ? 1 : (interface_only ? 0 : 2)); store_pending_inline (fn, t); /* We make this declaration private (static in the C sense). */ TREE_PUBLIC (fn) = 0; } finish_method (fn); DECL_CLASS_CONTEXT (fn) = type; /* Show that this function was generated by the compiler. */ DECL_SOURCE_LINE (fn) = 0; 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 != IDENTIFIER && yychar != TYPENAME) { if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) error ("semicolon missing after %s declaration", TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct"); else error ("semicolon missing after declaration of `%s'", TYPE_NAME_STRING (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':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -