📄 decl2.c
字号:
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, 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)) { cp_error ("`%D' already defined in the class ", decl); return void_type_node; } cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 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)) { cp_error ("function `%D' declared twice in class %T", decl, DECL_CONTEXT (decl)); return NULL_TREE; } DECL_IN_AGGR_P (decl) = 1; return decl;}#endiftreegrokoptypename (declspecs, declarator) tree declspecs, declarator;{ tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE, NULL_TREE); return build_typename_overload (t);}/* When a function is declared with an initializer, do the right thing. Currently, there are two possibilities: class B { public: // initialization possibility #1. virtual void f () = 0; int g (); }; class D1 : B { public: int d1; // error, no f (); }; class D2 : B { public: int d2; void f (); }; class D3 : B { public: int d3; // initialization possibility #2 void f () = B::f; };*/intcopy_assignment_arg_p (parmtype, virtualp) tree parmtype; int virtualp;{ if (TREE_CODE (parmtype) == REFERENCE_TYPE) parmtype = TREE_TYPE (parmtype); if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type) || (virtualp && DERIVED_FROM_P (parmtype, current_class_type))) return 1; return 0;}static voidgrok_function_init (decl, init) tree decl; tree init;{ /* An initializer for a function tells how this function should be inherited. */ tree type = TREE_TYPE (decl); if (TREE_CODE (type) == FUNCTION_TYPE) cp_error ("initializer specified for non-member function `%D'", decl); else if (DECL_VINDEX (decl) == NULL_TREE) cp_error ("initializer specified for non-virtual method `%D'", decl); else if (integer_zerop (init)) {#if 0 /* Mark this function as being "defined". */ DECL_INITIAL (decl) = error_mark_node; /* pure virtual destructors must be defined. */ /* pure virtual needs to be defined (as abort) only when put in vtbl. For wellformed call, it should be itself. pr4737 */ if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))) { extern tree abort_fndecl; /* Give this node rtl from `abort'. */ DECL_RTL (decl) = DECL_RTL (abort_fndecl); }#endif DECL_ABSTRACT_VIRTUAL_P (decl) = 1; if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR]) { tree parmtype = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))); if (copy_assignment_arg_p (parmtype, 1)) TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1; } } else if (TREE_CODE (init) == OFFSET_REF && TREE_OPERAND (init, 0) == NULL_TREE && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE) { tree basetype = DECL_CLASS_CONTEXT (init); tree basefn = TREE_OPERAND (init, 1); if (TREE_CODE (basefn) != FUNCTION_DECL) cp_error ("non-method initializer invalid for method `%D'", decl); else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn)))) sorry ("base member function from other than first base class"); else { tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1); if (binfo == error_mark_node) ; else if (binfo == 0) error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)), TYPE_METHOD_BASETYPE (type)); else { /* Mark this function as being defined, and give it new rtl. */ DECL_INITIAL (decl) = error_mark_node; DECL_RTL (decl) = DECL_RTL (basefn); } } } else cp_error ("invalid initializer for virtual method `%D'", decl);}/* When we get a declaration of the form type cname::fname ... the node for `cname::fname' gets built here in a special way. Namely, we push into `cname's scope. When this declaration is processed, we pop back out. */treebuild_push_scope (cname, name) tree cname; tree name;{ extern int current_class_depth; tree ctype, rval; int is_ttp = 0; if (cname == error_mark_node) return error_mark_node; ctype = IDENTIFIER_TYPE_VALUE (cname); if (TREE_CODE (ctype) == TEMPLATE_TYPE_PARM) is_ttp = 1; else if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype)) { cp_error ("`%T' not defined as aggregate type", cname); return name; } else if (IS_SIGNATURE (ctype)) { error ("cannot push into signature scope, scope resolution operator ignored"); return name; } rval = build_parse_node (SCOPE_REF, cname, name); /* Don't need to push the scope if we're already in it. We also don't need to push the scope for a ptr-to-member/method. */ if (ctype == current_class_type || TREE_CODE (name) != IDENTIFIER_NODE || is_ttp) return rval; /* We do need to push the scope in this case, since CTYPE helps determine subsequent initializers (i.e., Foo::Bar x = foo_enum_1;). */ push_nested_class (ctype, 3); TREE_COMPLEXITY (rval) = current_class_depth; return rval;}voidcplus_decl_attributes (decl, attributes, prefix_attributes) tree decl, attributes, prefix_attributes;{ if (decl == NULL_TREE || decl == void_type_node) return; if (TREE_CODE (decl) == TEMPLATE_DECL) decl = DECL_TEMPLATE_RESULT (decl); decl_attributes (decl, attributes, prefix_attributes); if (TREE_CODE (decl) == TYPE_DECL) SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (decl), TREE_TYPE (decl));}/* CONSTRUCTOR_NAME: Return the name for the constructor (or destructor) for the specified class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. When given a template, this routine doesn't lose the specialization. */treeconstructor_name_full (thing) tree thing;{ if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE) return DECL_NAME (UPT_TEMPLATE (thing)); if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) { if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) thing = DECL_NAME (TREE_VEC_ELT (TYPE_METHODS (thing), 0)); else thing = TYPE_NAME (thing); } if (TREE_CODE (thing) == TYPE_DECL || (TREE_CODE (thing) == TEMPLATE_DECL && DECL_TEMPLATE_IS_CLASS (thing))) thing = DECL_NAME (thing); my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197); return thing;}/* CONSTRUCTOR_NAME: Return the name for the constructor (or destructor) for the specified class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. When given a template, return the plain unspecialized name. */treeconstructor_name (thing) tree thing;{ tree t; thing = constructor_name_full (thing); t = IDENTIFIER_TEMPLATE (thing); if (!t) return thing; t = TREE_PURPOSE (t); return DECL_NAME (t);}/* Cache the value of this class's main virtual function table pointer in a register variable. This will save one indirection if a more than one virtual function call is made this function. */voidsetup_vtbl_ptr (){ extern tree base_init_expr; if (base_init_expr == 0 && DECL_CONSTRUCTOR_P (current_function_decl)) emit_base_init (current_class_type, 0);}/* Record the existence of an addressable inline function. */voidmark_inline_for_output (decl) tree decl;{ decl = DECL_MAIN_VARIANT (decl); if (DECL_SAVED_INLINE (decl)) return; my_friendly_assert (TREE_PERMANENT (decl), 363); DECL_SAVED_INLINE (decl) = 1;#if 0 if (DECL_PENDING_INLINE_INFO (decl) != 0 && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu) { struct pending_inline *t = pending_inlines; my_friendly_assert (DECL_SAVED_INSNS (decl) == 0, 198); while (t) { if (t == DECL_PENDING_INLINE_INFO (decl)) break; t = t->next; } if (t == 0) { t = DECL_PENDING_INLINE_INFO (decl); t->next = pending_inlines; pending_inlines = t; } DECL_PENDING_INLINE_INFO (decl) = 0; }#endif saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_inlines);}voidclear_temp_name (){ temp_name_counter = 0;}/* Hand off a unique name which can be used for variable we don't really want to know about anyway, for example, the anonymous variables which are needed to make references work. Declare this thing so we can use it. The variable created will be of type TYPE. STATICP is nonzero if this variable should be static. */treeget_temp_name (type, staticp) tree type; int staticp;{ char buf[sizeof (AUTO_TEMP_FORMAT) + 20]; tree decl; int toplev = toplevel_bindings_p (); push_obstacks_nochange (); if (toplev || staticp) { end_temporary_allocation (); sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++); decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type)); } else { sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++); decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type)); } TREE_USED (decl) = 1; TREE_STATIC (decl) = staticp; /* If this is a local variable, then lay out its rtl now. Otherwise, callers of this function are responsible for dealing with this variable's rtl. */ if (! toplev) { expand_decl (decl); expand_decl_init (decl); } pop_obstacks (); return decl;}/* Get a variable which we can use for multiple assignments. It is not entered into current_binding_level, because that breaks things when it comes time to do final cleanups (which take place "outside" the binding contour of the function). */treeget_temp_regvar (type, init) tree type, init;{ static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' }; tree decl; sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++); decl = build_decl (VAR_DECL, get_identifier (buf), type); TREE_USED (decl) = 1; DECL_REGISTER (decl) = 1; if (init) store_init_value (decl, init); /* We can expand these without fear, since they cannot need constructors or destructors. */ expand_decl (decl); expand_decl_init (decl); if (type_needs_gc_entry (type)) DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index); return decl;}/* Make the macro TEMP_NAME_P available to units which do not include c-tree.h. */inttemp_name_p (decl) tree decl;{ return TEMP_NAME_P (decl);}/* Finish off the processing of a UNION_TYPE structure. If there are static members, then all members are static, and must be laid out together. If the union is an anonymous union, we arrange for that as well. PUBLIC_P is nonzero if this union is not declared static. */voidfinish_anon_union (anon_union_decl) tree anon_union_decl;{ tree
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -