]> git.ipfire.org Git - thirdparty/gcc.git/blame - libphobos/libdruntime/rt/cast_.d
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
[thirdparty/gcc.git] / libphobos / libdruntime / rt / cast_.d
CommitLineData
b4c522fa
IB
1/**
2 * Implementation of array assignment support routines.
3 *
4 * Copyright: Copyright Digital Mars 2004 - 2010.
5fee5ec3 5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
b4c522fa 6 * Authors: Walter Bright, Sean Kelly
5fee5ec3 7 * Source: $(DRUNTIMESRC rt/_cast_.d)
b4c522fa
IB
8 */
9
10/* Copyright Digital Mars 2004 - 2010.
11 * Distributed under the Boost Software License, Version 1.0.
12 * (See accompanying file LICENSE or copy at
13 * http://www.boost.org/LICENSE_1_0.txt)
14 */
15module rt.cast_;
16
17extern (C):
5fee5ec3
IB
18@nogc:
19nothrow:
20pure:
21
22// Needed because ClassInfo.opEquals(Object) does a dynamic cast,
23// but we are trying to implement dynamic cast.
24extern (D) private bool areClassInfosEqual(scope const ClassInfo a, scope const ClassInfo b) @safe
25{
26 if (a is b)
27 return true;
28 // take care of potential duplicates across binaries
29 return a.name == b.name;
30}
b4c522fa
IB
31
32/******************************************
33 * Given a pointer:
34 * If it is an Object, return that Object.
35 * If it is an interface, return the Object implementing the interface.
36 * If it is null, return null.
37 * Else, undefined crash
38 */
5fee5ec3 39Object _d_toObject(return void* p)
b4c522fa
IB
40{
41 if (!p)
42 return null;
43
44 Object o = cast(Object) p;
45 ClassInfo oc = typeid(o);
46 Interface* pi = **cast(Interface***) p;
47
48 /* Interface.offset lines up with ClassInfo.name.ptr,
49 * so we rely on pointers never being less than 64K,
50 * and Objects never being greater.
51 */
52 if (pi.offset < 0x10000)
53 {
54 debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
55 return cast(Object)(p - pi.offset);
56 }
57 return o;
58}
59
60/*************************************
61 * Attempts to cast Object o to class c.
62 * Returns o if successful, null if not.
63 */
64void* _d_interface_cast(void* p, ClassInfo c)
65{
66 debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
67 if (!p)
68 return null;
69
70 Interface* pi = **cast(Interface***) p;
71
72 debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
73 return _d_dynamic_cast(cast(Object)(p - pi.offset), c);
74}
75
76void* _d_dynamic_cast(Object o, ClassInfo c)
77{
78 debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
79
80 void* res = null;
81 size_t offset = 0;
82 if (o && _d_isbaseof2(typeid(o), c, offset))
83 {
84 debug(cast_) printf("\toffset = %d\n", offset);
85 res = cast(void*) o + offset;
86 }
87 debug(cast_) printf("\tresult = %p\n", res);
88 return res;
89}
90
5fee5ec3 91int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t offset) @safe
b4c522fa 92{
5fee5ec3 93 if (areClassInfosEqual(oc, c))
b4c522fa
IB
94 return true;
95
96 do
97 {
5fee5ec3 98 if (oc.base && areClassInfosEqual(oc.base, c))
b4c522fa
IB
99 return true;
100
101 // Bugzilla 2013: Use depth-first search to calculate offset
102 // from the derived (oc) to the base (c).
103 foreach (iface; oc.interfaces)
104 {
5fee5ec3 105 if (areClassInfosEqual(iface.classinfo, c) || _d_isbaseof2(iface.classinfo, c, offset))
b4c522fa
IB
106 {
107 offset += iface.offset;
108 return true;
109 }
110 }
111
112 oc = oc.base;
113 } while (oc);
114
115 return false;
116}
117
5fee5ec3 118int _d_isbaseof(scope ClassInfo oc, scope const ClassInfo c) @safe
b4c522fa 119{
5fee5ec3 120 if (areClassInfosEqual(oc, c))
b4c522fa
IB
121 return true;
122
123 do
124 {
5fee5ec3 125 if (oc.base && areClassInfosEqual(oc.base, c))
b4c522fa
IB
126 return true;
127
128 foreach (iface; oc.interfaces)
129 {
5fee5ec3 130 if (areClassInfosEqual(iface.classinfo, c) || _d_isbaseof(iface.classinfo, c))
b4c522fa
IB
131 return true;
132 }
133
134 oc = oc.base;
135 } while (oc);
136
137 return false;
138}