📄 cp-decl2.c
字号:
&& IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) error_with_decl (value, "member `%s' conflicts with virtual function table field name"); /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) { DECL_NONLOCAL (value) = 1; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; pushdecl_class_level (value); return value; } if (DECL_IN_AGGR_P (value)) { error_with_decl (value, "`%s' is already defined in the class %s", TYPE_NAME_STRING (DECL_CONTEXT (value))); return void_type_node; } if (flag_cadillac) cadillac_start_decl (value); if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); if (init != 0) { if (TREE_CODE (value) == FUNCTION_DECL) { grok_function_init (value, init); init = NULL_TREE; } else if (pedantic) { error ("fields cannot have initializers"); init = NULL_TREE; } else { /* We allow initializers to become parameters to base initializers. */ if (TREE_CODE (init) == TREE_LIST) { if (TREE_CHAIN (init) == NULL_TREE) init = TREE_VALUE (init); else init = digest_init (TREE_TYPE (value), init, 0, 1, 0, "field declaration"); } if (TREE_CODE (init) == CONST_DECL) init = DECL_INITIAL (init); else if (TREE_READONLY_DECL_P (init)) init = decl_constant_value (init); else if (TREE_CODE (init) == CONSTRUCTOR) init = digest_init (TREE_TYPE (value), init, 0); my_friendly_assert (TREE_PERMANENT (init), 192); if (init == error_mark_node) /* We must make this look different than `error_mark_node' because `decl_const_value' would mis-interpret it as only meaning that this VAR_DECL is defined. */ init = build1 (NOP_EXPR, TREE_TYPE (value), init); else if (! TREE_CONSTANT (init)) { /* We can allow references to things that are effectively static, since references are initialized with the address. */ if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE || (TREE_STATIC (init) == 0 && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd' || DECL_EXTERNAL (init) == 0))) { error ("field initializer is not constant"); init = error_mark_node; } } } } /* The corresponding pop_obstacks is in finish_decl. */ push_obstacks_nochange (); if (TREE_CODE (value) == VAR_DECL) { /* We cannot call pushdecl here, because that would fill in the value of our TREE_CHAIN. Instead, we modify finish_decl to do the right thing, namely, to put this decl out straight away. */ if (TREE_STATIC (value)) { /* current_class_type can be NULL_TREE in case of error. */ if (asmspec == 0 && current_class_type) { tree name; char *buf, *buf2; buf2 = build_overload_name (current_class_type, 1, 1); buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (value)) + sizeof (STATIC_NAME_FORMAT) + strlen (buf2)); sprintf (buf, STATIC_NAME_FORMAT, buf2, IDENTIFIER_POINTER (DECL_NAME (value))); name = get_identifier (buf); TREE_PUBLIC (value) = 1; DECL_INITIAL (value) = error_mark_node; DECL_ASSEMBLER_NAME (value) = name; } pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); /* Static consts need not be initialized in the class definition. */ if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value))) { static int explanation = 0; error ("initializer invalid for static member with constructor"); if (explanation++ == 0) error ("(you really want to initialize it separately)"); init = 0; } /* Force the compiler to know when an uninitialized static const member is being used. */ if (TYPE_READONLY (value) && init == 0) TREE_USED (value) = 1; } DECL_INITIAL (value) = init; DECL_IN_AGGR_P (value) = 1; finish_decl (value, init, asmspec_tree, 1); pushdecl_class_level (value); return value; } if (TREE_CODE (value) == FIELD_DECL) { if (asmspec) DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); if (DECL_INITIAL (value) == error_mark_node) init = error_mark_node; finish_decl (value, init, asmspec_tree, 1); DECL_INITIAL (value) = init; DECL_IN_AGGR_P (value) = 1; return value; } if (TREE_CODE (value) == FUNCTION_DECL) { /* grokdeclarator defers setting this. */ TREE_PUBLIC (value) = 1; if (DECL_CHAIN (value) != NULL_TREE) { /* Need a fresh node here so that we don't get circularity when we link these together. */ value = copy_node (value); /* When does this happen? */ my_friendly_assert (init == NULL_TREE, 193); } finish_decl (value, init, asmspec_tree, 1); /* Pass friends back this way. */ if (DECL_FRIEND_P (value)) return void_type_node; DECL_IN_AGGR_P (value) = 1; return value; } my_friendly_abort (21); /* NOTREACHED */ return NULL_TREE;}/* Like `grokfield', but for bitfields. WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */treegrokbitfield (declarator, declspecs, width) tree declarator, declspecs, width;{ register tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL_TREE); if (! value) return NULL_TREE; /* friends went bad. */ /* Pass friendly classes back. */ if (TREE_CODE (value) == VOID_TYPE) return void_type_node; if (TREE_CODE (value) == TYPE_DECL) { error_with_decl (value, "cannot declare `%s' to be a bitfield type"); return NULL_TREE; } if (DECL_IN_AGGR_P (value)) { error_with_decl (value, "`%s' is already defined in the class %s", TYPE_NAME_STRING (DECL_CONTEXT (value))); return void_type_node; } GNU_xref_member (current_class_name, value); if (TREE_STATIC (value)) { error_with_decl (value, "static member `%s' cannot be a bitfield"); return NULL_TREE; } finish_decl (value, NULL_TREE, NULL_TREE, 0); if (width != error_mark_node) { /* detect invalid field size. */ if (TREE_CODE (width) == CONST_DECL) width = DECL_INITIAL (width); else if (TREE_READONLY_DECL_P (width)) width = decl_constant_value (width); if (TREE_CODE (width) != INTEGER_CST) { error_with_decl (value, "structure field `%s' width not an integer constant"); DECL_INITIAL (value) = NULL_TREE; } else { DECL_INITIAL (value) = width; DECL_BIT_FIELD (value) = 1; } } DECL_IN_AGGR_P (value) = 1; return value;}/* Like GROKFIELD, except that the declarator has been buried in DECLSPECS. Find the declarator, and return something that looks like it came from GROKFIELD. */treegroktypefield (declspecs, parmlist) tree declspecs; tree parmlist;{ tree spec = declspecs; tree prev = NULL_TREE; tree type_id = NULL_TREE; tree quals = NULL_TREE; tree lengths = NULL_TREE; tree decl = NULL_TREE; while (spec) { register tree id = TREE_VALUE (spec); if (TREE_CODE (spec) != TREE_LIST) /* Certain parse errors slip through. For example, `int class ();' is not caught by the parser. Try weakly to recover here. */ return NULL_TREE; if (TREE_CODE (id) == TYPE_DECL || (TREE_CODE (id) == IDENTIFIER_NODE && TREE_TYPE (id))) { /* We have a constructor/destructor or conversion operator. Use it. */ if (prev) TREE_CHAIN (prev) = TREE_CHAIN (spec); else declspecs = TREE_CHAIN (spec); type_id = id; goto found; } prev = spec; spec = TREE_CHAIN (spec); } /* Nope, we have a conversion operator to a scalar type or something else, that includes things like constructor declarations for templates. */ spec = declspecs; while (spec) { tree id = TREE_VALUE (spec); if (TREE_CODE (id) == IDENTIFIER_NODE) { if (id == ridpointers[(int)RID_INT] || id == ridpointers[(int)RID_DOUBLE] || id == ridpointers[(int)RID_FLOAT] || id == ridpointers[(int)RID_WCHAR]) { if (type_id) error ("extra `%s' ignored", IDENTIFIER_POINTER (id)); else type_id = id; } else if (id == ridpointers[(int)RID_LONG] || id == ridpointers[(int)RID_SHORT] || id == ridpointers[(int)RID_CHAR]) { lengths = tree_cons (NULL_TREE, id, lengths); } else if (id == ridpointers[(int)RID_VOID]) { if (type_id) error ("spurious `void' type ignored"); else error ("conversion to `void' type invalid"); } else if (id == ridpointers[(int)RID_AUTO] || id == ridpointers[(int)RID_REGISTER] || id == ridpointers[(int)RID_TYPEDEF] || id == ridpointers[(int)RID_CONST] || id == ridpointers[(int)RID_VOLATILE]) { error ("type specifier `%s' used invalidly", IDENTIFIER_POINTER (id)); } else if (id == ridpointers[(int)RID_FRIEND] || id == ridpointers[(int)RID_VIRTUAL] || id == ridpointers[(int)RID_INLINE] || id == ridpointers[(int)RID_UNSIGNED] || id == ridpointers[(int)RID_SIGNED] || id == ridpointers[(int)RID_STATIC] || id == ridpointers[(int)RID_EXTERN]) { quals = tree_cons (NULL_TREE, id, quals); } else { /* Happens when we have a global typedef and a class-local member function with the same name. */ type_id = id; goto found; } } else if (TREE_CODE (id) == RECORD_TYPE) { type_id = TYPE_NAME (id); if (TREE_CODE (type_id) == TYPE_DECL) type_id = DECL_NAME (type_id); if (type_id == NULL_TREE) error ("identifier for aggregate type conversion omitted"); } else if (TREE_CODE_CLASS (TREE_CODE (id)) == 't') { error ("`operator' missing on conversion operator or tag missing from type"); } else my_friendly_assert (0, 194); spec = TREE_CHAIN (spec); } if (type_id) { declspecs = chainon (lengths, quals); } else if (lengths) { if (TREE_CHAIN (lengths)) error ("multiple length specifiers"); type_id = ridpointers[(int)RID_INT]; declspecs = chainon (lengths, quals); } else if (quals) { error ("no type given, defaulting to `operator int ...'"); type_id = ridpointers[(int)RID_INT]; declspecs = quals; } else return NULL_TREE; found: decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE), declspecs, FIELD, 0, NULL_TREE); if (decl == NULL_TREE) return NULL_TREE; if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CHAIN (decl) != NULL_TREE) { /* Need a fresh node here so that we don't get circularity when we link these together. */ decl = copy_node (decl); } if (decl == void_type_node || (TREE_CODE (decl) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (decl)) != METHOD_TYPE)) /* bunch of friends. */ return decl; if (DECL_IN_AGGR_P (decl)) { error_with_decl (decl, "`%s' already defined in the class "); return void_type_node; } finish_decl (decl, NULL_TREE, NULL_TREE, 0); /* If this declaration is common to another declaration complain about such redundancy, and return NULL_TREE so that we don't build a circular list. */ if (DECL_CHAIN (decl)) { error_with_decl (decl, "function `%s' declared twice in class %s", TYPE_NAME_STRING (DECL_CONTEXT (decl))); return NULL_TREE; } DECL_IN_AGGR_P (decl) = 1; return decl;}/* The precedence rules of this grammar (or any other deterministic LALR grammar, for that matter), place the CALL_EXPR somewhere where we may not want it. The solution is to grab the first CALL_EXPR we see, pretend that that is the one that belongs to the parameter list of the type conversion function, and leave everything else alone. We pull it out in place. CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR does not appear in DECL. */treegrokoptypename (decl, call_required) tree decl; int call_required;{ tree tmp, last; my_friendly_assert (TREE_CODE (decl) == TYPE_EXPR, 195); tmp = TREE_OPERAND (decl, 0); last = NULL_TREE; while (tmp) { switch (TREE_CODE (tmp)) { case CALL_EXPR: { tree parms = TREE_OPERAND (tmp, 1); if (last) TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0); else TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0); if (parms
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -