📄 typeck2.c
字号:
case FIX_TRUNC_EXPR: case FIX_FLOOR_EXPR: case FIX_ROUND_EXPR: case FIX_CEIL_EXPR: ref = convert_pointer_to (binfo, build_unary_op (ADDR_EXPR, TREE_OPERAND (datum, 0), 0)); break; default: ref = convert_pointer_to (binfo, build_unary_op (ADDR_EXPR, datum, 0)); } return build_indirect_ref (ref, "(compiler error in build_scoped_ref)"); } return error_mark_node;}/* Build a reference to an object specified by the C++ `->' operator. Usually this just involves dereferencing the object, but if the `->' operator is overloaded, then such overloads must be performed until an object which does not have the `->' operator overloaded is found. An error is reported when circular pointer delegation is detected. */treebuild_x_arrow (datum) tree datum;{ tree types_memoized = NULL_TREE; register tree rval = datum; tree type = TREE_TYPE (rval); tree last_rval = NULL_TREE; if (type == error_mark_node) return error_mark_node; if (processing_template_decl) return build_min_nt (ARROW_EXPR, rval); if (TREE_CODE (rval) == OFFSET_REF) { rval = resolve_offset_ref (datum); type = TREE_TYPE (rval); } if (TREE_CODE (type) == REFERENCE_TYPE) { rval = convert_from_reference (rval); type = TREE_TYPE (rval); } if (IS_AGGR_TYPE (type)) { while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE))) { if (rval == error_mark_node) return error_mark_node; if (value_member (TREE_TYPE (rval), types_memoized)) { error ("circular pointer delegation detected"); return error_mark_node; } else { types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval), types_memoized); } last_rval = rval; } if (last_rval == NULL_TREE) { cp_error ("base operand of `->' has non-pointer type `%T'", type); return error_mark_node; } if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE) last_rval = convert_from_reference (last_rval); } else last_rval = default_conversion (rval); /* Signature pointers are not dereferenced. */ if (TYPE_LANG_SPECIFIC (TREE_TYPE (last_rval)) && IS_SIGNATURE_POINTER (TREE_TYPE (last_rval))) return last_rval; if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) return build_indirect_ref (last_rval, NULL_PTR); if (types_memoized) error ("result of `operator->()' yields non-pointer result"); else error ("base operand of `->' is not a pointer"); return error_mark_node;}/* Make an expression to refer to the COMPONENT field of structure or union value DATUM. COMPONENT is an arbitrary expression. DATUM has not already been checked out to be of aggregate type. For C++, COMPONENT may be a TREE_LIST. This happens when we must return an object of member type to a method of the current class, but there is not yet enough typing information to know which one. As a special case, if there is only one method by that name, it is returned. Otherwise we return an expression which other routines will have to know how to deal with later. */treebuild_m_component_ref (datum, component) tree datum, component;{ tree type; tree objtype = TREE_TYPE (datum); tree rettype; tree binfo; if (processing_template_decl) return build_min_nt (DOTSTAR_EXPR, datum, component); if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) { type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component))); rettype = type; } else { type = TREE_TYPE (TREE_TYPE (component)); rettype = TREE_TYPE (type); } if (datum == error_mark_node || component == error_mark_node) return error_mark_node; if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE) { cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type); return error_mark_node; } if (TREE_CODE (objtype) == REFERENCE_TYPE) objtype = TREE_TYPE (objtype); objtype = TYPE_MAIN_VARIANT (objtype); if (! IS_AGGR_TYPE (objtype)) { cp_error ("cannot apply member pointer `%E' to `%E'", component, datum); cp_error ("which is of non-aggregate type `%T'", objtype); return error_mark_node; } binfo = get_binfo (TYPE_METHOD_BASETYPE (type), objtype, 1); if (binfo == NULL_TREE) { cp_error ("member type `%T::' incompatible with object type `%T'", TYPE_METHOD_BASETYPE (type), objtype); return error_mark_node; } else if (binfo == error_mark_node) return error_mark_node; component = build (OFFSET_REF, rettype, datum, component); if (TREE_CODE (type) == OFFSET_TYPE) component = resolve_offset_ref (component); return component;}/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */treebuild_functional_cast (exp, parms) tree exp; tree parms;{ /* This is either a call to a constructor, or a C cast in C++'s `functional' notation. */ tree type; if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; if (TREE_CODE (exp) == IDENTIFIER_NODE) { if (IDENTIFIER_HAS_TYPE_VALUE (exp)) /* Either an enum or an aggregate type. */ type = IDENTIFIER_TYPE_VALUE (exp); else { type = lookup_name (exp, 1); if (!type || TREE_CODE (type) != TYPE_DECL) { cp_error ("`%T' fails to be a typedef or built-in type", exp); return error_mark_node; } type = TREE_TYPE (type); } } else if (TREE_CODE (exp) == TYPE_DECL) type = TREE_TYPE (exp); else type = exp; if (processing_template_decl) return build_min (CAST_EXPR, type, parms); if (IS_SIGNATURE (type)) { error ("signature type not allowed in cast or constructor expression"); return error_mark_node; } if (! IS_AGGR_TYPE (type)) { /* this must build a C cast */ if (parms == NULL_TREE) parms = integer_zero_node; else { if (TREE_CHAIN (parms) != NULL_TREE) pedwarn ("initializer list being treated as compound expression"); parms = build_compound_expr (parms); } return build_c_cast (type, parms); } /* Prepare to evaluate as a call to a constructor. If this expression is actually used, for example, return X (arg1, arg2, ...); then the slot being initialized will be filled in. */ if (TYPE_SIZE (complete_type (type)) == NULL_TREE) { cp_error ("type `%T' is not yet defined", type); return error_mark_node; } if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type)) { abstract_virtuals_error (NULL_TREE, type); return error_mark_node; } if (parms && TREE_CHAIN (parms) == NULL_TREE) return build_c_cast (type, TREE_VALUE (parms)); /* We need to zero-initialize POD types. Let's do that for everything that doesn't need a constructor. */ if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); return get_target_expr (exp); } exp = build_method_call (NULL_TREE, ctor_identifier, parms, TYPE_BINFO (type), LOOKUP_NORMAL); if (exp == error_mark_node) return error_mark_node; return build_cplus_new (type, exp);}/* Return the character string for the name that encodes the enumeral value VALUE in the domain TYPE. */char *enum_name_string (value, type) tree value; tree type;{ register tree values = TYPE_VALUES (type); register HOST_WIDE_INT intval = TREE_INT_CST_LOW (value); my_friendly_assert (TREE_CODE (type) == ENUMERAL_TYPE, 324); while (values && TREE_INT_CST_LOW (TREE_VALUE (values)) != intval) values = TREE_CHAIN (values); if (values == NULL_TREE) { char *buf = (char *)oballoc (16 + TYPE_NAME_LENGTH (type)); /* Value must have been cast. */ sprintf (buf, "(enum %s)%ld", TYPE_NAME_STRING (type), (long) intval); return buf; } return IDENTIFIER_POINTER (TREE_PURPOSE (values));}#if 0/* Print out a language-specific error message for (Pascal) case or (C) switch statements. CODE tells what sort of message to print. TYPE is the type of the switch index expression. NEW is the new value that we were trying to add. OLD is the old value that stopped us from adding it. */voidreport_case_error (code, type, new_value, old_value) int code; tree type; tree new_value, old_value;{ if (code == 1) { if (new_value) error ("case label not within a switch statement"); else error ("default label not within a switch statement"); } else if (code == 2) { if (new_value == 0) { error ("multiple default labels in one switch"); return; } if (TREE_CODE (new_value) == RANGE_EXPR) if (TREE_CODE (old_value) == RANGE_EXPR) { char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); if (TREE_CODE (type) == ENUMERAL_TYPE) sprintf (buf, "overlapping ranges [%s..%s], [%s..%s] in case expression", enum_name_string (TREE_OPERAND (new_value, 0), type), enum_name_string (TREE_OPERAND (new_value, 1), type), enum_name_string (TREE_OPERAND (old_value, 0), type), enum_name_string (TREE_OPERAND (old_value, 1), type)); else sprintf (buf, "overlapping ranges [%d..%d], [%d..%d] in case expression", TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)), TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)), TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)), TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1))); error (buf); } else { char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); if (TREE_CODE (type) == ENUMERAL_TYPE) sprintf (buf, "range [%s..%s] includes element `%s' in case expression", enum_name_string (TREE_OPERAND (new_value, 0), type), enum_name_string (TREE_OPERAND (new_value, 1), type), enum_name_string (old_value, type)); else sprintf (buf, "range [%d..%d] includes (%d) in case expression", TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)), TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)), TREE_INT_CST_LOW (old_value)); error (buf); } else if (TREE_CODE (old_value) == RANGE_EXPR) { char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); if (TREE_CODE (type) == ENUMERAL_TYPE) sprintf (buf, "range [%s..%s] includes element `%s' in case expression", enum_name_string (TREE_OPERAND (old_value, 0), type), enum_name_string (TREE_OPERAND (old_value, 1), type), enum_name_string (new_value, type)); else sprintf (buf, "range [%d..%d] includes (%d) in case expression", TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)), TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)), TREE_INT_CST_LOW (new_value)); error (buf); } else { if (TREE_CODE (type) == ENUMERAL_TYPE) error ("duplicate label `%s' in switch statement", enum_name_string (new_value, type)); else error ("duplicate label (%d) in switch statement", TREE_INT_CST_LOW (new_value)); } } else if (code == 3) { if (TREE_CODE (type) == ENUMERAL_TYPE) warning ("case value out of range for enum %s", TYPE_NAME_STRING (type)); else warning ("case value out of range"); } else if (code == 4) { if (TREE_CODE (type) == ENUMERAL_TYPE) error ("range values `%s' and `%s' reversed", enum_name_string (new_value, type), enum_name_string (old_value, type)); else error ("range values reversed"); }}#endif/* Complain about defining new types in inappropriate places. We give an exception for C-style casts, to accommodate GNU C stylings. */voidcheck_for_new_type (string, inptree) const char *string; flagged_type_tree inptree;{ if (inptree.new_type_flag && (pedantic || strcmp (string, "cast") != 0)) pedwarn ("ANSI C++ forbids defining types within %s",string);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -