📄 decl2.c
字号:
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; if (DECL_CONSTRUCTOR_P (function)) { if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) { DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1; /* In this case we need "in-charge" flag saying whether this constructor is responsible for initialization of virtual baseclasses or not. */ 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; DECL_REGISTER (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; } } 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; } if (flags == DTOR_FLAG) { char *buf, *dbuf; tree const_integer_type = build_type_variant (integer_type_node, 1, 0); int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1; arg_types = hash_tree_chain (const_integer_type, void_list_node); TREE_SIDE_EFFECTS (arg_types) = 1; /* Build the overload name. It will look like `7Example'. */ if (IDENTIFIER_TYPE_VALUE (cname)) dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1); else if (IDENTIFIER_LOCAL_VALUE (cname)) dbuf = build_overload_name (TREE_TYPE (IDENTIFIER_LOCAL_VALUE (cname)), 1, 1); else /* Using ctype fixes the `X::Y::~Y()' crash. The cname has no type when it's defined out of the class definition, since poplevel_class wipes it out. This used to be internal error 346. */ dbuf = build_overload_name (ctype, 1, 1); buf = (char *) alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX)); bcopy (DESTRUCTOR_DECL_PREFIX, buf, len); buf[len] = '\0'; strcat (buf, dbuf); DECL_ASSEMBLER_NAME (function) = get_identifier (buf); parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type); /* Mark the artificial `__in_chrg' parameter as "artificial". */ SET_DECL_ARTIFICIAL (parm); TREE_USED (parm) = 1;#if 0 /* We don't need to mark the __in_chrg parameter itself as `const' since its type is already `const int'. In fact we MUST NOT mark it as `const' cuz that will screw up the debug info (causing it to say that the type of __in_chrg is `const const int'). */ TREE_READONLY (parm) = 1;#endif DECL_ARG_TYPE (parm) = const_integer_type; /* This is the same chain as DECL_ARGUMENTS (...). */ TREE_CHAIN (last_function_parms) = parm; fntype = build_cplus_method_type (qualtype, void_type_node, arg_types); if (raises) { fntype = build_exception_variant (fntype, raises); } TREE_TYPE (function) = fntype; TYPE_HAS_DESTRUCTOR (ctype) = 1; } else { tree these_arg_types; if (DECL_CONSTRUCTOR_FOR_VBASE_P (function)) { arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); fntype = build_cplus_method_type (qualtype, TREE_TYPE (TREE_TYPE (function)), arg_types); if (raises) { fntype = build_exception_variant (fntype, raises); } TREE_TYPE (function) = fntype; arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); } these_arg_types = arg_types; if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) /* Only true for static member functions. */ these_arg_types = hash_tree_chain (build_pointer_type (qualtype), arg_types); DECL_ASSEMBLER_NAME (function) = build_decl_overload (fn_name, these_arg_types, 1 + DECL_CONSTRUCTOR_P (function));#if 0 /* This code is going into the compiler, but currently, it makes libg++/src/Integer.cc not compile. The problem is that the nice name winds up going into the symbol table, and conversion operations look for the manged name. */ substitute_nice_name (function);#endif } DECL_ARGUMENTS (function) = last_function_parms; /* First approximations. */ DECL_CONTEXT (function) = ctype; DECL_CLASS_CONTEXT (function) = ctype;}/* 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 (TREE_CODE (expr) == COMPONENT_REF && DECL_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 (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 (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_ARRAY_REF (type)) return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, NULL_TREE); /* Otherwise, create an ARRAY_REF for a pointer or array type. */ 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 = stabilize_reference (convert_from_reference (exp)); tree type = TREE_TYPE (t); enum tree_code code = TREE_CODE (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; /* This is used for deleting arrays. */ tree elt_size; switch (doing_vec) { case 2: maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); if (! flag_traditional) pedwarn ("anachronistic use of array size in vector delete"); /* Fall through. */ case 1: elt_size = c_sizeof (type); break; default: if (code != POINTER_TYPE) { cp_error ("type `%#T' argument given to `delete', expected pointer", type); return error_mark_node; } /* Deleting a pointer with the value zero is valid and has no effect. */ if (integer_zerop (t)) return build1 (NOP_EXPR, void_type_node, t); } if (code == POINTER_TYPE) {#if 0 /* As of Valley Forge, you can delete a pointer to constant. */ /* You can't delete a pointer to constant. */ if (TREE_READONLY (TREE_TYPE (type))) { error ("`const *' cannot be deleted"); return error_mark_node; }#endif /* You also can't delete functions. */ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) { error ("cannot delete a function"); return error_mark_node; } }#if 0 /* If the type has no destructor, then we should build a regular delete, instead of a vector delete. Otherwise, we would end up passing a bogus offset into __builtin_delete, which is not expecting it. */ if (doing_vec && TREE_CODE (type) == POINTER_TYPE && !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type))) { doing_vec = 0; use_global_delete = 1; }#endif if (doing_vec) return build_vec_delete (t, maxindex, elt_size, integer_one_node, integer_two_node, use_global_delete); else { if (IS_AGGR_TYPE (TREE_TYPE (type)) && TYPE_GETS_REG_DELETE (TREE_TYPE (type))) { /* Only do access checking here; we'll be calling op delete from the destructor. */ tree tmp = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, t, size_zero_node, NULL_TREE); if (tmp == error_mark_node) return error_mark_node; } return build_delete (type, t, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, use_global_delete); }}/* Sanity check: report error if this function FUNCTION is not really a member of the class (CTYPE) it is supposed to belong to. CNAME is the same here as it is for grokclassfn above. */treecheck_classfn (ctype, cname, function) tree ctype, cname, function;{ tree fn_name = DECL_NAME (function); tree fndecl; tree method_vec = CLASSTYPE_METHOD_VEC (ctype); tree *methods = 0; tree *end = 0; if (method_vec != 0) { methods = &TREE_VEC_ELT (method_vec, 0); end = TREE_VEC_END (method_vec); /* First suss out ctors and dtors. */ if (*methods && fn_name == DECL_NAME (*methods)) goto got_it; while (++methods != end) { if (fn_name == DECL_NAME (*methods)) { got_it: fndecl = *methods; while (fndecl) { if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl)) return fndecl;#if 0 /* This should work, but causes libg++ to fail make check-tFix. */ /* We have to do more extensive argument checking here, as the name may have been changed by asm("new_name"). */ if (decls_match (function, fndecl)) return fndecl;#else if (DECL_NAME (function) == DECL_NAME (fndecl)) { tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); /* Get rid of the this parameter on functions that become static. */ if (DECL_STATIC_FUNCTION_P (fndecl) && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) p1 = TREE_CHAIN (p1); if (comptypes (TREE_TYPE (TREE_TYPE (function)), TREE_TYPE (TREE_TYPE (fndecl)), 1) && compparms (p1, p2, 3)) { if (DECL_STATIC_FUNCTION_P (fndecl) && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) revert_static_member_fn (&function, NULL, NULL); return fndecl; } }#endif fndecl = DECL_CHAIN (fndecl); } break; /* loser */ } } } if (methods != end) { tree fndecl = *methods; cp_error ("prototype for `%#D' does not match any in class `%T'", function, ctype); cp_error_at ("candidate%s: %+#D", DECL_CHAIN (fndecl) ? "s are" : " is", fndecl); while (fndecl = DECL_CHAIN (fndecl), fndecl) cp_error_at (" %#D", fndecl); } else { methods = 0; cp_error ("no `%#D' member function declared in class `%T'", function, ctype); } /* If we did not find the method in the class, add it to avoid spurious errors. */ add_method (ctype, methods, function); return NULL_TREE;}/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) of a structure component, returning a FIELD_DECL node. QUALS is a list of type qualifiers for this decl (such as for declaring const member functions). This is done during the parsing of the struct declaration. The FIELD_DECL nodes are chained together and the lot of them are ultimately passed to `build_struct' to make the RECORD_TYPE node.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -