📄 tree.c
字号:
return t; case CONSTRUCTOR: t = copy_node (t); CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func); return t; case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) return build_ptrmemfunc_type (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); /* else fall through */ /* This list is incomplete, but should suffice for now. It is very important that `sorry' not call `report_error_function'. That could cause an infinite loop. */ default: sorry ("initializer contains unrecognized tree code"); return error_mark_node; } my_friendly_abort (107); /* NOTREACHED */ return NULL_TREE;}static treeperm_manip (t) tree t;{ if (TREE_PERMANENT (t)) return t; /* Support `void f () { extern int i; A<&i> a; }' */ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) && TREE_PUBLIC (t)) return copy_node (t); return NULL_TREE;}/* Assuming T is a node built bottom-up, make it all exist on permanent obstack, if it is not permanent already. */treecopy_to_permanent (t) tree t;{ register struct obstack *ambient_obstack = current_obstack; register struct obstack *ambient_saveable_obstack = saveable_obstack; register struct obstack *ambient_expression_obstack = expression_obstack; if (t == NULL_TREE || TREE_PERMANENT (t)) return t; saveable_obstack = &permanent_obstack; current_obstack = saveable_obstack; expression_obstack = saveable_obstack; t = mapcar (t, perm_manip); current_obstack = ambient_obstack; saveable_obstack = ambient_saveable_obstack; expression_obstack = ambient_expression_obstack; return t;}#ifdef GATHER_STATISTICSextern int depth_reached;#endifvoidprint_lang_statistics (){ extern struct obstack decl_obstack; print_obstack_statistics ("class_obstack", &class_obstack); print_obstack_statistics ("decl_obstack", &decl_obstack); print_search_statistics (); print_class_statistics ();#ifdef GATHER_STATISTICS fprintf (stderr, "maximum template instantiation depth reached: %d\n", depth_reached);#endif}/* This is used by the `assert' macro. It is provided in libgcc.a, which `cc' doesn't know how to link. Note that the C++ front-end no longer actually uses the `assert' macro (instead, it calls my_friendly_assert). But all of the back-end files still need this. */void__eprintf (string, expression, line, filename)#ifdef __STDC__ const char *string; const char *expression; unsigned line; const char *filename;#else char *string; char *expression; unsigned line; char *filename;#endif{ fprintf (stderr, string, expression, line, filename); fflush (stderr); abort ();}/* Return, as an INTEGER_CST node, the number of elements for TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */treearray_type_nelts_top (type) tree type;{ return fold (build (PLUS_EXPR, sizetype, array_type_nelts (type), integer_one_node));}/* Return, as an INTEGER_CST node, the number of elements for TYPE (which is an ARRAY_TYPE). This one is a recursive count of all ARRAY_TYPEs that are clumped together. */treearray_type_nelts_total (type) tree type;{ tree sz = array_type_nelts_top (type); type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE) { tree n = array_type_nelts_top (type); sz = fold (build (MULT_EXPR, sizetype, sz, n)); type = TREE_TYPE (type); } return sz;}statictreebot_manip (t) tree t;{ if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t)) return t; else if (TREE_CODE (t) == TARGET_EXPR) { if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR) { mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0)); return build_cplus_new (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1))); } t = copy_node (t); TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t)); layout_decl (TREE_OPERAND (t, 0), 0); return t; } else if (TREE_CODE (t) == CALL_EXPR) mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0)); return NULL_TREE;} /* Actually, we'll just clean out the target exprs for the moment. */treebreak_out_target_exprs (t) tree t;{ return mapcar (t, bot_manip);}/* Obstack used for allocating nodes in template function and variable definitions. *//* Similar to `build_nt', except we build on the permanent_obstack, regardless. */treebuild_min_nt VPROTO((enum tree_code code, ...)){#ifndef __STDC__ enum tree_code code;#endif register struct obstack *ambient_obstack = expression_obstack; va_list p; register tree t; register int length; register int i; VA_START (p, code);#ifndef __STDC__ code = va_arg (p, enum tree_code);#endif expression_obstack = &permanent_obstack; t = make_node (code); length = tree_code_length[(int) code]; TREE_COMPLEXITY (t) = lineno; for (i = 0; i < length; i++) { tree x = va_arg (p, tree); TREE_OPERAND (t, i) = copy_to_permanent (x); } va_end (p); expression_obstack = ambient_obstack; return t;}/* Similar to `build', except we build on the permanent_obstack, regardless. */treebuild_min VPROTO((enum tree_code code, tree tt, ...)){#ifndef __STDC__ enum tree_code code; tree tt;#endif register struct obstack *ambient_obstack = expression_obstack; va_list p; register tree t; register int length; register int i; VA_START (p, tt);#ifndef __STDC__ code = va_arg (p, enum tree_code); tt = va_arg (p, tree);#endif expression_obstack = &permanent_obstack; t = make_node (code); length = tree_code_length[(int) code]; TREE_TYPE (t) = tt; TREE_COMPLEXITY (t) = lineno; for (i = 0; i < length; i++) { tree x = va_arg (p, tree); TREE_OPERAND (t, i) = copy_to_permanent (x); } va_end (p); expression_obstack = ambient_obstack; return t;}/* Same as `tree_cons' but make a permanent object. */treemin_tree_cons (purpose, value, chain) tree purpose, value, chain;{ register tree node; register struct obstack *ambient_obstack = current_obstack; current_obstack = &permanent_obstack; node = tree_cons (copy_to_permanent (purpose), copy_to_permanent (value), chain); current_obstack = ambient_obstack; return node;}treeget_type_decl (t) tree t;{ if (TREE_CODE (t) == IDENTIFIER_NODE) return identifier_typedecl_value (t); if (TREE_CODE (t) == TYPE_DECL) return t; if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') return TYPE_STUB_DECL (t); my_friendly_abort (42);}intcan_free (obstack, t) struct obstack *obstack; tree t;{ int size; if (TREE_CODE (t) == TREE_VEC) size = (TREE_VEC_LENGTH (t)-1) * sizeof (tree) + sizeof (struct tree_vec); else my_friendly_abort (42);#define ROUND(x) ((x + obstack_alignment_mask (obstack)) \ & ~ obstack_alignment_mask (obstack)) if ((char *)t + ROUND (size) == obstack_next_free (obstack)) return 1;#undef ROUND return 0;}/* Return first vector element whose BINFO_TYPE is ELEM. Return 0 if ELEM is not in VEC. VEC may be NULL_TREE. */treevec_binfo_member (elem, vec) tree elem, vec;{ int i; if (vec) for (i = 0; i < TREE_VEC_LENGTH (vec); ++i) if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1)) return TREE_VEC_ELT (vec, i); return NULL_TREE;}/* Kludge around the fact that DECL_CONTEXT for virtual functions returns the wrong thing for decl_function_context. Hopefully the uses in the backend won't matter, since we don't need a static chain for local class methods. FIXME! */treehack_decl_function_context (decl) tree decl;{ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (decl)) return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl))); return decl_function_context (decl);}/* Return truthvalue of whether T1 is the same tree structure as T2. Return 1 if they are the same. Return 0 if they are understandably different. Return -1 if either contains tree structure not understood by this function. */intcp_tree_equal (t1, t2) tree t1, t2;{ register enum tree_code code1, code2; int cmp; if (t1 == t2) return 1; if (t1 == 0 || t2 == 0) return 0; code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR) if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR) return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); else return cp_tree_equal (TREE_OPERAND (t1, 0), t2); else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR) return cp_tree_equal (t1, TREE_OPERAND (t2, 0)); if (code1 != code2) return 0; switch (code1) { case INTEGER_CST: return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2) && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2); case REAL_CST: return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); case STRING_CST: return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2) && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2), TREE_STRING_LENGTH (t1)); case CONSTRUCTOR: abort (); case SAVE_EXPR: return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); case CALL_EXPR: cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); if (cmp <= 0) return cmp; return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); case TARGET_EXPR: /* Special case: if either target is an unallocated VAR_DECL, it means that it's going to be unified with whatever the TARGET_EXPR is really supposed to initialize, so treat it as being equivalent to anything. */ if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE && DECL_RTL (TREE_OPERAND (t1, 0)) == 0) || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE && DECL_RTL (TREE_OPERAND (t2, 0)) == 0)) cmp = 1; else cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); if (cmp <= 0) return cmp; return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); case WITH_CLEANUP_EXPR: cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); if (cmp <= 0) return cmp; return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2)); case COMPONENT_REF: if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1)) return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); return 0; case VAR_DECL: case PARM_DECL: case CONST_DECL: case FUNCTION_DECL: return 0; case TEMPLATE_CONST_PARM: return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2) && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2); case SIZEOF_EXPR: if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0))) return 0; if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't') return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1); break; } switch (TREE_CODE_CLASS (code1)) { int i; case '1': case '2': case '<': case 'e': case 'r': case 's': cmp = 1; for (i=0; i<tree_code_length[(int) code1]; ++i) { cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)); if (cmp <= 0) return cmp; } return cmp; } return -1;}/* Similar to make_tree_vec, but build on a temporary obstack. */treemake_temp_vec (len) int len;{ register tree node; register struct obstack *ambient_obstack = current_obstack; current_obstack = expression_obstack; node = make_tree_vec (len); current_obstack = ambient_obstack; return node;}voidpush_expression_obstack (){ push_obstacks_nochange (); current_obstack = expression_obstack;}/* The type of ARG when used as an lvalue. */treelvalue_type (arg) tree arg;{ return cp_build_type_variant (TREE_TYPE (arg), TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));}/* The type of ARG for printing error messages; denote lvalues with reference types. */treeerror_type (arg) tree arg;{ tree type = TREE_TYPE (arg); if (TREE_CODE (type) == ARRAY_TYPE) ; else if (real_lvalue_p (arg)) type = build_reference_type (lvalue_type (arg)); else if (IS_AGGR_TYPE (type)) type = lvalue_type (arg); return type;}/* Does FUNCTION use a variable-length argument list? */intvarargs_function_p (function) tree function;{ tree parm = TYPE_ARG_TYPES (TREE_TYPE (function)); for (; parm; parm = TREE_CHAIN (parm)) if (TREE_VALUE (parm) == void_type_node) return 0; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -