📄 c-typeck.c
字号:
/* Build expressions with type checking for C compiler. Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* This file is part of the C front end. It contains routines to build C expressions given their operands, including computing the types of the result, C-specific error checks, and some optimization. There are also routines to build RETURN_STMT nodes and CASE_STMT nodes, and to process initializations in declarations (since they work like a strange sort of assignment). */#include "config.h"#include <stdio.h>#include "tree.h"#include "c-tree.h"#include "flags.h"int mark_addressable ();static tree convert_for_assignment ();static int compparms ();int comp_target_types ();static tree shorten_compare ();static void binary_op_error ();static tree pointer_int_sum ();static tree pointer_diff ();static tree convert_sequence ();static tree unary_complex_lvalue ();static tree process_init_constructor ();tree digest_init ();tree truthvalue_conversion ();static tree invert_truthvalue ();void incomplete_type_error ();void readonly_warning ();/* Return the _TYPE node describing the data type of the data which NODE represents as a C expression. Arrays and functions are converted to pointers just as they are when they appear as C expressions. */treedatatype (node) tree node;{ register tree type = TREE_TYPE (node); if (TREE_CODE (type) == ARRAY_TYPE) return TYPE_POINTER_TO (TREE_TYPE (type)); if (TREE_CODE (type) == FUNCTION_TYPE) return build_pointer_type (type); return type;}/* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */treerequire_complete_type (value) tree value;{ tree type = TREE_TYPE (value); /* First, detect a valid value with a complete type. */ if (TYPE_SIZE (type) != 0 && type != void_type_node) return value; incomplete_type_error (value, type); return error_mark_node;}/* Print an error message for invalid use of an incomplete type. VALUE is the expression that was used (or 0 if that isn't known) and TYPE is the type that was invalid. */voidincomplete_type_error (value, type) tree value; tree type;{ char *errmsg; /* Avoid duplicate error message. */ if (TREE_CODE (type) == ERROR_MARK) return; if (value != 0 && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)) error ("`%s' has an incomplete type", IDENTIFIER_POINTER (DECL_NAME (value))); else { retry: /* We must print an error message. Be clever about what it says. */ switch (TREE_CODE (type)) { case RECORD_TYPE: errmsg = "invalid use of undefined type `struct %s'"; break; case UNION_TYPE: errmsg = "invalid use of undefined type `union %s'"; break; case ENUMERAL_TYPE: errmsg = "invalid use of undefined type `enum %s'"; break; case VOID_TYPE: error ("invalid use of void expression"); return; case ARRAY_TYPE: if (TYPE_DOMAIN (type)) { type = TREE_TYPE (type); goto retry; } error ("invalid use of array with unspecified bounds"); return; default: abort (); } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type))); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ error ("invalid use of incomplete typedef `%s'", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); }}/* Return a variant of TYPE which has all the type qualifiers of LIKE as well as those of TYPE. */static treequalify_type (type, like) tree type, like;{ int constflag = TREE_READONLY (type) || TREE_READONLY (like); int volflag = TREE_VOLATILE (type) || TREE_VOLATILE (like); return c_build_type_variant (type, constflag, volflag);}/* Return the common type of two types. We assume that comptypes has already been done and returned 1; if that isn't so, this may crash. This is the type for the result of most arithmetic operations if the operands have the given two types. We do not deal with enumeral types here because they have already been converted to integer types. */treecommontype (t1, t2) tree t1, t2;{ register enum tree_code form1; register enum tree_code form2; /* Save time if the two types are the same. */ if (t1 == t2) return t1; /* If one type is nonsense, use the other. */ if (t1 == error_mark_node) return t2; if (t2 == error_mark_node) return t1; /* Treat an enum type as the unsigned integer type of the same width. */ if (TREE_CODE (t1) == ENUMERAL_TYPE) t1 = type_for_size (TYPE_PRECISION (t1), 1); if (TREE_CODE (t2) == ENUMERAL_TYPE) t2 = type_for_size (TYPE_PRECISION (t2), 1); form1 = TREE_CODE (t1); form2 = TREE_CODE (t2); switch (form1) { case INTEGER_TYPE: case REAL_TYPE: /* If only one is real, use it as the result. */ if (form1 == REAL_TYPE && form2 != REAL_TYPE) return t1; if (form2 == REAL_TYPE && form1 != REAL_TYPE) return t2; /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) return t1; else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) return t2; /* Same precision. Prefer longs to ints even when same size. */ if (t1 == long_unsigned_type_node || t2 == long_unsigned_type_node) return long_unsigned_type_node; if (t1 == long_integer_type_node || t2 == long_integer_type_node) { /* But preserve unsignedness from the other type, since long cannot hold all the values of an unsigned int. */ if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2)) return long_unsigned_type_node; return long_integer_type_node; } /* Otherwise prefer the unsigned one. */ if (TREE_UNSIGNED (t1)) return t1; else return t2; case POINTER_TYPE:#if 0 /* For two pointers, do this recursively on the target type, and combine the qualifiers of the two types' targets. */ { tree target = commontype (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), TYPE_MAIN_VARIANT (TREE_TYPE (t2))); int constp = TREE_READ_ONLY (TREE_TYPE (t1)) || TREE_READ_ONLY (TREE_TYPE (t2)); int volatilep = TREE_VOLATILE (TREE_TYPE (t1)) || TREE_VOLATILE (TREE_TYPE (t2)); return build_pointer_type (c_build_type_variant (target, constp, volatilep)); }#endif return build_pointer_type (commontype (TREE_TYPE (t1), TREE_TYPE (t2))); case ARRAY_TYPE: { tree elt = commontype (TREE_TYPE (t1), TREE_TYPE (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) return t1; if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) return t2; /* Merge the element types, and have a size if either arg has one. */ return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); } case FUNCTION_TYPE: /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { tree valtype = commontype (TREE_TYPE (t1), TREE_TYPE (t2)); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); int len; tree newargs, n; int i; /* Save space: see if the result is identical to one of the args. */ if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2)) return t1; if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1)) return t2; /* Simple way if one arg fails to specify argument types. */ if (TYPE_ARG_TYPES (t1) == 0) return build_function_type (valtype, TYPE_ARG_TYPES (t2)); if (TYPE_ARG_TYPES (t2) == 0) return build_function_type (valtype, TYPE_ARG_TYPES (t1)); /* If both args specify argument types, we must merge the two lists, argument by argument. */ len = list_length (p1); newargs = 0; for (i = 0; i < len; i++) newargs = tree_cons (0, 0, newargs); n = newargs; for (; p1; p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n)) TREE_VALUE (n) = commontype (TREE_VALUE (p1), TREE_VALUE (p2)); return build_function_type (valtype, newargs); } default: return t1; }}/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. This is what ANSI C speaks of as "being the same". */intcomptypes (type1, type2) tree type1, type2;{ register tree t1 = type1; register tree t2 = type2; /* Suppress errors caused by previously reported errors */ if (t1 == t2 || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) return 1; /* Treat an enum type as the unsigned integer type of the same width. */ if (TREE_CODE (t1) == ENUMERAL_TYPE) t1 = type_for_size (TYPE_PRECISION (t1), 1); if (TREE_CODE (t2) == ENUMERAL_TYPE) t2 = type_for_size (TYPE_PRECISION (t2), 1); if (t1 == t2) return 1; /* Different classes of types can't be compatible. */ if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; /* Qualifiers must match. */ if (TREE_READONLY (t1) != TREE_READONLY (t2)) return 0; if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2)) return 0; switch (TREE_CODE (t1)) { case POINTER_TYPE: return (TREE_TYPE (t1) == TREE_TYPE (t2) || comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); case FUNCTION_TYPE: return ((TREE_TYPE (t1) == TREE_TYPE (t2) || comptypes (TREE_TYPE (t1), TREE_TYPE (t2))) && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2))); case ARRAY_TYPE: /* Target types must match incl. qualifiers. */ if (!(TREE_TYPE (t1) == TREE_TYPE (t2) || comptypes (TREE_TYPE (t1), TREE_TYPE (t2)))) return 0; { tree d1 = TYPE_DOMAIN (t1); tree d2 = TYPE_DOMAIN (t2); /* Sizes must match unless one is missing or variable. */ if (d1 == 0 || d2 == 0 || d1 == d2 || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST) return 1; return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1)) == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2))) && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1)) == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2))) && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1)) == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2))) && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1)) == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))); } } return 0;}/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring their qualifiers. */intcomp_target_types (ttl, ttr) tree ttl, ttr;{ return comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));}/* Subroutines of `comptypes'. *//* Return 1 if two parameter type lists PARMS1 and PARMS2 are equivalent in the sense that functions with those parameter types can have equivalent types. If either list is empty, we win. Otherwise, the two lists must be equivalent, element by element. */static intcompparms (parms1, parms2) tree parms1, parms2;{ register tree t1 = parms1, t2 = parms2; /* An unspecified parmlist matches any specified parmlist whose argument types don't need default promotions. */ if (t1 == 0) return compparms1 (t2); if (t2 == 0) return compparms1 (t1); while (1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -