📄 tree.c
字号:
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)) { t = copy_node (t); /* copy_rtx won't make a new SYMBOL_REF, so call make_decl_rtl again. */ DECL_RTL (t) = 0; make_decl_rtl (t, NULL_PTR, 1); return 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;{ if (t == NULL_TREE || TREE_PERMANENT (t)) return t; push_obstacks_nochange (); end_temporary_allocation (); t = mapcar (t, perm_manip); pop_obstacks (); 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) const char *string; const char *expression; unsigned line; const char *filename;{ 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)) == AGGR_INIT_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) = copy_to_permanent (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) == TYPE_DECL) return t; if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') return TYPE_STUB_DECL (t); my_friendly_abort (42); /* Stop compiler from complaining control reaches end of non-void function. */ return 0;}intcan_free (obstack, t) struct obstack *obstack; tree t;{ int size = 0; 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 (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)))) 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);}/* Returns the namespace that contains DECL, whether directly or indirectly. */treedecl_namespace_context (decl) tree decl;{ while (1) { if (TREE_CODE (decl) == NAMESPACE_DECL) return decl; else if (TYPE_P (decl)) decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl)); else decl = CP_DECL_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: /* We need to do this when determining whether or not two non-type pointer to member function template arguments are the same. */ if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) /* The first operand is RTL. */ && TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0))) return 0; return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); case TREE_LIST: cmp = cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); if (cmp <= 0) return cmp; cmp = cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)); if (cmp <= 0) return cmp; return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2)); 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_PARM_INDEX: return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2) && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2); case SIZEOF_EXPR: case ALIGNOF_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 same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); break; case PTRMEM_CST: /* Two pointer-to-members are the same if they point to the same field or function in the same class. */ return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2) && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2))); default: 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 the momentary_obstack. Thus, these vectors are really and truly temporary. */treemake_temp_vec (len) int len;{ register tree node; push_expression_obstack (); node = make_tree_vec (len); pop_obstacks (); return node;}/* Build a wrapper around some pointer PTR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -