aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/libsupc++/tinfo.h
blob: 456f715eeb3c0fc566d00055e4b702fee14377d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
// RTTI support internals for -*- C++ -*-
// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation

#include "typeinfo"
#include <cstddef>

// Class declarations shared between the typeinfo implementation files.

#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
// original (old) abi

// type_info for a class with no base classes (or an enum).

struct __user_type_info : public std::type_info {
  __user_type_info (const char *n) : type_info (n) {}

  // 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 virtual or non-virtual bases.
  //    Lazily search all the bases of TARGET.
  // BOFF == -2, SUBTYPE is not a public base.
  // BOFF == -3, SUBTYPE occurs as multiple public non-virtual bases.
  //    Lazily search the non-virtual bases of TARGET.
  // For backwards compatibility set BOFF to -1, that is the safe "unknown"
  // value. We do not 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;
  }
  static inline bool contained_virtual_p (sub_kind access_path)
  {
    return (access_path & (contained_mask | contained_virtual_mask))
           == (contained_mask | contained_virtual_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 == -2)
      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.

class __si_type_info : public __user_type_info {
  const __user_type_info &base;

public:
  __si_type_info (const char *n, const __user_type_info &b)
    : __user_type_info (n), base (b) { }

  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.

#include <climits>

#if INT_MAX == 2147483647
typedef int myint32;
#elif SHRT_MAX == 2147483647
typedef short myint32;
#elif SCHAR_MAX == 2147483647
typedef signed char myint32;
#elif LONG_MAX == 2147483647
typedef long myint32;
#else
# error "No 32-bit data type?"
#endif

struct __class_type_info : public __user_type_info {
  enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };

  struct base_info {
    const __user_type_info *base;
    myint32 offset: 29;
    bool is_virtual: 1;
    enum access access: 2;
  };

  const base_info *base_list;
  std::size_t n_bases;

  __class_type_info (const char *name, const base_info *bl, std::size_t bn)
    : __user_type_info (name), base_list (bl), n_bases (bn) {}

  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;
};
#else
// new abi
#include <cxxabi.h>

#endif