📄 typeck.c
字号:
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 cp_convert (t, exp); } return exp;}/* Take the address of an inline function without setting TREE_ADDRESSABLE or TREE_USED. */treeinline_conversion (exp) tree exp;{ if (TREE_CODE (exp) == FUNCTION_DECL) exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp); return exp;}/* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */intstring_conv_p (totype, exp, warn) tree totype, exp; int warn;{ tree t; if (! flag_const_strings || TREE_CODE (totype) != POINTER_TYPE) return 0; t = TREE_TYPE (totype); if (!same_type_p (t, char_type_node) && !same_type_p (t, wchar_type_node)) return 0; if (TREE_CODE (exp) == STRING_CST) { /* Make sure that we don't try to convert between char and wchar_t. */ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t)) return 0; } else { /* Is this a string constant which has decayed to 'const char *'? */ t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST)); if (!same_type_p (TREE_TYPE (exp), t)) return 0; STRIP_NOPS (exp); if (TREE_CODE (exp) != ADDR_EXPR || TREE_CODE (TREE_OPERAND (exp, 0)) != STRING_CST) return 0; } /* This warning is not very useful, as it complains about printf. */ if (warn && warn_write_strings) cp_warning ("deprecated conversion from string constant to `%T'", totype); return 1;}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 (basetype)) { warning ("signature name in scope resolution ignored"); return build_component_ref (datum, field, NULL_TREE, 1); } else if (is_aggr_type (basetype, 1)) { tree binfo = binfo_or_else (basetype, dtype); if (binfo) return build_x_component_ref (build_scoped_ref (datum, basetype), field, binfo, 1); } return error_mark_node;}/* Like `build_component_ref, but uses an already found field, and converts from a reference. Must compute access for current_class_ref. Otherwise, ok. */treebuild_component_ref_1 (datum, field, protect) tree datum, field; int protect;{ return convert_from_reference (build_component_ref (datum, field, NULL_TREE, protect));}/* Given a COND_EXPR, MIN_EXPR, or MAX_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. But now it's again only called from unary_complex_lvalue. 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;{ /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that the first operand is always the one to be used if both operands are equal, so we know what conditional expression this used to be. */ if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR) { return build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR ? LE_EXPR : GE_EXPR), TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)), build_unary_op (code, TREE_OPERAND (t, 0), 0), build_unary_op (code, TREE_OPERAND (t, 1), 0)); } 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));}/* Given the TYPE of an anonymous union field inside T, return the FIELD_DECL for the field. If not found return NULL_TREE. Because anonymous unions can nest, we must also search all anonymous unions that are directly reachable. */static treelookup_anon_field (t, type) tree t, type;{ tree field; for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) { if (TREE_STATIC (field)) continue; if (TREE_CODE (field) != FIELD_DECL) continue; /* If we find it directly, return the field. */ if (DECL_NAME (field) == NULL_TREE && type == TREE_TYPE (field)) { return field; } /* Otherwise, it could be nested, search harder. */ if (DECL_NAME (field) == NULL_TREE && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree subfield = lookup_anon_field (TREE_TYPE (field), type); if (subfield) return subfield; } } return NULL_TREE;}/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT. COMPONENT can be an IDENTIFIER_NODE that is the name of the member that we are interested in, or it can be a FIELD_DECL. */treebuild_component_ref (datum, component, basetype_path, protect) tree datum, component, basetype_path; int protect;{ register tree basetype; register enum tree_code code; register tree field = NULL; register tree ref; tree field_type; int type_quals; if (processing_template_decl) return build_min_nt (COMPONENT_REF, datum, component); if (datum == error_mark_node || TREE_TYPE (datum) == error_mark_node) return error_mark_node; /* BASETYPE holds the type of the class containing the COMPONENT. */ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); /* 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)); case TEMPLATE_DECL: cp_error ("invalid use of %D", datum); datum = error_mark_node; break; default: break; } code = TREE_CODE (basetype); if (code == REFERENCE_TYPE) { datum = convert_from_reference (datum); basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); code = TREE_CODE (basetype); } if (TREE_CODE (datum) == OFFSET_REF) { datum = resolve_offset_ref (datum); basetype = TYPE_MAIN_VARIANT (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) { /* I could not trigger this code. MvL */ my_friendly_abort (980326);#ifdef DEAD my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);#endif return build (COMPONENT_REF, TREE_TYPE (component), datum, component); } 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 (!complete_type_or_else (basetype, datum)) 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), 1); } /* 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 (TREE_CODE (component) == FIELD_DECL) field = component; else if (TREE_CODE (component) == TYPE_DECL) { cp_error ("invalid use of type decl `%#D' as expression", component); return error_mark_node; } else { tree name = component; if (TREE_CODE (component) == VAR_DECL) name = DECL_NAME (component); if (basetype_path == NULL_TREE) basetype_path = TYPE_BINFO (basetype); field = lookup_field (basetype_path, name, protect && !VFIELD_NAME_P (name), 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, name, 1); if (fndecls == error_mark_node) return error_mark_node; if (fndecls) { /* If the function is unique and static, we can resolve it now. Otherwise, we have to wait and see what context it is used in; a component_ref involving a non-static member function can only be used in a call (expr.ref). */ if (TREE_CHAIN (fndecls) == NULL_TREE && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL) { if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls))) { tree fndecl = TREE_VALUE (fndecls); enforce_access (TREE_PURPOSE (fndecls), fndecl); mark_used (fndecl); return fndecl; } else { /* A unique non-static member function. Other parts of the compiler expect something with unknown_type_node to be really overloaded, so let's oblige. */ TREE_VALUE (fndecls) = scratch_ovl_cons (TREE_VALUE (fndecls), NULL_TREE); } } ref = build (COMPONENT_REF, unknown_type_node, datum, TREE_VALUE (fndecls)); return ref; } cp_error ("`%#T' has no member named `%D'", basetype, name); return error_mark_node; } else if (TREE_TYPE (field) == error_mark_node) return error_mark_node; if (TREE_CODE (field) != FIELD_DECL) { if (TREE_CODE (field) == TYPE_DECL) cp_pedwarn ("invalid use of type decl `%#D' as expression", field); else if (DECL_RTL (field) != 0) mark_used (field); else TREE_USED (field) = 1; return field; } } /* See if we have to do any conversions so that we pick up the field from the right context. */ if (DECL_FIELD_CONTEXT (field) != basetype) { tree context = DECL_FIELD_CONTEXT (field); tree base = context; while (!same_type_p (base, basetype) && TYPE_NAME (base) && ANON_UNION_TYPE_P (base)) { base = TYPE_CONTEXT (base); } /* Handle base classes here... */ if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); if (integer_zerop (addr)) { error ("invalid reference to NULL ptr, use ptr-to-member instead"); return error_mark_node; } if (VBASE_NAME_P (DECL_NAME (field))) { /* It doesn't matter which vbase pointer we grab, just find one of them. */ tree binfo = get_binfo (base, TREE_TYPE (TREE_TYPE (addr)), 0); addr = convert_pointer_to_real (binfo, addr); } else addr = convert_pointer_to (base, addr); datum = build_indirect_ref (addr, NULL_PTR); my_friendly_assert (datum != error_mark_node, 311); } basetype = base; /* Handle things from anon unions here... */ if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context)) { tree subfield = lookup_anon_field (basetype, context); tree subdatum = build_component_ref (datum, subfield, basetype_path, protect); return build_component_ref (subdatum, field, basetype_path, protect); } } /* Compute the type of the field, as described in [expr.ref]. */ type_quals = TYPE_UNQUALIFIED; field_type = TREE_TYPE (field); if (TREE_CODE (field_type) == REFERENCE_TYPE) /* The standard says that the type of the result should be the type referred to by the reference. But for now, at least, we do the conversion from reference type later. */ ; else { type_quals = (CP_TYPE_QUALS (field_type) | CP_TYPE_QUALS (TREE_TYPE (datum))); /* A field is const (volatile) if the enclosing object, or the field itself, is const (volatile). But, a mutable field is not const, even within a const object. */ if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field)) type_quals &= ~TYPE_QUAL_CONST; if (!IS_SIGNATURE (field_type)) field_type = cp_build_qualified_type (field_type, type_quals); } ref = fold (build (COMPONENT_REF, field_type, break_out_cleanups (datum), field)); /* Mark the expression const or volatile, as appropriate. Even though we've dealt with the type above, we still have to mark the expression itse
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -