📄 cp-type2.c
字号:
a function call or a call to a constructor or a request for a type conversion, we try all three, and report any ambiguities we find. */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, name = NULL_TREE; tree expr_as_ctor = NULL_TREE; tree expr_as_method = NULL_TREE; tree expr_as_fncall = NULL_TREE; tree expr_as_conversion = NULL_TREE; if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; if (TREE_CODE (exp) == IDENTIFIER_NODE) { name = exp; 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) { error ("`%s' fails to be a typedef or built-in type", IDENTIFIER_POINTER (name)); return error_mark_node; } type = TREE_TYPE (type); } } else type = exp; /* 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 (name == NULL_TREE) { name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); } /* Try evaluating as a call to a function. */ if (IDENTIFIER_CLASS_VALUE (name)) expr_as_method = build_method_call (current_class_decl, name, parms, NULL_TREE, LOOKUP_SPECULATIVELY); if (IDENTIFIER_GLOBAL_VALUE (name) && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TREE_LIST || TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == FUNCTION_DECL)) { expr_as_fncall = build_overload_call (name, parms, 0, 0); if (expr_as_fncall == NULL_TREE) expr_as_fncall = error_mark_node; } if (! IS_AGGR_TYPE (type)) { /* this must build a C cast */ if (parms == NULL_TREE) { if (expr_as_method || expr_as_fncall) goto return_function; error ("cannot cast null list to type `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; } if (expr_as_method || (expr_as_fncall && expr_as_fncall != error_mark_node)) { error ("ambiguity between cast to `%s' and function call", IDENTIFIER_POINTER (name)); return error_mark_node; } return build_c_cast (type, build_compound_expr (parms)); } if (TYPE_SIZE (type) == NULL_TREE) { if (expr_as_method || expr_as_fncall) goto return_function; error ("type `%s' is not yet defined", IDENTIFIER_POINTER (name)); return error_mark_node; } if (parms && TREE_CHAIN (parms) == NULL_TREE) expr_as_conversion = build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0); if (! TYPE_NEEDS_CONSTRUCTOR (type) && parms != NULL_TREE) { char *msg = 0; if (parms == NULL_TREE) msg = "argument missing in cast to `%s' type"; else if (TREE_CHAIN (parms) == NULL_TREE) { if (expr_as_conversion == NULL_TREE) msg = "conversion to type `%s' failed"; } else msg = "type `%s' does not have a constructor"; if ((expr_as_method || expr_as_fncall) && expr_as_conversion) msg = "ambiguity between conversion to `%s' and function call"; else if (expr_as_method || expr_as_fncall) goto return_function; else if (expr_as_conversion) return expr_as_conversion; error (msg, IDENTIFIER_POINTER (name)); return error_mark_node; } if (! TYPE_HAS_CONSTRUCTOR (type)) { if (expr_as_method || expr_as_fncall) goto return_function; if (expr_as_conversion) return expr_as_conversion; /* Look through this type until we find the base type which has a constructor. */ do { tree binfos = TYPE_BINFO_BASETYPES (type); int i, index = 0; while (binfos && TREE_VEC_LENGTH (binfos) == 1 && ! TYPE_HAS_CONSTRUCTOR (type)) { type = BINFO_TYPE (TREE_VEC_ELT (binfos, 0)); binfos = TYPE_BINFO_BASETYPES (type); } if (TYPE_HAS_CONSTRUCTOR (type)) break; /* Hack for MI. */ i = binfos ? TREE_VEC_LENGTH (binfos) : 0; if (i == 0) break; while (--i > 0) { if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (TREE_VEC_ELT (binfos, i)))) { if (index == 0) index = i; else { error ("multiple base classes with constructor, ambiguous"); type = 0; break; } } } if (type == 0) break; } while (! TYPE_HAS_CONSTRUCTOR (type)); if (type == 0) return error_mark_node; } name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 321); { int flags = LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN; if (parms && TREE_CHAIN (parms) == NULL_TREE) flags |= LOOKUP_NO_CONVERSION; try_again: expr_as_ctor = build_method_call (NULL_TREE, name, parms, NULL_TREE, flags); if (expr_as_ctor && expr_as_ctor != error_mark_node) {#if 0 /* mrs Mar 12, 1992 I claim that if it is a constructor, it is impossible to be an expr_as_method, without being a constructor call. */ if (expr_as_method || (expr_as_fncall && expr_as_fncall != error_mark_node))#else if (expr_as_fncall && expr_as_fncall != error_mark_node)#endif { error ("ambiguity between constructor for `%s' and function call", IDENTIFIER_POINTER (name)); return error_mark_node; } else if (expr_as_conversion && expr_as_conversion != error_mark_node) { /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ error ("ambiguity between conversion to `%s' and constructor", IDENTIFIER_POINTER (name)); return error_mark_node; } if (current_function_decl) return build_cplus_new (type, expr_as_ctor, 1); { register tree parm = TREE_OPERAND (expr_as_ctor, 1); /* Initializers for static variables and parameters have to handle doing the initialization and cleanup themselves. */ my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322); my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323); TREE_VALUE (parm) = NULL_TREE; expr_as_ctor = build_indirect_ref (expr_as_ctor, 0); TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1; } return expr_as_ctor; } /* If it didn't work going through constructor, try type conversion. */ if (! (flags & LOOKUP_COMPLAIN)) { if (expr_as_conversion) return expr_as_conversion; if (flags & LOOKUP_NO_CONVERSION) { flags = LOOKUP_NORMAL; goto try_again; } } if (expr_as_conversion) { if (expr_as_method || expr_as_fncall) { error ("ambiguity between conversion to `%s' and function call", IDENTIFIER_POINTER (name)); return error_mark_node; } return expr_as_conversion; } return_function: if (expr_as_method) return build_method_call (current_class_decl, name, parms, NULL_TREE, LOOKUP_NORMAL); if (expr_as_fncall) return expr_as_fncall == error_mark_node ? build_overload_call (name, parms, 1, 0) : expr_as_fncall; error ("invalid functional cast"); return error_mark_node; }}/* 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)%d", TYPE_NAME_STRING (type), intval); return buf; } return IDENTIFIER_POINTER (TREE_PURPOSE (values));}/* 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"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -