typeck.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,225 行 · 第 1/5 页
C
2,225 行
/* Build expressions with type checking for C++ compiler. Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com)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 2, 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, 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 and 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 "rtl.h"#include "cp-tree.h"#include "flags.h"#include "output.h"#include "expr.h"#ifdef HAVE_STRING_H#include <string.h>#endifextern void compiler_error ();static tree convert_for_assignment PROTO((tree, tree, char*, tree, int));static tree pointer_int_sum PROTO((enum tree_code, tree, tree));static tree rationalize_conditional_expr PROTO((enum tree_code, tree));static int comp_target_parms PROTO((tree, tree, int));static int comp_ptr_ttypes_real PROTO((tree, tree, int));static int comp_ptr_ttypes_const PROTO((tree, tree));static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));static int comp_array_types PROTO((int (*) (tree, tree, int), tree, tree, int));static tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));static tree common_base_type PROTO((tree, tree));static tree convert_sequence PROTO((tree, tree));static tree lookup_anon_field PROTO((tree, tree));static tree pointer_diff PROTO((tree, tree));static tree qualify_type PROTO((tree, tree));static tree expand_target_expr PROTO((tree));static tree get_delta_difference PROTO((tree, tree, int));/* Return the target type of TYPE, which meas return T for: T*, T&, T[], T (...), and otherwise, just T. */treetarget_type (type) tree type;{ if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); while (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == OFFSET_TYPE) type = TREE_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; if (processing_template_decl) return value; type = TREE_TYPE (value); /* First, detect a valid value with a complete type. */ if (TYPE_SIZE (type) != 0 && type != void_type_node && ! (TYPE_LANG_SPECIFIC (type) && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)) && TYPE_SIZE (SIGNATURE_TYPE (type)) == 0)) return value; /* If we see X::Y, we build an OFFSET_TYPE which has not been laid out. Try to avoid an error by interpreting it as this->X::Y, if reasonable. */ if (TREE_CODE (value) == OFFSET_REF && current_class_ref != 0 && TREE_OPERAND (value, 0) == current_class_ref) { tree base, member = TREE_OPERAND (value, 1); tree basetype = TYPE_OFFSET_BASETYPE (type); my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305); base = convert_pointer_to (basetype, current_class_ptr); value = build (COMPONENT_REF, TREE_TYPE (member), build_indirect_ref (base, NULL_PTR), member); return require_complete_type (value); } if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) { instantiate_class_template (TYPE_MAIN_VARIANT (type)); if (TYPE_SIZE (type) != 0) return value; } incomplete_type_error (value, type); return error_mark_node;}treecomplete_type (type) tree type;{ if (type == error_mark_node || TYPE_SIZE (type) != NULL_TREE) ; else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl) layout_type (type); TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); TYPE_NEEDS_DESTRUCTOR (type) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t)); } else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) instantiate_class_template (TYPE_MAIN_VARIANT (type)); return type;}/* Return truthvalue of whether type of EXP is instantiated. */inttype_unknown_p (exp) tree exp;{ return (TREE_CODE (exp) == TREE_LIST || TREE_TYPE (exp) == unknown_type_node || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node));}/* Return truthvalue of whether T is function (or pfn) type. */intfntype_p (t) tree t;{ return (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE || (TREE_CODE (t) == POINTER_TYPE && (TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)));}/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP does not have an uninstantiated type. TYPE is type to instantiate with, if uninstantiated. */treerequire_instantiated_type (type, exp, errval) tree type, exp, errval;{ if (TREE_TYPE (exp) == NULL_TREE) { error ("argument list may not have an initializer list"); return errval; } if (TREE_TYPE (exp) == unknown_type_node || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node)) { exp = instantiate_type (type, exp, 1); if (TREE_TYPE (exp) == error_mark_node) return errval; } return exp;}/* 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 = TYPE_READONLY (type) || TYPE_READONLY (like); int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like); /* @@ Must do member pointers here. */ return cp_build_type_variant (type, constflag, volflag);}/* Return the common type of two parameter lists. We assume that comptypes has already been done and returned 1; if that isn't so, this may crash. As an optimization, free the space we allocate if the parameter lists are already common. */treecommonparms (p1, p2) tree p1, p2;{ tree oldargs = p1, newargs, n; int i, len; int any_change = 0; char *first_obj = (char *) oballoc (0); len = list_length (p1); newargs = tree_last (p1); if (newargs == void_list_node) i = 1; else { i = 0; newargs = 0; } for (; i < len; i++) newargs = tree_cons (NULL_TREE, NULL_TREE, newargs); n = newargs; for (i = 0; p1; p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n), i++) { if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2)) { TREE_PURPOSE (n) = TREE_PURPOSE (p1); any_change = 1; } else if (! TREE_PURPOSE (p1)) { if (TREE_PURPOSE (p2)) { TREE_PURPOSE (n) = TREE_PURPOSE (p2); any_change = 1; } } else { if (1 != simple_cst_equal (TREE_PURPOSE (p1), TREE_PURPOSE (p2))) any_change = 1; TREE_PURPOSE (n) = TREE_PURPOSE (p2); } if (TREE_VALUE (p1) != TREE_VALUE (p2)) { any_change = 1; TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2)); } else TREE_VALUE (n) = TREE_VALUE (p1); } if (! any_change) { obfree (first_obj); return oldargs; } return newargs;}/* 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. */treecommon_type (t1, t2) tree t1, t2;{ register enum tree_code code1; register enum tree_code code2; tree attributes; /* 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; /* Merge the attributes */ { register tree a1, a2; a1 = TYPE_ATTRIBUTES (t1); a2 = TYPE_ATTRIBUTES (t2); /* Either one unset? Take the set one. */ if (!(attributes = a1)) attributes = a2; /* One that completely contains the other? Take it. */ else if (a2 && !attribute_list_contained (a1, a2)) if (attribute_list_contained (a2, a1)) attributes = a2; else { /* Pick the longest list, and hang on the other list. */ /* ??? For the moment we punt on the issue of attrs with args. */ if (list_length (a1) < list_length (a2)) attributes = a2, a2 = a1; for (; a2; a2 = TREE_CHAIN (a2)) if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), attributes) == NULL_TREE) { a1 = copy_node (a2); TREE_CHAIN (a1) = attributes; attributes = a1; } } } /* 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 (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); /* If one type is complex, form the common type of the non-complex components, then make that complex. Use T1 or T2 if it is the required type. */ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) { tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; tree subtype = common_type (subtype1, subtype2); if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) return build_type_attribute_variant (t1, attributes); else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) return build_type_attribute_variant (t2, attributes); else return build_type_attribute_variant (build_complex_type (subtype), attributes); } switch (code1) { case INTEGER_TYPE: case REAL_TYPE: /* If only one is real, use it as the result. */ if (code1 == REAL_TYPE && code2 != REAL_TYPE) return build_type_attribute_variant (t1, attributes); if (code2 == REAL_TYPE && code1 != REAL_TYPE) return build_type_attribute_variant (t2, attributes); /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) return build_type_attribute_variant (t1, attributes); else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) return build_type_attribute_variant (t2, attributes); /* Same precision. Prefer longs to ints even when same size. */ if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) return build_type_attribute_variant (long_unsigned_type_node, attributes); if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node || TYPE_MAIN_VARIANT (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)) t1 = long_unsigned_type_node; else t1 = long_integer_type_node; return build_type_attribute_variant (t1, attributes); } if (TYPE_MAIN_VARIANT (t1) == long_double_type_node || TYPE_MAIN_VARIANT (t2) == long_double_type_node) return build_type_attribute_variant (long_double_type_node, attributes); /* Otherwise prefer the unsigned one. */ if (TREE_UNSIGNED (t1)) return build_type_attribute_variant (t1, attributes); else return build_type_attribute_variant (t2, attributes); case POINTER_TYPE: case REFERENCE_TYPE: /* For two pointers, do this recursively on the target type, and combine the qualifiers of the two types' targets. */ /* This code was turned off; I don't know why. But ANSI C++ specifies doing this with the qualifiers. So I turned it on again. */ { tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1)); tree tt2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2)); int constp = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?