📄 decl2.c
字号:
? "member function" : "type"); ctype = cp_build_qualified_type (ctype, type_quals); fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype), (TREE_CODE (fntype) == METHOD_TYPE ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) : TYPE_ARG_TYPES (fntype))); if (raises) fntype = build_exception_variant (fntype, raises); TREE_TYPE (function) = fntype; return ctype;}/* Warn when -fexternal-templates is used and #pragma interface/implementation is not used all the times it should be, inform the user. */voidwarn_if_unknown_interface (decl) tree decl;{ static int already_warned = 0; if (already_warned++) return; if (flag_alt_external_templates) { struct tinst_level *til = tinst_for_decl (); int sl = lineno; char *sf = input_filename; if (til) { lineno = til->line; input_filename = til->file; } cp_warning ("template `%#D' instantiated in file without #pragma interface", decl); lineno = sl; input_filename = sf; } else cp_warning_at ("template `%#D' defined in file without #pragma interface", decl);}/* A subroutine of the parser, to handle a component list. */voidgrok_x_components (specs) tree specs;{ struct pending_inline **p; tree t; specs = strip_attrs (specs); check_tag_decl (specs); t = groktypename (build_decl_list (specs, NULL_TREE)); /* The only case where we need to do anything additional here is an anonymous union field, e.g.: `struct S { union { int i; }; };'. */ if (t == NULL_TREE || !ANON_UNION_TYPE_P (t)) return; fixup_anonymous_union (t); finish_member_declaration (build_lang_field_decl (FIELD_DECL, NULL_TREE, t)); /* Ignore any inline function definitions in the anonymous union since an anonymous union may not have function members. */ p = &pending_inlines; for (; *p; *p = (*p)->next) if (DECL_CONTEXT ((*p)->fndecl) != t) break;}/* Constructors for types with virtual baseclasses need an "in-charge" flag saying whether this constructor is responsible for initialization of virtual baseclasses or not. All destructors also need this "in-charge" flag, which additionally determines whether or not the destructor should free the memory for the object. This function adds the "in-charge" flag to member function FN if appropriate. It is called from grokclassfn and tsubst. FN must be either a constructor or destructor. For vtable thunks, types with polymorphic virtual bases need an additional "vlist" argument which is an array of virtual tables. In addition, if backwards-compatibility to v1 thunks is requested, a wrapper constructor may be needed as well. */voidmaybe_retrofit_in_chrg (fn) tree fn;{ tree basetype, arg_types, parms, parm, fntype; tree wrapper; if (CLASSTYPE_IS_TEMPLATE (DECL_CLASS_CONTEXT (fn))) /* Never retrofit arguments on template methods. */ return; if (DECL_CONSTRUCTOR_P (fn) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) && DECL_CONSTRUCTOR_FOR_VBASE (fn) == 0) /* OK */; else if (! DECL_CONSTRUCTOR_P (fn) && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) /* OK */; else return; if (DECL_CONSTRUCTOR_P (fn)) { if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) { DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE; if (flag_vtable_thunks_compat && varargs_function_p (fn)) sorry ("-fvtable-thunks=2 for vararg constructor", fn); } else DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE; } else if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) DECL_CONSTRUCTOR_FOR_VBASE (fn) = DESTRUCTOR_FOR_PVBASE; /* Retrieve the arguments, because it is potentially modified twice. */ arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); basetype = TREE_TYPE (TREE_VALUE (arg_types)); arg_types = TREE_CHAIN (arg_types); if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fn) || DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) { /* Add the __vlist argument first. See __in_chrg below. */ tree id = vlist_identifier; if (DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) id = get_identifier (VLIST1_NAME); parm = build_decl (PARM_DECL, id, vlist_type_node); SET_DECL_ARTIFICIAL (parm); DECL_ARG_TYPE (parm) = vlist_type_node; parms = DECL_ARGUMENTS (fn); /* Add it after 'this'. */ TREE_CHAIN (parm) = TREE_CHAIN (parms); TREE_CHAIN (parms) = parm; arg_types = hash_tree_chain (vlist_type_node, arg_types); } /* First add it to DECL_ARGUMENTS... */ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); /* Mark the artificial `__in_chrg' parameter as "artificial". */ SET_DECL_ARTIFICIAL (parm); DECL_ARG_TYPE (parm) = integer_type_node; TREE_READONLY (parm) = 1; parms = DECL_ARGUMENTS (fn); TREE_CHAIN (parm) = TREE_CHAIN (parms); TREE_CHAIN (parms) = parm; /* ...and then to TYPE_ARG_TYPES. */ arg_types = hash_tree_chain (integer_type_node, arg_types); fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), arg_types); if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) fntype = build_exception_variant (fntype, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); TREE_TYPE (fn) = fntype;}/* Classes overload their constituent function names automatically. When a function name is declared in a record structure, its name is changed to it overloaded name. Since names for constructors and destructors can conflict, we place a leading '$' for destructors. CNAME is the name of the class we are grokking for. FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'. FLAGS contains bits saying what's special about today's arguments. 1 == DESTRUCTOR. 2 == OPERATOR. If FUNCTION is a destructor, then we must add the `auto-delete' field as a second parameter. There is some hair associated with the fact that we must "declare" this variable in the manner consistent with the way the rest of the arguments were declared. QUALS are the qualifiers for the this pointer. */voidgrokclassfn (ctype, function, flags, quals) tree ctype, function; enum overload_flags flags; tree quals;{ tree fn_name = DECL_NAME (function); tree arg_types; tree parm; tree qualtype; if (fn_name == NULL_TREE) { error ("name missing for member function"); fn_name = get_identifier ("<anonymous>"); DECL_NAME (function) = fn_name; } if (quals) qualtype = grok_method_quals (ctype, function, quals); else qualtype = ctype; arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) { /* Must add the class instance variable up front. */ /* Right now we just make this a pointer. But later we may wish to make it special. */ tree type = TREE_VALUE (arg_types); int constp = 1; if ((flag_this_is_variable > 0) && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))) constp = 0; parm = build_decl (PARM_DECL, this_identifier, type); /* Mark the artificial `this' parameter as "artificial". */ SET_DECL_ARTIFICIAL (parm); DECL_ARG_TYPE (parm) = type; /* We can make this a register, so long as we don't accidentally complain if someone tries to take its address. */ DECL_REGISTER (parm) = 1; if (constp) TREE_READONLY (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; } DECL_ARGUMENTS (function) = last_function_parms; /* First approximations. */ DECL_CONTEXT (function) = ctype; DECL_CLASS_CONTEXT (function) = ctype; if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)) { maybe_retrofit_in_chrg (function); arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); } if (flags == DTOR_FLAG) { DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype, DECL_DESTRUCTOR_FOR_PVBASE_P (function)); TYPE_HAS_DESTRUCTOR (ctype) = 1; } else set_mangled_name_for_decl (function);}/* Work on the expr used by alignof (this is only called by the parser). */treegrok_alignof (expr) tree expr;{ tree best, t; int bestalign; if (processing_template_decl) return build_min (ALIGNOF_EXPR, sizetype, expr); if (TREE_CODE (expr) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))) error ("`__alignof__' applied to a bit-field"); if (TREE_CODE (expr) == INDIRECT_REF) { best = t = TREE_OPERAND (expr, 0); bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); while (TREE_CODE (t) == NOP_EXPR && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) { int thisalign; t = TREE_OPERAND (t, 0); thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); if (thisalign > bestalign) best = t, bestalign = thisalign; } return c_alignof (TREE_TYPE (TREE_TYPE (best))); } else { /* ANSI says arrays and fns are converted inside comma. But we can't convert them in build_compound_expr because that would break commas in lvalues. So do the conversion here if operand was a comma. */ if (TREE_CODE (expr) == COMPOUND_EXPR && (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) expr = default_conversion (expr); return c_alignof (TREE_TYPE (expr)); }}/* Create an ARRAY_REF, checking for the user doing things backwards along the way. */treegrok_array_decl (array_expr, index_exp) tree array_expr, index_exp;{ tree type = TREE_TYPE (array_expr); tree p1, p2, i1, i2; if (type == error_mark_node || index_exp == error_mark_node) return error_mark_node; if (processing_template_decl) return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE, array_expr, index_exp); if (type == NULL_TREE) { /* Something has gone very wrong. Assume we are mistakenly reducing an expression instead of a declaration. */ error ("parser may be lost: is there a '{' missing somewhere?"); return NULL_TREE; } if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); /* If they have an `operator[]', use that. */ if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp))) return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, NULL_TREE); /* Otherwise, create an ARRAY_REF for a pointer or array type. It is a little-known fact that, if `a' is an array and `i' is an int, you can write `i[a]', which means the same thing as `a[i]'. */ if (TREE_CODE (type) == ARRAY_TYPE) p1 = array_expr; else p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0); if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE) p2 = index_exp; else p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0); i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0); i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0); if ((p1 && i2) && (i1 && p2)) error ("ambiguous conversion for array subscript"); if (p1 && i2) array_expr = p1, index_exp = i2; else if (i1 && p2) array_expr = p2, index_exp = i1; else { cp_error ("invalid types `%T[%T]' for array subscript", type, TREE_TYPE (index_exp)); return error_mark_node; } if (array_expr == error_mark_node || index_exp == error_mark_node) error ("ambiguous conversion for array subscript"); return build_array_ref (array_expr, index_exp);}/* Given the cast expression EXP, checking out its validity. Either return an error_mark_node if there was an unavoidable error, return a cast to void for trying to delete a pointer w/ the value 0, or return the call to delete. If DOING_VEC is 1, we handle things differently for doing an array delete. If DOING_VEC is 2, they gave us the array size as an argument to delete. Implements ARM $5.3.4. This is called from the parser. */treedelete_sanity (exp, size, doing_vec, use_global_delete) tree exp, size; int doing_vec, use_global_delete;{ tree t, type; /* For a regular vector delete (aka, no size argument) we will pass this down as a NULL_TREE into build_vec_delete. */ tree maxindex = NULL_TREE; if (exp == error_mark_node) return exp; if (processing_template_decl) { t = build_min (DELETE_EXPR, void_type_node, exp, size); DELETE_EXPR_USE_GLOBAL (t) = use_global_delete; DELETE_EXPR_USE_VEC (t) = doing_vec; return t; } if (TREE_CODE (exp) == OFFSET_REF) exp = resolve_offset_ref (exp); exp = convert_from_reference (exp); t = stabilize_reference (exp); t = build_expr_type_conversion (WANT_POINTER, t, 1); if (t == NULL_TREE || t == error_mark_node) { cp_error ("type `%#T' argument given to `delete', expected pointer", TREE_TYPE (exp)); return error_mark_node; } if (doing_vec == 2) { maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node); pedwarn ("anachronistic use of array size in vector delete"); } type = TREE_TYPE (t); /* As of Valley Forge, you can delete a pointer to const. */ /* You can't delete functions. */ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -