diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 56 |
1 files changed, 56 insertions, 0 deletions
@@ -10779,4 +10779,60 @@ lhd_gcc_personality (void) return gcc_eh_personality_decl; } +/* Try to find a base info of BINFO that would have its field decl at offset + OFFSET within the BINFO type and which is of EXPECTED_TYPE. If it can be + found, return, otherwise return NULL_TREE. */ + +tree +get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type) +{ + tree type; + + if (offset == 0) + return binfo; + + type = TREE_TYPE (binfo); + while (offset > 0) + { + tree base_binfo, found_binfo; + HOST_WIDE_INT pos, size; + tree fld; + int i; + + if (TREE_CODE (type) != RECORD_TYPE) + return NULL_TREE; + + for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld)) + { + if (TREE_CODE (fld) != FIELD_DECL) + continue; + + pos = int_bit_position (fld); + size = tree_low_cst (DECL_SIZE (fld), 1); + if (pos <= offset && (pos + size) > offset) + break; + } + if (!fld) + return NULL_TREE; + + found_binfo = NULL_TREE; + for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + if (TREE_TYPE (base_binfo) == TREE_TYPE (fld)) + { + found_binfo = base_binfo; + break; + } + + if (!found_binfo) + return NULL_TREE; + + type = TREE_TYPE (fld); + binfo = found_binfo; + offset -= pos; + } + if (type != expected_type) + return NULL_TREE; + return binfo; +} + #include "gt-tree.h" |