📄 cp-typeck.c
字号:
return p2 == void_type_node && TREE_PURPOSE (t1); return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);#endif } /* Target types are compatible--just make sure that if we use parameter lists, that they are ok as well. */ if (TREE_CODE (p1) == FUNCTION_TYPE || TREE_CODE (p1) == METHOD_TYPE) switch (comp_target_parms (TYPE_ARG_TYPES (p1), TYPE_ARG_TYPES (p2), strict)) { case 0: return 0; case 1: break; case 2: warn_contravariance = 1; } if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) { int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); if (cmp < 0) my_friendly_abort (114); if (cmp == 0) return 0; } } return 1 + warn_contravariance;}/* Return 1 if PARMS specifies a fixed number of parameters and none of their types is affected by default promotions. */static intself_promoting_args_p (parms) tree parms;{ register tree t; for (t = parms; t; t = TREE_CHAIN (t)) { register tree type = TREE_VALUE (t); if (TREE_CHAIN (t) == 0 && type != void_type_node) return 0; if (TYPE_MAIN_VARIANT (type) == float_type_node) return 0; if (type == 0) return 0; if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; } return 1;}/* Return an unsigned type the same as TYPE in other respects. C++: must make these work for type variants as well. */treeunsigned_type (type) tree type;{ tree type1 = TYPE_MAIN_VARIANT (type); if (type1 == signed_char_type_node || type1 == char_type_node) return unsigned_char_type_node; if (type1 == integer_type_node) return unsigned_type_node; if (type1 == short_integer_type_node) return short_unsigned_type_node; if (type1 == long_integer_type_node) return long_unsigned_type_node; if (type1 == long_long_integer_type_node) return long_long_unsigned_type_node; return type;}/* Return a signed type the same as TYPE in other respects. */treesigned_type (type) tree type;{ tree type1 = TYPE_MAIN_VARIANT (type); if (type1 == unsigned_char_type_node || type1 == char_type_node) return signed_char_type_node; if (type1 == unsigned_type_node) return integer_type_node; if (type1 == short_unsigned_type_node) return short_integer_type_node; if (type1 == long_unsigned_type_node) return long_integer_type_node; if (type1 == long_long_unsigned_type_node) return long_long_integer_type_node; return type;}/* Return a type the same as TYPE except unsigned or signed according to UNSIGNEDP. */treesigned_or_unsigned_type (unsignedp, type) int unsignedp; tree type;{ if (TREE_CODE (type) != INTEGER_TYPE) return type; if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); return type;}treec_sizeof (type) tree type;{ enum tree_code code = TREE_CODE (type); if (code == FUNCTION_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a function type"); return size_int (1); } if (code == METHOD_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a method type"); return size_int (1); } if (code == VOID_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a void type"); return size_int (1); } if (code == ERROR_MARK) return size_int (1); /* C++: this is really correct! */ if (code == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_SIZE (type) == 0) { error ("sizeof applied to an incomplete type"); return size_int (0); } /* Convert in case a char is more than one unit. */ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node)));}treec_sizeof_nowarn (type) tree type;{ enum tree_code code = TREE_CODE (type); 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) { /* ??? Tiemann, why have any diagnostic here? There is none in the corresponding function for C. */ warning ("sizeof applied to an incomplete type"); return size_int (0); } /* Convert in case a char is more than one unit. */ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node)));}/* 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); 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); return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);}/* 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. */treedefault_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 default_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) && DECL_MODE (exp) != BLKmode) { exp = decl_constant_value (exp); type = TREE_TYPE (exp); } /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since EXP is being used in non-lvalue context. */ if (TREE_CODE (exp) == NOP_EXPR && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))) exp = TREE_OPERAND (exp, 0); /* Normally convert enums to int, but convert wide enums to something wider. */ if (code == ENUMERAL_TYPE) { type = type_for_size (MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)), (flag_traditional && TREE_UNSIGNED (type))); return convert (type, exp); } if (C_PROMOTING_INTEGER_TYPE_P (type)) { /* Traditionally, unsignedness is preserved in default promotions. Otherwise, retain unsignedness if really not getting bigger. */ if (TREE_UNSIGNED (type) && (flag_traditional || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) return convert (double_type_node, exp); 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_TYPE (type); tree ptrtype; 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 (TYPE_POINTER_TO (TREE_TYPE (type)), inner); } if (TREE_CODE (exp) == COMPOUND_EXPR) { tree op1 = default_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; } if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) restype = build_type_variant (restype, TYPE_READONLY (type), TYPE_VOLATILE (type)); 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;}/* Like `build_component_ref, but uses an already found field. Must compute visibility 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) error_with_decl (field, "request for member `%s' in something not a class, structure or union"); 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 && ! DECL_PUBLIC (field)) { enum visibility_type visibility = compute_visibility (TYPE_BINFO (current_class_type), field); if (visibility == visibility_private) { error_with_decl (field, "field `%s' is private"); return error_mark_node; } else if (visibility == visibility_protected) { error_with_decl (field, "field `%s' is protected"); 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; return ref;}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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -