diff options
Diffstat (limited to 'gcc/cp/tinfo.h')
| -rw-r--r-- | gcc/cp/tinfo.h | 161 |
1 files changed, 152 insertions, 9 deletions
diff --git a/gcc/cp/tinfo.h b/gcc/cp/tinfo.h index ffca9c3..39be84e 100644 --- a/gcc/cp/tinfo.h +++ b/gcc/cp/tinfo.h @@ -10,10 +10,138 @@ struct __user_type_info : public std::type_info { __user_type_info (const char *n) : type_info (n) {} - // If our type can be converted to the desired type, - // return the pointer, adjusted accordingly; else return 0. - virtual int dcast (const type_info &, int, void *, void **, - const type_info * = 0, void * = 0) const; + // If our type can be upcast to a public and unambiguous base, then return + // non-zero and set RES to point to the base object. OBJ points to the throw + // object and can be NULL, if there is no object to adjust. + int upcast (const type_info &target, void *obj, void **res) const; + + // If our type can be dynamicly cast to the target type, then return + // pointer to the target object. OBJ is the pointer to the most derived + // type and cannot be NULL. SUBTYPE and SUBOBJ indicate the static type + // base object from whence we came, it cannot be NULL. SUBTYPE cannot be + // the same as TARGET. TARGET cannot be a base of SUBTYPE. + // BOFF indicates how SUBTYPE is related to TARGET. + // BOFF >= 0, there is only one public non-virtual SUBTYPE base at offset + // BOFF, and there are no public virtual SUBTYPE bases. + // Therefore check if SUBOBJ is at offset BOFF when we find a target + // BOFF == -1, SUBTYPE occurs as multiple public non-virtual bases. + // Lazily search the non-virtual bases of TARGET. + // BOFF == -2, SUBTYPE occurs as multiple public virtual or non-virtual bases. + // Lazily search all the bases of TARGET. + // BOFF == -3, SUBTYPE is not a public base. + // For backwards compatibility set BOFF to -2, that is the safe `don't know' + // value. We don't care about SUBTYPES as private bases of TARGET, as they + // can never succeed as downcasts, only as crosscasts -- and then only if + // they are virtual. This is more complicated that it might seem. + void *dyncast (int boff, + const type_info &target, void *obj, + const type_info &subtype, void *subobj) const; + + // non_virtual_base_type is used to indicate that a base class is via a + // non-virtual access path. + static const type_info *const nonvirtual_base_type + = static_cast <const type_info *> (0) + 1; + + // sub_kind tells us about how a base object is contained within a derived + // object. We often do this lazily, hence the UNKNOWN value. At other times + // we may use NOT_CONTAINED to mean not publicly contained. + enum sub_kind + { + unknown = 0, // we have no idea + not_contained, // not contained within us (in some + // circumstances this might mean not contained + // publicly) + contained_ambig, // contained ambiguously + contained_mask = 4, // contained within us + contained_virtual_mask = 1, // via a virtual path + contained_public_mask = 2, // via a public path + contained_private = contained_mask, + contained_public = contained_mask | contained_public_mask + }; + // some predicate functions for sub_kind + static inline bool contained_p (sub_kind access_path) + { + return access_path >= contained_mask; + } + static inline bool contained_public_p (sub_kind access_path) + { + return access_path >= contained_public; + } + static inline bool contained_nonpublic_p (sub_kind access_path) + { + return (access_path & contained_public) == contained_mask; + } + static inline bool contained_nonvirtual_p (sub_kind access_path) + { + return (access_path & (contained_mask | contained_virtual_mask)) + == contained_mask; + } + + struct upcast_result + { + void *target_obj; // pointer to target object or NULL (init NULL) + sub_kind whole2target; // path from most derived object to target + const type_info *base_type; // where we found the target, (init NULL) + // if in vbase the __user_type_info of vbase) + // if a non-virtual base then 1 + // else NULL + public: + upcast_result () + :target_obj (NULL), whole2target (unknown), base_type (NULL) + {} + }; + struct dyncast_result + { + void *target_obj; // pointer to target object or NULL (init NULL) + sub_kind whole2target; // path from most derived object to target + sub_kind whole2sub; // path from most derived object to sub object + sub_kind target2sub; // path from target to sub object + + public: + dyncast_result () + :target_obj (NULL), whole2target (unknown), + whole2sub (unknown), target2sub (unknown) + {} + }; + + public: + // Helper for upcast. See if TARGET is us, or one of our bases. ACCESS_PATH + // gives the access from the start object. Return TRUE if we know the catch + // fails. + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + // Helper for dyncast. BOFF indicates how the SUBTYPE is related to TARGET. + // ACCESS_PATH indicates the access from the most derived object. It is + // used to prune the DAG walk. All information about what we find is put + // into RESULT. Return true, if the match we have found is ambiguous. + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + public: + // Indicate whether SUBPTR of type SUBTYPE is contained publicly within + // OBJPTR. OBJPTR points to this base object. BOFF indicates how SUBTYPE + // objects might be contained within this type. If SUBPTR is one of our + // SUBTYPE bases, indicate virtuality. Returns not_contained for non + // containment or private containment. + sub_kind find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const + { + if (boff >= 0) + return ((char *)subptr - (char *)objptr) == boff + ? contained_public : not_contained; + if (boff == -3) + return not_contained; + return do_find_public_subobj (boff, subtype, objptr, subptr); + } + + public: + // Helper for find_subobj. BOFF indicates how SUBTYPE bases are inherited by + // the type started from -- which is not necessarily the current type. + // OBJPTR points to the current base. + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; }; // type_info for a class with one public, nonvirtual base class. @@ -25,8 +153,16 @@ public: __si_type_info (const char *n, const __user_type_info &b) : __user_type_info (n), base (b) { } - virtual int dcast (const type_info &, int, void *, void **, - const type_info * = 0, void * = 0) const; + private: + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; }; // type_info for a general class. @@ -49,7 +185,14 @@ struct __class_type_info : public __user_type_info { __class_type_info (const char *name, const base_info *bl, size_t bn) : __user_type_info (name), base_list (bl), n_bases (bn) {} - // This is a little complex. - virtual int dcast (const type_info &, int, void *, void **, - const type_info * = 0, void * = 0) const; + public: + virtual bool do_upcast (sub_kind access_path, + const type_info &target, void *obj, + upcast_result &__restrict result) const; + virtual bool do_dyncast (int boff, sub_kind access_path, + const type_info &target, void *obj, + const type_info &subtype, void *subptr, + dyncast_result &__restrict result) const; + virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype, + void *objptr, void *subptr) const; }; |
