📄 decl2.c
字号:
C++: If class A defines that certain functions in class B are friends, then the way I have set things up, it is B who is interested in permission granted by A. However, it is in A's context that these declarations are parsed. By returning a void_type_node, class A does not attempt to incorporate the declarations of the friends within its structure. DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING CHANGES TO CODE IN `start_method'. */treegrokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist) tree declarator, declspecs, raises, init, asmspec_tree, attrlist;{ register tree value; char *asmspec = 0; int flags = LOOKUP_ONLYCONVERTING; /* Convert () initializers to = initializers. */ if (init == NULL_TREE && declarator != NULL_TREE && TREE_CODE (declarator) == CALL_EXPR && TREE_OPERAND (declarator, 0) && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF) && parmlist_is_exprlist (TREE_OPERAND (declarator, 1))) { init = TREE_OPERAND (declarator, 1); declarator = TREE_OPERAND (declarator, 0); flags = 0; } if (init && TREE_CODE (init) == TREE_LIST && TREE_VALUE (init) == error_mark_node && TREE_CHAIN (init) == NULL_TREE) init = NULL_TREE; value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises, attrlist); if (! value) return value; /* friend or constructor went bad. */ /* Pass friendly classes back. */ if (TREE_CODE (value) == VOID_TYPE) return void_type_node; if (DECL_NAME (value) != NULL_TREE && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) cp_error ("member `%D' conflicts with virtual function table field name", value); /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) { DECL_NONLOCAL (value) = 1; DECL_CONTEXT (value) = current_class_type; DECL_CLASS_CONTEXT (value) = current_class_type; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; /* If we declare a typedef name for something that has no name, the typedef name is used for linkage. See 7.1.3 p4 94/0158. */ if (TYPE_NAME (TREE_TYPE (value)) && TREE_CODE (TYPE_NAME (TREE_TYPE (value))) == TYPE_DECL && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (value)))) { TYPE_NAME (TREE_TYPE (value)) = value; TYPE_STUB_DECL (TREE_TYPE (value)) = value; } pushdecl_class_level (value); return value; } if (IS_SIGNATURE (current_class_type) && TREE_CODE (value) != FUNCTION_DECL) { error ("field declaration not allowed in signature"); return void_type_node; } if (DECL_IN_AGGR_P (value)) { cp_error ("`%D' is already defined in the class %T", value, 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) { if (IS_SIGNATURE (current_class_type) && TREE_CODE (value) == FUNCTION_DECL) { error ("function declarations cannot have initializers in signature"); init = NULL_TREE; } else if (TREE_CODE (value) == FUNCTION_DECL) { grok_function_init (value, init); init = NULL_TREE; } else if (pedantic && TREE_CODE (value) != VAR_DECL) /* Already complained in grokdeclarator. */ 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, (tree *)0); } 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, (tree *)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 cp_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 cp_finish_decl to do the right thing, namely, to put this decl out straight away. */ if (TREE_PUBLIC (value)) { /* current_class_type can be NULL_TREE in case of error. */ if (asmspec == 0 && current_class_type) { TREE_PUBLIC (value) = 1; DECL_INITIAL (value) = error_mark_node; DECL_ASSEMBLER_NAME (value) = build_static_name (current_class_type, DECL_NAME (value)); } 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; cp_finish_decl (value, init, asmspec_tree, 1, flags); pushdecl_class_level (value); return value; } if (TREE_CODE (value) == FIELD_DECL) { if (asmspec) { /* This must override the asm specifier which was placed by grokclassfn. Lay this out fresh. */ DECL_RTL (value) = NULL_RTX; DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); } if (DECL_INITIAL (value) == error_mark_node) init = error_mark_node; cp_finish_decl (value, init, asmspec_tree, 1, flags); DECL_INITIAL (value) = init; DECL_IN_AGGR_P (value) = 1; return value; } if (TREE_CODE (value) == FUNCTION_DECL) { check_default_args (value); 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); } if (asmspec) { /* This must override the asm specifier which was placed by grokclassfn. Lay this out fresh. */ DECL_RTL (value) = NULL_RTX; DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); } cp_finish_decl (value, init, asmspec_tree, 1, flags); /* Pass friends back this way. */ if (DECL_FRIEND_P (value)) return void_type_node;#if 0 /* Just because a fn is declared doesn't mean we'll try to define it. */ if (current_function_decl && ! IS_SIGNATURE (current_class_type)) cp_error ("method `%#D' of local class must be defined in class body", value);#endif 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, 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) { cp_error ("cannot declare `%D' to be a bitfield type", value); return NULL_TREE; } if (IS_SIGNATURE (current_class_type)) { error ("field declaration not allowed in signature"); return void_type_node; } if (DECL_IN_AGGR_P (value)) { cp_error ("`%D' is already defined in the class %T", value, DECL_CONTEXT (value)); return void_type_node; } GNU_xref_member (current_class_name, value); if (TREE_STATIC (value)) { cp_error ("static member `%D' cannot be a bitfield", value); return NULL_TREE; } cp_finish_decl (value, NULL_TREE, NULL_TREE, 0, 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) { cp_error ("structure field `%D' width not an integer constant", value); DECL_INITIAL (value) = NULL_TREE; } else { constant_expression_warning (width); DECL_INITIAL (value) = width; DECL_BIT_FIELD (value) = 1; } } DECL_IN_AGGR_P (value) = 1; return value;}#if 0/* 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_abort (194); spec = TREE_CHAIN (spec); } if (type_id) declspecs = chainon (lengths, quals); else if (lengths) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -