📄 typeck.c
字号:
In that case we should be able to do better. */ if (IS_SIGNATURE (type)) { error ("`__alignof' applied to a signature type"); return size_int (1); } t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); force_fit_type (t, 0); return t;}/* Perform default promotions for C data used in expressions. Arrays and functions are converted to pointers; enumeral types or short or char, to int. In addition, manifest constants symbols are replaced by their values. C++: this will automatically bash references to their target type. */treedecay_conversion (exp) tree exp;{ register tree type = TREE_TYPE (exp); register enum tree_code code = TREE_CODE (type); if (code == OFFSET_TYPE /* || TREE_CODE (exp) == OFFSET_REF */ ) { if (TREE_CODE (exp) == OFFSET_REF) return decay_conversion (resolve_offset_ref (exp)); type = TREE_TYPE (type); code = TREE_CODE (type); } if (code == REFERENCE_TYPE) { exp = convert_from_reference (exp); type = TREE_TYPE (exp); code = TREE_CODE (type); } /* Constants can be used directly unless they're not loadable. */ if (TREE_CODE (exp) == CONST_DECL) exp = DECL_INITIAL (exp); /* Replace a nonvolatile const static variable with its value. */ else if (TREE_READONLY_DECL_P (exp)) { exp = decl_constant_value (exp); type = TREE_TYPE (exp); } /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */ if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); return error_mark_node; } if (code == FUNCTION_TYPE) { return build_unary_op (ADDR_EXPR, exp, 0); } if (code == METHOD_TYPE) { if (TREE_CODE (exp) == OFFSET_REF) { my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL, 308); return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0); } return build_unary_op (ADDR_EXPR, exp, 0); } if (code == ARRAY_TYPE) { register tree adr; tree restype; tree ptrtype; int constp, volatilep; if (TREE_CODE (exp) == INDIRECT_REF) { /* Stripping away the INDIRECT_REF is not the right thing to do for references... */ tree inner = TREE_OPERAND (exp, 0); if (TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE) { inner = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (inner))), inner); TREE_REFERENCE_EXPR (inner) = 1; } return convert (build_pointer_type (TREE_TYPE (type)), inner); } if (TREE_CODE (exp) == COMPOUND_EXPR) { tree op1 = decay_conversion (TREE_OPERAND (exp, 1)); return build (COMPOUND_EXPR, TREE_TYPE (op1), TREE_OPERAND (exp, 0), op1); } if (!lvalue_p (exp) && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) { error ("invalid use of non-lvalue array"); return error_mark_node; } constp = volatilep = 0; if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd') { constp = TREE_READONLY (exp); volatilep = TREE_THIS_VOLATILE (exp); } restype = TREE_TYPE (type); if (TYPE_READONLY (type) || TYPE_VOLATILE (type) || constp || volatilep) restype = cp_build_type_variant (restype, TYPE_READONLY (type) || constp, TYPE_VOLATILE (type) || volatilep); ptrtype = build_pointer_type (restype); if (TREE_CODE (exp) == VAR_DECL) { /* ??? This is not really quite correct in that the type of the operand of ADDR_EXPR is not the target type of the type of the ADDR_EXPR itself. Question is, can this lossage be avoided? */ adr = build1 (ADDR_EXPR, ptrtype, exp); if (mark_addressable (exp) == 0) return error_mark_node; TREE_CONSTANT (adr) = staticp (exp); TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ return adr; } /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = build_unary_op (ADDR_EXPR, exp, 1); return convert (ptrtype, adr); } return exp;}treedefault_conversion (exp) tree exp;{ tree type; enum tree_code code; exp = decay_conversion (exp); type = TREE_TYPE (exp); code = TREE_CODE (type); if (INTEGRAL_CODE_P (code)) { tree t = type_promotes_to (type); if (t != type) return convert (t, exp); } if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) return convert (double_type_node, exp); return exp;}treebuild_object_ref (datum, basetype, field) tree datum, basetype, field;{ tree dtype; if (datum == error_mark_node) return error_mark_node; dtype = TREE_TYPE (datum); if (TREE_CODE (dtype) == REFERENCE_TYPE) dtype = TREE_TYPE (dtype); if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype))) { cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'", basetype, field, dtype); return error_mark_node; } else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype))) { warning ("signature name in scope resolution ignored"); return build_component_ref (datum, field, NULL_TREE, 1); } else if (is_aggr_typedef (basetype, 1)) { tree real_basetype = IDENTIFIER_TYPE_VALUE (basetype); tree binfo = binfo_or_else (real_basetype, TREE_TYPE (datum)); if (binfo) return build_component_ref (build_scoped_ref (datum, basetype), field, binfo, 1); } return error_mark_node;}/* Like `build_component_ref, but uses an already found field. Must compute access for C_C_D. Otherwise, ok. */treebuild_component_ref_1 (datum, field, protect) tree datum, field; int protect;{ register tree basetype = TREE_TYPE (datum); register enum tree_code code = TREE_CODE (basetype); register tree ref; if (code == REFERENCE_TYPE) { datum = convert_from_reference (datum); basetype = TREE_TYPE (datum); code = TREE_CODE (basetype); } if (! IS_AGGR_TYPE_CODE (code)) { if (code != ERROR_MARK) cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", field, datum, basetype); return error_mark_node; } if (TYPE_SIZE (basetype) == 0) { incomplete_type_error (0, basetype); return error_mark_node; } /* Look up component name in the structure type definition. */ if (field == error_mark_node) my_friendly_abort (115); if (TREE_STATIC (field)) return field; if (datum == C_C_D) { enum access_type access = compute_access (TYPE_BINFO (current_class_type), field); if (access == access_private) { cp_error ("field `%D' is private", field); return error_mark_node; } else if (access == access_protected) { cp_error ("field `%D' is protected", field); return error_mark_node; } } ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field); if (TREE_READONLY (datum) || TREE_READONLY (field)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field)) TREE_THIS_VOLATILE (ref) = 1; if (DECL_MUTABLE_P (field)) TREE_READONLY (ref) = 0; return ref;}/* Given a COND_EXPR in T, return it in a form that we can, for example, use as an lvalue. This code used to be in unary_complex_lvalue, but we needed it to deal with `a = (d == c) ? b : c' expressions, where we're dealing with aggregates. So, we now call this in unary_complex_lvalue, and in build_modify_expr. The case (in particular) that led to this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd get it there. */static treerationalize_conditional_expr (code, t) enum tree_code code; tree t;{ return build_conditional_expr (TREE_OPERAND (t, 0), build_unary_op (code, TREE_OPERAND (t, 1), 0), build_unary_op (code, TREE_OPERAND (t, 2), 0));}treebuild_component_ref (datum, component, basetype_path, protect) tree datum, component, basetype_path; int protect;{ register tree basetype = TREE_TYPE (datum); register enum tree_code code = TREE_CODE (basetype); register tree field = NULL; register tree ref; /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */ switch (TREE_CODE (datum)) { case COMPOUND_EXPR: { tree value = build_component_ref (TREE_OPERAND (datum, 1), component, basetype_path, protect); return build (COMPOUND_EXPR, TREE_TYPE (value), TREE_OPERAND (datum, 0), value); } case COND_EXPR: return build_conditional_expr (TREE_OPERAND (datum, 0), build_component_ref (TREE_OPERAND (datum, 1), component, basetype_path, protect), build_component_ref (TREE_OPERAND (datum, 2), component, basetype_path, protect)); } if (code == REFERENCE_TYPE) {#if 0 /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'. @@ Maybe that is not right. */ if (TREE_REFERENCE_EXPR (datum)) datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum); else#endif datum = convert_from_reference (datum); basetype = TREE_TYPE (datum); code = TREE_CODE (basetype); } /* First, see if there is a field or component with name COMPONENT. */ if (TREE_CODE (component) == TREE_LIST) { my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309); return build (COMPONENT_REF, TREE_TYPE (component), datum, component); }#if 0 if (TREE_CODE (component) == TYPE_EXPR) return build_component_type_expr (datum, component, NULL_TREE, protect);#endif if (! IS_AGGR_TYPE_CODE (code)) { if (code != ERROR_MARK) cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", component, datum, basetype); return error_mark_node; } if (TYPE_SIZE (basetype) == 0) { incomplete_type_error (0, basetype); return error_mark_node; } if (TREE_CODE (component) == BIT_NOT_EXPR) { if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0)) { cp_error ("destructor specifier `%T::~%T' must have matching names", basetype, TREE_OPERAND (component, 0)); return error_mark_node; } if (! TYPE_HAS_DESTRUCTOR (basetype)) { cp_error ("type `%T' has no destructor", basetype); return error_mark_node; } return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); } /* Look up component name in the structure type definition. */ if (CLASSTYPE_VFIELD (basetype) && DECL_NAME (CLASSTYPE_VFIELD (basetype)) == component) /* Special-case this because if we use normal lookups in an ambiguous hierarchy, the compiler will abort (because vptr lookups are not supposed to be ambiguous. */ field = CLASSTYPE_VFIELD (basetype); else { if (basetype_path == NULL_TREE) basetype_path = TYPE_BINFO (basetype); field = lookup_field (basetype_path, component, protect && ! VFIELD_NAME_P (component), 0); if (field == error_mark_node) return error_mark_node; if (field == NULL_TREE) { /* Not found as a data field, look for it as a method. If found, then if this is the only possible one, return it, else report ambiguity error. */ tree fndecls = lookup_fnfields (basetype_path, component, 1); if (fndecls == error_mark_node) return error_mark_node; if (fndecls) { if (TREE_CHAIN (fndecls) == NULL_TREE && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE) { enum access_type access; tree fndecl; /* Unique, so use this one now. */ basetype = TREE_PURPOSE (fndecls); fndecl = TREE_VALUE (fndecls); access = compute_access (TREE_PURPOSE (fndecls), fndecl); if (access == access_public) { if (DECL_VINDEX (fndecl) && ! resolves_to_fixed_type_p (datum, 0)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr); datum = build_indirect_ref (addr, NULL_PTR); my_friendly_assert (datum != error_mark_node, 310); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); } assemble_external (fndecl); return fndecl; } if (access == access_protected) cp_error ("member function `%D' is protected", fndecl); else cp_error ("member function `%D' is private", fndecl); return error_mark_node; } else { /* Just act like build_offset_ref, since the object does not matter unless we're actually calling the function. */ tree t; for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t)) assemble_external (t); t = build_tree_list (error_mark_node, fndecls); TREE_TYPE (t) = build_offset_type (basetype, unknown_type_node); return t; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -