typeck.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,225 行 · 第 1/5 页
C
2,225 行
return size_int (1); /* ARM $5.3.2: ``When applied to a reference, the result is the size of the referenced object.'' */ if (code == REFERENCE_TYPE) type = TREE_TYPE (type); /* We couldn't find anything in the ARM or the draft standard that says, one way or the other, if doing sizeof on something that doesn't have an object associated with it is correct or incorrect. For example, if you declare `struct S { char str[16]; };', and in your program do a `sizeof (S::str)', should we flag that as an error or should we give the size of it? Since it seems like a reasonable thing to do, we'll go with giving the value. */ if (code == OFFSET_TYPE) type = TREE_TYPE (type); /* @@ This also produces an error for a signature ref. In that case we should be able to do better. */ if (IS_SIGNATURE (type)) { error ("`sizeof' applied to a signature type"); return size_int (0); } if (TYPE_SIZE (complete_type (type)) == 0) { cp_error ("`sizeof' applied to incomplete type `%T'", type); return size_int (0); } /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); /* size_binop does not put the constant in range, so do it now. */ if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0)) TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1; return t;}treeexpr_sizeof (e) tree e;{ if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, e); if (TREE_CODE (e) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND (e, 1))) error ("sizeof applied to a bit-field"); /* ANSI says arrays and functions are converted inside comma. But we can't really 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 (e) == COMPOUND_EXPR && (TREE_CODE (TREE_TYPE (e)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (e)) == FUNCTION_TYPE)) e = default_conversion (e); else if (TREE_CODE (e) == TREE_LIST) { tree t = TREE_VALUE (e); if (t != NULL_TREE && ((TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) || is_overloaded_fn (t))) pedwarn ("ANSI C++ forbids taking the sizeof a function type"); } return c_sizeof (TREE_TYPE (e));} treec_sizeof_nowarn (type) tree type;{ enum tree_code code = TREE_CODE (type); tree t; if (code == FUNCTION_TYPE || code == METHOD_TYPE || code == VOID_TYPE || code == ERROR_MARK) return size_int (1); if (code == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_SIZE (type) == 0) return size_int (0); /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); force_fit_type (t, 0); return t;}/* Implement the __alignof keyword: Return the minimum required alignment of TYPE, measured in bytes. */treec_alignof (type) tree type;{ enum tree_code code = TREE_CODE (type); tree t; if (code == FUNCTION_TYPE || code == METHOD_TYPE) return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (code == VOID_TYPE || code == ERROR_MARK) return size_int (1); /* C++: this is really correct! */ if (code == REFERENCE_TYPE) type = TREE_TYPE (type); /* @@ This also produces an error for a signature ref. 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) { if (TREE_CODE (exp) == OFFSET_REF) return decay_conversion (resolve_offset_ref (exp)); type = TREE_TYPE (type); code = TREE_CODE (type); if (type == unknown_type_node) { cp_pedwarn ("assuming & on overloaded member function"); return build_unary_op (ADDR_EXPR, exp, 0); } } 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) { cp_pedwarn ("assuming & on `%E'", exp); 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_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0)); } return cp_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 cp_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 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) { tree type = build_type_variant (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); exp = build1 (ADDR_EXPR, build_pointer_type (type), 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 (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 = TREE_TYPE (datum); register enum tree_code code; register tree field = NULL; register tree ref; if (processing_template_decl) return build_min_nt (COMPONENT_REF, datum, component); /* 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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?