145
|
1
|
|
2 /* Compiler implementation of the D programming language
|
|
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
|
|
4 * written by Walter Bright
|
|
5 * http://www.digitalmars.com
|
|
6 * Distributed under the Boost Software License, Version 1.0.
|
|
7 * http://www.boost.org/LICENSE_1_0.txt
|
|
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/class.c
|
|
9 */
|
|
10
|
|
11 #include "root/dsystem.h" // mem{cpy|set}()
|
|
12 #include "root/root.h"
|
|
13 #include "root/rmem.h"
|
|
14
|
|
15 #include "errors.h"
|
|
16 #include "enum.h"
|
|
17 #include "init.h"
|
|
18 #include "attrib.h"
|
|
19 #include "declaration.h"
|
|
20 #include "aggregate.h"
|
|
21 #include "id.h"
|
|
22 #include "mtype.h"
|
|
23 #include "scope.h"
|
|
24 #include "module.h"
|
|
25 #include "expression.h"
|
|
26 #include "statement.h"
|
|
27 #include "template.h"
|
|
28 #include "target.h"
|
|
29 #include "objc.h"
|
|
30
|
|
31 bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
|
|
32 Objc *objc();
|
|
33
|
|
34
|
|
35 /********************************* ClassDeclaration ****************************/
|
|
36
|
|
37 ClassDeclaration *ClassDeclaration::object;
|
|
38 ClassDeclaration *ClassDeclaration::throwable;
|
|
39 ClassDeclaration *ClassDeclaration::exception;
|
|
40 ClassDeclaration *ClassDeclaration::errorException;
|
|
41 ClassDeclaration *ClassDeclaration::cpp_type_info_ptr; // Object.__cpp_type_info_ptr
|
|
42
|
|
43 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
|
|
44 : AggregateDeclaration(loc, id ? id : Identifier::generateId("__anonclass"))
|
|
45 {
|
|
46 static const char msg[] = "only object.d can define this reserved class name";
|
|
47
|
|
48 if (baseclasses)
|
|
49 {
|
|
50 // Actually, this is a transfer
|
|
51 this->baseclasses = baseclasses;
|
|
52 }
|
|
53 else
|
|
54 this->baseclasses = new BaseClasses();
|
|
55
|
|
56 this->members = members;
|
|
57
|
|
58 baseClass = NULL;
|
|
59
|
|
60 interfaces.length = 0;
|
|
61 interfaces.ptr = NULL;
|
|
62
|
|
63 vtblInterfaces = NULL;
|
|
64
|
|
65 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim);
|
|
66
|
|
67 // For forward references
|
|
68 type = new TypeClass(this);
|
|
69
|
|
70 staticCtor = NULL;
|
|
71 staticDtor = NULL;
|
|
72
|
|
73 vtblsym = NULL;
|
|
74 vclassinfo = NULL;
|
|
75
|
|
76 if (id)
|
|
77 {
|
|
78 // Look for special class names
|
|
79
|
|
80 if (id == Id::__sizeof || id == Id::__xalignof || id == Id::_mangleof)
|
|
81 error("illegal class name");
|
|
82
|
|
83 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
|
|
84 if (id->toChars()[0] == 'T')
|
|
85 {
|
|
86 if (id == Id::TypeInfo)
|
|
87 {
|
|
88 if (!inObject)
|
|
89 error("%s", msg);
|
|
90 Type::dtypeinfo = this;
|
|
91 }
|
|
92
|
|
93 if (id == Id::TypeInfo_Class)
|
|
94 {
|
|
95 if (!inObject)
|
|
96 error("%s", msg);
|
|
97 Type::typeinfoclass = this;
|
|
98 }
|
|
99
|
|
100 if (id == Id::TypeInfo_Interface)
|
|
101 {
|
|
102 if (!inObject)
|
|
103 error("%s", msg);
|
|
104 Type::typeinfointerface = this;
|
|
105 }
|
|
106
|
|
107 if (id == Id::TypeInfo_Struct)
|
|
108 {
|
|
109 if (!inObject)
|
|
110 error("%s", msg);
|
|
111 Type::typeinfostruct = this;
|
|
112 }
|
|
113
|
|
114 if (id == Id::TypeInfo_Pointer)
|
|
115 {
|
|
116 if (!inObject)
|
|
117 error("%s", msg);
|
|
118 Type::typeinfopointer = this;
|
|
119 }
|
|
120
|
|
121 if (id == Id::TypeInfo_Array)
|
|
122 {
|
|
123 if (!inObject)
|
|
124 error("%s", msg);
|
|
125 Type::typeinfoarray = this;
|
|
126 }
|
|
127
|
|
128 if (id == Id::TypeInfo_StaticArray)
|
|
129 {
|
|
130 //if (!inObject)
|
|
131 // Type::typeinfostaticarray->error("%s", msg);
|
|
132 Type::typeinfostaticarray = this;
|
|
133 }
|
|
134
|
|
135 if (id == Id::TypeInfo_AssociativeArray)
|
|
136 {
|
|
137 if (!inObject)
|
|
138 error("%s", msg);
|
|
139 Type::typeinfoassociativearray = this;
|
|
140 }
|
|
141
|
|
142 if (id == Id::TypeInfo_Enum)
|
|
143 {
|
|
144 if (!inObject)
|
|
145 error("%s", msg);
|
|
146 Type::typeinfoenum = this;
|
|
147 }
|
|
148
|
|
149 if (id == Id::TypeInfo_Function)
|
|
150 {
|
|
151 if (!inObject)
|
|
152 error("%s", msg);
|
|
153 Type::typeinfofunction = this;
|
|
154 }
|
|
155
|
|
156 if (id == Id::TypeInfo_Delegate)
|
|
157 {
|
|
158 if (!inObject)
|
|
159 error("%s", msg);
|
|
160 Type::typeinfodelegate = this;
|
|
161 }
|
|
162
|
|
163 if (id == Id::TypeInfo_Tuple)
|
|
164 {
|
|
165 if (!inObject)
|
|
166 error("%s", msg);
|
|
167 Type::typeinfotypelist = this;
|
|
168 }
|
|
169
|
|
170 if (id == Id::TypeInfo_Const)
|
|
171 {
|
|
172 if (!inObject)
|
|
173 error("%s", msg);
|
|
174 Type::typeinfoconst = this;
|
|
175 }
|
|
176
|
|
177 if (id == Id::TypeInfo_Invariant)
|
|
178 {
|
|
179 if (!inObject)
|
|
180 error("%s", msg);
|
|
181 Type::typeinfoinvariant = this;
|
|
182 }
|
|
183
|
|
184 if (id == Id::TypeInfo_Shared)
|
|
185 {
|
|
186 if (!inObject)
|
|
187 error("%s", msg);
|
|
188 Type::typeinfoshared = this;
|
|
189 }
|
|
190
|
|
191 if (id == Id::TypeInfo_Wild)
|
|
192 {
|
|
193 if (!inObject)
|
|
194 error("%s", msg);
|
|
195 Type::typeinfowild = this;
|
|
196 }
|
|
197
|
|
198 if (id == Id::TypeInfo_Vector)
|
|
199 {
|
|
200 if (!inObject)
|
|
201 error("%s", msg);
|
|
202 Type::typeinfovector = this;
|
|
203 }
|
|
204 }
|
|
205
|
|
206 if (id == Id::Object)
|
|
207 {
|
|
208 if (!inObject)
|
|
209 error("%s", msg);
|
|
210 object = this;
|
|
211 }
|
|
212
|
|
213 if (id == Id::Throwable)
|
|
214 {
|
|
215 if (!inObject)
|
|
216 error("%s", msg);
|
|
217 throwable = this;
|
|
218 }
|
|
219
|
|
220 if (id == Id::Exception)
|
|
221 {
|
|
222 if (!inObject)
|
|
223 error("%s", msg);
|
|
224 exception = this;
|
|
225 }
|
|
226
|
|
227 if (id == Id::Error)
|
|
228 {
|
|
229 if (!inObject)
|
|
230 error("%s", msg);
|
|
231 errorException = this;
|
|
232 }
|
|
233
|
|
234 if (id == Id::cpp_type_info_ptr)
|
|
235 {
|
|
236 if (!inObject)
|
|
237 error("%s", msg);
|
|
238 cpp_type_info_ptr = this;
|
|
239 }
|
|
240 }
|
|
241
|
|
242 com = false;
|
|
243 cpp = false;
|
|
244 isscope = false;
|
|
245 isabstract = ABSfwdref;
|
|
246 inuse = 0;
|
|
247 baseok = BASEOKnone;
|
|
248 isobjc = false;
|
|
249 cpp_type_info_ptr_sym = NULL;
|
|
250 }
|
|
251
|
|
252 ClassDeclaration *ClassDeclaration::create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
|
|
253 {
|
|
254 return new ClassDeclaration(loc, id, baseclasses, members, inObject);
|
|
255 }
|
|
256
|
|
257 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
|
|
258 {
|
|
259 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
|
|
260 ClassDeclaration *cd =
|
|
261 s ? (ClassDeclaration *)s
|
|
262 : new ClassDeclaration(loc, ident, NULL, NULL, false);
|
|
263
|
|
264 cd->storage_class |= storage_class;
|
|
265
|
|
266 cd->baseclasses->setDim(this->baseclasses->dim);
|
|
267 for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
|
268 {
|
|
269 BaseClass *b = (*this->baseclasses)[i];
|
|
270 BaseClass *b2 = new BaseClass(b->type->syntaxCopy());
|
|
271 (*cd->baseclasses)[i] = b2;
|
|
272 }
|
|
273
|
|
274 return ScopeDsymbol::syntaxCopy(cd);
|
|
275 }
|
|
276
|
|
277 Scope *ClassDeclaration::newScope(Scope *sc)
|
|
278 {
|
|
279 Scope *sc2 = AggregateDeclaration::newScope(sc);
|
|
280 if (isCOMclass())
|
|
281 {
|
|
282 if (global.params.isWindows)
|
|
283 sc2->linkage = LINKwindows;
|
|
284 else
|
|
285 {
|
|
286 /* This enables us to use COM objects under Linux and
|
|
287 * work with things like XPCOM
|
|
288 */
|
|
289 sc2->linkage = LINKc;
|
|
290 }
|
|
291 }
|
|
292 return sc2;
|
|
293 }
|
|
294
|
|
295 /* Bugzilla 12078, 12143 and 15733:
|
|
296 * While resolving base classes and interfaces, a base may refer
|
|
297 * the member of this derived class. In that time, if all bases of
|
|
298 * this class can be determined, we can go forward the semantc process
|
|
299 * beyond the Lancestorsdone. To do the recursive semantic analysis,
|
|
300 * temporarily set and unset `_scope` around exp().
|
|
301 */
|
|
302 static Type *resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, Type *type)
|
|
303 {
|
|
304 if (!scx)
|
|
305 {
|
|
306 scx = sc->copy();
|
|
307 scx->setNoFree();
|
|
308 }
|
|
309 cd->_scope = scx;
|
|
310 Type *t = type->semantic(cd->loc, sc);
|
|
311 cd->_scope = NULL;
|
|
312 return t;
|
|
313 }
|
|
314
|
|
315 static void resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, ClassDeclaration *sym)
|
|
316 {
|
|
317 if (!scx)
|
|
318 {
|
|
319 scx = sc->copy();
|
|
320 scx->setNoFree();
|
|
321 }
|
|
322 cd->_scope = scx;
|
|
323 sym->semantic(NULL);
|
|
324 cd->_scope = NULL;
|
|
325 }
|
|
326
|
|
327 static void badObjectDotD(ClassDeclaration *cd)
|
|
328 {
|
|
329 cd->error("missing or corrupt object.d");
|
|
330 fatal();
|
|
331 }
|
|
332
|
|
333 void ClassDeclaration::semantic(Scope *sc)
|
|
334 {
|
|
335 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
|
|
336 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
|
|
337 //printf("sc->stc = %x\n", sc->stc);
|
|
338
|
|
339 //{ static int n; if (++n == 20) *(char*)0=0; }
|
|
340
|
|
341 if (semanticRun >= PASSsemanticdone)
|
|
342 return;
|
|
343 unsigned errors = global.errors;
|
|
344
|
|
345 //printf("+ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
|
|
346
|
|
347 Scope *scx = NULL;
|
|
348 if (_scope)
|
|
349 {
|
|
350 sc = _scope;
|
|
351 scx = _scope; // save so we don't make redundant copies
|
|
352 _scope = NULL;
|
|
353 }
|
|
354
|
|
355 if (!parent)
|
|
356 {
|
|
357 assert(sc->parent);
|
|
358 parent = sc->parent;
|
|
359 }
|
|
360
|
|
361 if (this->errors)
|
|
362 type = Type::terror;
|
|
363 type = type->semantic(loc, sc);
|
|
364
|
|
365 if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
|
|
366 {
|
|
367 TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
|
|
368 if (ti && isError(ti))
|
|
369 ((TypeClass *)type)->sym = this;
|
|
370 }
|
|
371
|
|
372 // Ungag errors when not speculative
|
|
373 Ungag ungag = ungagSpeculative();
|
|
374
|
|
375 if (semanticRun == PASSinit)
|
|
376 {
|
|
377 protection = sc->protection;
|
|
378
|
|
379 storage_class |= sc->stc;
|
|
380 if (storage_class & STCdeprecated)
|
|
381 isdeprecated = true;
|
|
382 if (storage_class & STCauto)
|
|
383 error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
|
|
384 if (storage_class & STCscope)
|
|
385 isscope = true;
|
|
386 if (storage_class & STCabstract)
|
|
387 isabstract = ABSyes;
|
|
388
|
|
389 userAttribDecl = sc->userAttribDecl;
|
|
390
|
|
391 if (sc->linkage == LINKcpp)
|
|
392 cpp = true;
|
|
393 if (sc->linkage == LINKobjc)
|
|
394 objc()->setObjc(this);
|
|
395 }
|
|
396 else if (symtab && !scx)
|
|
397 {
|
|
398 semanticRun = PASSsemanticdone;
|
|
399 return;
|
|
400 }
|
|
401 semanticRun = PASSsemantic;
|
|
402
|
|
403 if (baseok < BASEOKdone)
|
|
404 {
|
|
405 baseok = BASEOKin;
|
|
406
|
|
407 // Expand any tuples in baseclasses[]
|
|
408 for (size_t i = 0; i < baseclasses->dim; )
|
|
409 {
|
|
410 BaseClass *b = (*baseclasses)[i];
|
|
411 b->type = resolveBase(this, sc, scx, b->type);
|
|
412
|
|
413 Type *tb = b->type->toBasetype();
|
|
414 if (tb->ty == Ttuple)
|
|
415 {
|
|
416 TypeTuple *tup = (TypeTuple *)tb;
|
|
417 baseclasses->remove(i);
|
|
418 size_t dim = Parameter::dim(tup->arguments);
|
|
419 for (size_t j = 0; j < dim; j++)
|
|
420 {
|
|
421 Parameter *arg = Parameter::getNth(tup->arguments, j);
|
|
422 b = new BaseClass(arg->type);
|
|
423 baseclasses->insert(i + j, b);
|
|
424 }
|
|
425 }
|
|
426 else
|
|
427 i++;
|
|
428 }
|
|
429
|
|
430 if (baseok >= BASEOKdone)
|
|
431 {
|
|
432 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
|
|
433 if (semanticRun >= PASSsemanticdone)
|
|
434 return;
|
|
435 goto Lancestorsdone;
|
|
436 }
|
|
437
|
|
438 // See if there's a base class as first in baseclasses[]
|
|
439 if (baseclasses->dim)
|
|
440 {
|
|
441 BaseClass *b = (*baseclasses)[0];
|
|
442 Type *tb = b->type->toBasetype();
|
|
443 TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
|
|
444 if (!tc)
|
|
445 {
|
|
446 if (b->type != Type::terror)
|
|
447 error("base type must be class or interface, not %s", b->type->toChars());
|
|
448 baseclasses->remove(0);
|
|
449 goto L7;
|
|
450 }
|
|
451
|
|
452 if (tc->sym->isDeprecated())
|
|
453 {
|
|
454 if (!isDeprecated())
|
|
455 {
|
|
456 // Deriving from deprecated class makes this one deprecated too
|
|
457 isdeprecated = true;
|
|
458
|
|
459 tc->checkDeprecated(loc, sc);
|
|
460 }
|
|
461 }
|
|
462
|
|
463 if (tc->sym->isInterfaceDeclaration())
|
|
464 goto L7;
|
|
465
|
|
466 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
|
|
467 {
|
|
468 if (cdb == this)
|
|
469 {
|
|
470 error("circular inheritance");
|
|
471 baseclasses->remove(0);
|
|
472 goto L7;
|
|
473 }
|
|
474 }
|
|
475
|
|
476 /* Bugzilla 11034: Essentially, class inheritance hierarchy
|
|
477 * and instance size of each classes are orthogonal information.
|
|
478 * Therefore, even if tc->sym->sizeof == SIZEOKnone,
|
|
479 * we need to set baseClass field for class covariance check.
|
|
480 */
|
|
481 baseClass = tc->sym;
|
|
482 b->sym = baseClass;
|
|
483
|
|
484 if (tc->sym->baseok < BASEOKdone)
|
|
485 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
|
|
486 if (tc->sym->baseok < BASEOKdone)
|
|
487 {
|
|
488 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
|
|
489 if (tc->sym->_scope)
|
|
490 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
|
|
491 baseok = BASEOKnone;
|
|
492 }
|
|
493 L7: ;
|
|
494 }
|
|
495
|
|
496 // Treat the remaining entries in baseclasses as interfaces
|
|
497 // Check for errors, handle forward references
|
|
498 for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
|
|
499 {
|
|
500 BaseClass *b = (*baseclasses)[i];
|
|
501 Type *tb = b->type->toBasetype();
|
|
502 TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
|
|
503 if (!tc || !tc->sym->isInterfaceDeclaration())
|
|
504 {
|
|
505 if (b->type != Type::terror)
|
|
506 error("base type must be interface, not %s", b->type->toChars());
|
|
507 baseclasses->remove(i);
|
|
508 continue;
|
|
509 }
|
|
510
|
|
511 // Check for duplicate interfaces
|
|
512 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
|
|
513 {
|
|
514 BaseClass *b2 = (*baseclasses)[j];
|
|
515 if (b2->sym == tc->sym)
|
|
516 {
|
|
517 error("inherits from duplicate interface %s", b2->sym->toChars());
|
|
518 baseclasses->remove(i);
|
|
519 continue;
|
|
520 }
|
|
521 }
|
|
522
|
|
523 if (tc->sym->isDeprecated())
|
|
524 {
|
|
525 if (!isDeprecated())
|
|
526 {
|
|
527 // Deriving from deprecated class makes this one deprecated too
|
|
528 isdeprecated = true;
|
|
529
|
|
530 tc->checkDeprecated(loc, sc);
|
|
531 }
|
|
532 }
|
|
533
|
|
534 b->sym = tc->sym;
|
|
535
|
|
536 if (tc->sym->baseok < BASEOKdone)
|
|
537 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
|
|
538 if (tc->sym->baseok < BASEOKdone)
|
|
539 {
|
|
540 //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
|
|
541 if (tc->sym->_scope)
|
|
542 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
|
|
543 baseok = BASEOKnone;
|
|
544 }
|
|
545 i++;
|
|
546 }
|
|
547 if (baseok == BASEOKnone)
|
|
548 {
|
|
549 // Forward referencee of one or more bases, try again later
|
|
550 _scope = scx ? scx : sc->copy();
|
|
551 _scope->setNoFree();
|
|
552 _scope->_module->addDeferredSemantic(this);
|
|
553 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
|
|
554 return;
|
|
555 }
|
|
556 baseok = BASEOKdone;
|
|
557
|
|
558 // If no base class, and this is not an Object, use Object as base class
|
|
559 if (!baseClass && ident != Id::Object && !cpp)
|
|
560 {
|
|
561 if (!object || object->errors)
|
|
562 badObjectDotD(this);
|
|
563
|
|
564 Type *t = object->type;
|
|
565 t = t->semantic(loc, sc)->toBasetype();
|
|
566 if (t->ty == Terror)
|
|
567 badObjectDotD(this);
|
|
568 assert(t->ty == Tclass);
|
|
569 TypeClass *tc = (TypeClass *)t;
|
|
570
|
|
571 BaseClass *b = new BaseClass(tc);
|
|
572 baseclasses->shift(b);
|
|
573
|
|
574 baseClass = tc->sym;
|
|
575 assert(!baseClass->isInterfaceDeclaration());
|
|
576 b->sym = baseClass;
|
|
577 }
|
|
578 if (baseClass)
|
|
579 {
|
|
580 if (baseClass->storage_class & STCfinal)
|
|
581 error("cannot inherit from final class %s", baseClass->toChars());
|
|
582
|
|
583 // Inherit properties from base class
|
|
584 if (baseClass->isCOMclass())
|
|
585 com = true;
|
|
586 if (baseClass->isCPPclass())
|
|
587 cpp = true;
|
|
588 if (baseClass->isscope)
|
|
589 isscope = true;
|
|
590 enclosing = baseClass->enclosing;
|
|
591 storage_class |= baseClass->storage_class & STC_TYPECTOR;
|
|
592 }
|
|
593
|
|
594 interfaces.length = baseclasses->dim - (baseClass ? 1 : 0);
|
|
595 interfaces.ptr = baseclasses->tdata() + (baseClass ? 1 : 0);
|
|
596
|
|
597 for (size_t i = 0; i < interfaces.length; i++)
|
|
598 {
|
|
599 BaseClass *b = interfaces.ptr[i];
|
|
600 // If this is an interface, and it derives from a COM interface,
|
|
601 // then this is a COM interface too.
|
|
602 if (b->sym->isCOMinterface())
|
|
603 com = true;
|
|
604 if (cpp && !b->sym->isCPPinterface())
|
|
605 {
|
|
606 ::error(loc, "C++ class '%s' cannot implement D interface '%s'",
|
|
607 toPrettyChars(), b->sym->toPrettyChars());
|
|
608 }
|
|
609 }
|
|
610
|
|
611 interfaceSemantic(sc);
|
|
612 }
|
|
613 Lancestorsdone:
|
|
614 //printf("\tClassDeclaration::semantic(%s) baseok = %d\n", toChars(), baseok);
|
|
615
|
|
616 if (!members) // if opaque declaration
|
|
617 {
|
|
618 semanticRun = PASSsemanticdone;
|
|
619 return;
|
|
620 }
|
|
621 if (!symtab)
|
|
622 {
|
|
623 symtab = new DsymbolTable();
|
|
624
|
|
625 /* Bugzilla 12152: The semantic analysis of base classes should be finished
|
|
626 * before the members semantic analysis of this class, in order to determine
|
|
627 * vtbl in this class. However if a base class refers the member of this class,
|
|
628 * it can be resolved as a normal forward reference.
|
|
629 * Call addMember() and setScope() to make this class members visible from the base classes.
|
|
630 */
|
|
631 for (size_t i = 0; i < members->dim; i++)
|
|
632 {
|
|
633 Dsymbol *s = (*members)[i];
|
|
634 s->addMember(sc, this);
|
|
635 }
|
|
636
|
|
637 Scope *sc2 = newScope(sc);
|
|
638
|
|
639 /* Set scope so if there are forward references, we still might be able to
|
|
640 * resolve individual members like enums.
|
|
641 */
|
|
642 for (size_t i = 0; i < members->dim; i++)
|
|
643 {
|
|
644 Dsymbol *s = (*members)[i];
|
|
645 //printf("[%d] setScope %s %s, sc2 = %p\n", i, s->kind(), s->toChars(), sc2);
|
|
646 s->setScope(sc2);
|
|
647 }
|
|
648
|
|
649 sc2->pop();
|
|
650 }
|
|
651
|
|
652 for (size_t i = 0; i < baseclasses->dim; i++)
|
|
653 {
|
|
654 BaseClass *b = (*baseclasses)[i];
|
|
655 Type *tb = b->type->toBasetype();
|
|
656 assert(tb->ty == Tclass);
|
|
657 TypeClass *tc = (TypeClass *)tb;
|
|
658
|
|
659 if (tc->sym->semanticRun < PASSsemanticdone)
|
|
660 {
|
|
661 // Forward referencee of one or more bases, try again later
|
|
662 _scope = scx ? scx : sc->copy();
|
|
663 _scope->setNoFree();
|
|
664 if (tc->sym->_scope)
|
|
665 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
|
|
666 _scope->_module->addDeferredSemantic(this);
|
|
667 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
|
|
668 return;
|
|
669 }
|
|
670 }
|
|
671
|
|
672 if (baseok == BASEOKdone)
|
|
673 {
|
|
674 baseok = BASEOKsemanticdone;
|
|
675
|
|
676 // initialize vtbl
|
|
677 if (baseClass)
|
|
678 {
|
|
679 if (cpp && baseClass->vtbl.dim == 0)
|
|
680 {
|
|
681 error("C++ base class %s needs at least one virtual function", baseClass->toChars());
|
|
682 }
|
|
683
|
|
684 // Copy vtbl[] from base class
|
|
685 vtbl.setDim(baseClass->vtbl.dim);
|
|
686 memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
|
|
687
|
|
688 vthis = baseClass->vthis;
|
|
689 }
|
|
690 else
|
|
691 {
|
|
692 // No base class, so this is the root of the class hierarchy
|
|
693 vtbl.setDim(0);
|
|
694 if (vtblOffset())
|
|
695 vtbl.push(this); // leave room for classinfo as first member
|
|
696 }
|
|
697
|
|
698 /* If this is a nested class, add the hidden 'this'
|
|
699 * member which is a pointer to the enclosing scope.
|
|
700 */
|
|
701 if (vthis) // if inheriting from nested class
|
|
702 {
|
|
703 // Use the base class's 'this' member
|
|
704 if (storage_class & STCstatic)
|
|
705 error("static class cannot inherit from nested class %s", baseClass->toChars());
|
|
706 if (toParent2() != baseClass->toParent2() &&
|
|
707 (!toParent2() ||
|
|
708 !baseClass->toParent2()->getType() ||
|
|
709 !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
|
|
710 {
|
|
711 if (toParent2())
|
|
712 {
|
|
713 error("is nested within %s, but super class %s is nested within %s",
|
|
714 toParent2()->toChars(),
|
|
715 baseClass->toChars(),
|
|
716 baseClass->toParent2()->toChars());
|
|
717 }
|
|
718 else
|
|
719 {
|
|
720 error("is not nested, but super class %s is nested within %s",
|
|
721 baseClass->toChars(),
|
|
722 baseClass->toParent2()->toChars());
|
|
723 }
|
|
724 enclosing = NULL;
|
|
725 }
|
|
726 }
|
|
727 else
|
|
728 makeNested();
|
|
729 }
|
|
730
|
|
731 Scope *sc2 = newScope(sc);
|
|
732
|
|
733 for (size_t i = 0; i < members->dim; i++)
|
|
734 {
|
|
735 Dsymbol *s = (*members)[i];
|
|
736 s->importAll(sc2);
|
|
737 }
|
|
738
|
|
739 // Note that members.dim can grow due to tuple expansion during semantic()
|
|
740 for (size_t i = 0; i < members->dim; i++)
|
|
741 {
|
|
742 Dsymbol *s = (*members)[i];
|
|
743 s->semantic(sc2);
|
|
744 }
|
|
745
|
|
746 if (!determineFields())
|
|
747 {
|
|
748 assert(type == Type::terror);
|
|
749 sc2->pop();
|
|
750 return;
|
|
751 }
|
|
752
|
|
753 /* Following special member functions creation needs semantic analysis
|
|
754 * completion of sub-structs in each field types.
|
|
755 */
|
|
756 for (size_t i = 0; i < fields.dim; i++)
|
|
757 {
|
|
758 VarDeclaration *v = fields[i];
|
|
759 Type *tb = v->type->baseElemOf();
|
|
760 if (tb->ty != Tstruct)
|
|
761 continue;
|
|
762 StructDeclaration *sd = ((TypeStruct *)tb)->sym;
|
|
763 if (sd->semanticRun >= PASSsemanticdone)
|
|
764 continue;
|
|
765
|
|
766 sc2->pop();
|
|
767
|
|
768 _scope = scx ? scx : sc->copy();
|
|
769 _scope->setNoFree();
|
|
770 _scope->_module->addDeferredSemantic(this);
|
|
771 //printf("\tdeferring %s\n", toChars());
|
|
772 return;
|
|
773 }
|
|
774
|
|
775 /* Look for special member functions.
|
|
776 * They must be in this class, not in a base class.
|
|
777 */
|
|
778
|
|
779 // Can be in base class
|
|
780 aggNew = (NewDeclaration *)search(Loc(), Id::classNew);
|
|
781 aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);
|
|
782
|
|
783 // Look for the constructor
|
|
784 ctor = searchCtor();
|
|
785
|
|
786 if (!ctor && noDefaultCtor)
|
|
787 {
|
|
788 // A class object is always created by constructor, so this check is legitimate.
|
|
789 for (size_t i = 0; i < fields.dim; i++)
|
|
790 {
|
|
791 VarDeclaration *v = fields[i];
|
|
792 if (v->storage_class & STCnodefaultctor)
|
|
793 ::error(v->loc, "field %s must be initialized in constructor", v->toChars());
|
|
794 }
|
|
795 }
|
|
796
|
|
797 // If this class has no constructor, but base class has a default
|
|
798 // ctor, create a constructor:
|
|
799 // this() { }
|
|
800 if (!ctor && baseClass && baseClass->ctor)
|
|
801 {
|
|
802 FuncDeclaration *fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type, NULL, 1);
|
|
803 if (!fd) // try shared base ctor instead
|
|
804 fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type->sharedOf(), NULL, 1);
|
|
805 if (fd && !fd->errors)
|
|
806 {
|
|
807 //printf("Creating default this(){} for class %s\n", toChars());
|
|
808 TypeFunction *btf = fd->type->toTypeFunction();
|
|
809 TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
|
|
810 tf->mod = btf->mod;
|
|
811 tf->purity = btf->purity;
|
|
812 tf->isnothrow = btf->isnothrow;
|
|
813 tf->isnogc = btf->isnogc;
|
|
814 tf->trust = btf->trust;
|
|
815
|
|
816 CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
|
|
817 ctor->fbody = new CompoundStatement(Loc(), new Statements());
|
|
818
|
|
819 members->push(ctor);
|
|
820 ctor->addMember(sc, this);
|
|
821 ctor->semantic(sc2);
|
|
822
|
|
823 this->ctor = ctor;
|
|
824 defaultCtor = ctor;
|
|
825 }
|
|
826 else
|
|
827 {
|
|
828 error("cannot implicitly generate a default ctor when base class %s is missing a default ctor",
|
|
829 baseClass->toPrettyChars());
|
|
830 }
|
|
831 }
|
|
832
|
|
833 dtor = buildDtor(this, sc2);
|
|
834
|
|
835 if (FuncDeclaration *f = hasIdentityOpAssign(this, sc2))
|
|
836 {
|
|
837 if (!(f->storage_class & STCdisable))
|
|
838 error(f->loc, "identity assignment operator overload is illegal");
|
|
839 }
|
|
840
|
|
841 inv = buildInv(this, sc2);
|
|
842
|
|
843 Module::dprogress++;
|
|
844 semanticRun = PASSsemanticdone;
|
|
845 //printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
|
|
846 //members.print();
|
|
847
|
|
848 sc2->pop();
|
|
849
|
|
850 if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
|
|
851 {
|
|
852 // https://issues.dlang.org/show_bug.cgi?id=17492
|
|
853 ClassDeclaration *cd = ((TypeClass *)type)->sym;
|
|
854 error("already exists at %s. Perhaps in another function with the same name?", cd->loc.toChars());
|
|
855 }
|
|
856
|
|
857 if (global.errors != errors)
|
|
858 {
|
|
859 // The type is no good.
|
|
860 type = Type::terror;
|
|
861 this->errors = true;
|
|
862 if (deferred)
|
|
863 deferred->errors = true;
|
|
864 }
|
|
865
|
|
866 // Verify fields of a synchronized class are not public
|
|
867 if (storage_class & STCsynchronized)
|
|
868 {
|
|
869 for (size_t i = 0; i < fields.dim; i++)
|
|
870 {
|
|
871 VarDeclaration *vd = fields[i];
|
|
872 if (!vd->isThisDeclaration() &&
|
|
873 !vd->prot().isMoreRestrictiveThan(Prot(PROTpublic)))
|
|
874 {
|
|
875 vd->error("Field members of a synchronized class cannot be %s",
|
|
876 protectionToChars(vd->prot().kind));
|
|
877 }
|
|
878 }
|
|
879 }
|
|
880
|
|
881 if (deferred && !global.gag)
|
|
882 {
|
|
883 deferred->semantic2(sc);
|
|
884 deferred->semantic3(sc);
|
|
885 }
|
|
886 //printf("-ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
|
|
887 }
|
|
888
|
|
889 /*********************************************
|
|
890 * Determine if 'this' is a base class of cd.
|
|
891 * This is used to detect circular inheritance only.
|
|
892 */
|
|
893
|
|
894 bool ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
|
|
895 {
|
|
896 if (!cd)
|
|
897 return false;
|
|
898 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
|
|
899 for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
|
900 {
|
|
901 BaseClass *b = (*cd->baseclasses)[i];
|
|
902 if (b->sym == this || isBaseOf2(b->sym))
|
|
903 return true;
|
|
904 }
|
|
905 return false;
|
|
906 }
|
|
907
|
|
908 /*******************************************
|
|
909 * Determine if 'this' is a base class of cd.
|
|
910 */
|
|
911
|
|
912 bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
|
|
913 {
|
|
914 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
|
|
915 if (poffset)
|
|
916 *poffset = 0;
|
|
917 while (cd)
|
|
918 {
|
|
919 /* cd->baseClass might not be set if cd is forward referenced.
|
|
920 */
|
|
921 if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
|
|
922 {
|
|
923 cd->semantic(NULL);
|
|
924 if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
|
|
925 cd->error("base class is forward referenced by %s", toChars());
|
|
926 }
|
|
927
|
|
928 if (this == cd->baseClass)
|
|
929 return true;
|
|
930
|
|
931 cd = cd->baseClass;
|
|
932 }
|
|
933 return false;
|
|
934 }
|
|
935
|
|
936 /*********************************************
|
|
937 * Determine if 'this' has complete base class information.
|
|
938 * This is used to detect forward references in covariant overloads.
|
|
939 */
|
|
940
|
|
941 bool ClassDeclaration::isBaseInfoComplete()
|
|
942 {
|
|
943 return baseok >= BASEOKdone;
|
|
944 }
|
|
945
|
|
946 Dsymbol *ClassDeclaration::search(const Loc &loc, Identifier *ident, int flags)
|
|
947 {
|
|
948 //printf("%s.ClassDeclaration::search('%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
|
|
949
|
|
950 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
|
|
951 if (_scope && baseok < BASEOKdone)
|
|
952 {
|
|
953 if (!inuse)
|
|
954 {
|
|
955 // must semantic on base class/interfaces
|
|
956 ++inuse;
|
|
957 semantic(NULL);
|
|
958 --inuse;
|
|
959 }
|
|
960 }
|
|
961
|
|
962 if (!members || !symtab) // opaque or addMember is not yet done
|
|
963 {
|
|
964 error("is forward referenced when looking for '%s'", ident->toChars());
|
|
965 //*(char*)0=0;
|
|
966 return NULL;
|
|
967 }
|
|
968
|
|
969 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
|
|
970
|
|
971 // don't search imports of base classes
|
|
972 if (flags & SearchImportsOnly)
|
|
973 return s;
|
|
974
|
|
975 if (!s)
|
|
976 {
|
|
977 // Search bases classes in depth-first, left to right order
|
|
978
|
|
979 for (size_t i = 0; i < baseclasses->dim; i++)
|
|
980 {
|
|
981 BaseClass *b = (*baseclasses)[i];
|
|
982
|
|
983 if (b->sym)
|
|
984 {
|
|
985 if (!b->sym->symtab)
|
|
986 error("base %s is forward referenced", b->sym->ident->toChars());
|
|
987 else
|
|
988 {
|
|
989 s = b->sym->search(loc, ident, flags);
|
|
990 if (!s)
|
|
991 continue;
|
|
992 else if (s == this) // happens if s is nested in this and derives from this
|
|
993 s = NULL;
|
|
994 else if (!(flags & IgnoreSymbolVisibility) && !(s->prot().kind == PROTprotected) && !symbolIsVisible(this, s))
|
|
995 s = NULL;
|
|
996 else
|
|
997 break;
|
|
998 }
|
|
999 }
|
|
1000 }
|
|
1001 }
|
|
1002 return s;
|
|
1003 }
|
|
1004
|
|
1005 /************************************
|
|
1006 * Search base classes in depth-first, left-to-right order for
|
|
1007 * a class or interface named 'ident'.
|
|
1008 * Stops at first found. Does not look for additional matches.
|
|
1009 * Params:
|
|
1010 * ident = identifier to search for
|
|
1011 * Returns:
|
|
1012 * ClassDeclaration if found, null if not
|
|
1013 */
|
|
1014 ClassDeclaration *ClassDeclaration::searchBase(Identifier *ident)
|
|
1015 {
|
|
1016 for (size_t i = 0; i < baseclasses->dim; i++)
|
|
1017 {
|
|
1018 BaseClass *b = (*baseclasses)[i];
|
|
1019 ClassDeclaration *cdb = b->type->isClassHandle();
|
|
1020 if (!cdb) // Bugzilla 10616
|
|
1021 return NULL;
|
|
1022 if (cdb->ident->equals(ident))
|
|
1023 return cdb;
|
|
1024 cdb = cdb->searchBase(ident);
|
|
1025 if (cdb)
|
|
1026 return cdb;
|
|
1027 }
|
|
1028 return NULL;
|
|
1029 }
|
|
1030
|
|
1031 /****
|
|
1032 * Runs through the inheritance graph to set the BaseClass.offset fields.
|
|
1033 * Recursive in order to account for the size of the interface classes, if they are
|
|
1034 * more than just interfaces.
|
|
1035 * Params:
|
|
1036 * cd = interface to look at
|
|
1037 * baseOffset = offset of where cd will be placed
|
|
1038 * Returns:
|
|
1039 * subset of instantiated size used by cd for interfaces
|
|
1040 */
|
|
1041 static unsigned membersPlace(BaseClasses *vtblInterfaces, size_t &bi, ClassDeclaration *cd, unsigned baseOffset)
|
|
1042 {
|
|
1043 //printf(" membersPlace(%s, %d)\n", cd->toChars(), baseOffset);
|
|
1044 unsigned offset = baseOffset;
|
|
1045
|
|
1046 for (size_t i = 0; i < cd->interfaces.length; i++)
|
|
1047 {
|
|
1048 BaseClass *b = cd->interfaces.ptr[i];
|
|
1049 if (b->sym->sizeok != SIZEOKdone)
|
|
1050 b->sym->finalizeSize();
|
|
1051 assert(b->sym->sizeok == SIZEOKdone);
|
|
1052
|
|
1053 if (!b->sym->alignsize)
|
|
1054 b->sym->alignsize = Target::ptrsize;
|
|
1055 cd->alignmember(b->sym->alignsize, b->sym->alignsize, &offset);
|
|
1056 assert(bi < vtblInterfaces->dim);
|
|
1057 BaseClass *bv = (*vtblInterfaces)[bi];
|
|
1058 if (b->sym->interfaces.length == 0)
|
|
1059 {
|
|
1060 //printf("\tvtblInterfaces[%d] b=%p b->sym = %s, offset = %d\n", bi, bv, bv->sym->toChars(), offset);
|
|
1061 bv->offset = offset;
|
|
1062 ++bi;
|
|
1063 // All the base interfaces down the left side share the same offset
|
|
1064 for (BaseClass *b2 = bv; b2->baseInterfaces.length; )
|
|
1065 {
|
|
1066 b2 = &b2->baseInterfaces.ptr[0];
|
|
1067 b2->offset = offset;
|
|
1068 //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2->sym->toChars(), b2->offset);
|
|
1069 }
|
|
1070 }
|
|
1071 membersPlace(vtblInterfaces, bi, b->sym, offset);
|
|
1072 //printf(" %s size = %d\n", b->sym->toChars(), b->sym->structsize);
|
|
1073 offset += b->sym->structsize;
|
|
1074 if (cd->alignsize < b->sym->alignsize)
|
|
1075 cd->alignsize = b->sym->alignsize;
|
|
1076 }
|
|
1077 return offset - baseOffset;
|
|
1078 }
|
|
1079
|
|
1080 void ClassDeclaration::finalizeSize()
|
|
1081 {
|
|
1082 assert(sizeok != SIZEOKdone);
|
|
1083
|
|
1084 // Set the offsets of the fields and determine the size of the class
|
|
1085 if (baseClass)
|
|
1086 {
|
|
1087 assert(baseClass->sizeok == SIZEOKdone);
|
|
1088
|
|
1089 alignsize = baseClass->alignsize;
|
|
1090 structsize = baseClass->structsize;
|
|
1091 if (cpp && global.params.isWindows)
|
|
1092 structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
|
1093 }
|
|
1094 else if (isInterfaceDeclaration())
|
|
1095 {
|
|
1096 if (interfaces.length == 0)
|
|
1097 {
|
|
1098 alignsize = Target::ptrsize;
|
|
1099 structsize = Target::ptrsize; // allow room for __vptr
|
|
1100 }
|
|
1101 }
|
|
1102 else
|
|
1103 {
|
|
1104 alignsize = Target::ptrsize;
|
|
1105 structsize = Target::ptrsize; // allow room for __vptr
|
|
1106 if (!cpp)
|
|
1107 structsize += Target::ptrsize; // allow room for __monitor
|
|
1108 }
|
|
1109
|
|
1110 //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
|
|
1111 size_t bi = 0; // index into vtblInterfaces[]
|
|
1112
|
|
1113 // Add vptr's for any interfaces implemented by this class
|
|
1114 structsize += membersPlace(vtblInterfaces, bi, this, structsize);
|
|
1115
|
|
1116 if (isInterfaceDeclaration())
|
|
1117 {
|
|
1118 sizeok = SIZEOKdone;
|
|
1119 return;
|
|
1120 }
|
|
1121
|
|
1122 // FIXME: Currently setFieldOffset functions need to increase fields
|
|
1123 // to calculate each variable offsets. It can be improved later.
|
|
1124 fields.setDim(0);
|
|
1125
|
|
1126 unsigned offset = structsize;
|
|
1127 for (size_t i = 0; i < members->dim; i++)
|
|
1128 {
|
|
1129 Dsymbol *s = (*members)[i];
|
|
1130 s->setFieldOffset(this, &offset, false);
|
|
1131 }
|
|
1132
|
|
1133 sizeok = SIZEOKdone;
|
|
1134
|
|
1135 // Calculate fields[i]->overlapped
|
|
1136 checkOverlappedFields();
|
|
1137 }
|
|
1138
|
|
1139 /**********************************************************
|
|
1140 * fd is in the vtbl[] for this class.
|
|
1141 * Return 1 if function is hidden (not findable through search).
|
|
1142 */
|
|
1143
|
|
1144 int isf(void *param, Dsymbol *s)
|
|
1145 {
|
|
1146 FuncDeclaration *fd = s->isFuncDeclaration();
|
|
1147 if (!fd)
|
|
1148 return 0;
|
|
1149 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
|
|
1150 return (RootObject *)param == fd;
|
|
1151 }
|
|
1152
|
|
1153 bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
|
1154 {
|
|
1155 //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars());
|
|
1156 Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors);
|
|
1157 if (!s)
|
|
1158 {
|
|
1159 //printf("not found\n");
|
|
1160 /* Because, due to a hack, if there are multiple definitions
|
|
1161 * of fd->ident, NULL is returned.
|
|
1162 */
|
|
1163 return false;
|
|
1164 }
|
|
1165 s = s->toAlias();
|
|
1166 OverloadSet *os = s->isOverloadSet();
|
|
1167 if (os)
|
|
1168 {
|
|
1169 for (size_t i = 0; i < os->a.dim; i++)
|
|
1170 {
|
|
1171 Dsymbol *s2 = os->a[i];
|
|
1172 FuncDeclaration *f2 = s2->isFuncDeclaration();
|
|
1173 if (f2 && overloadApply(f2, (void *)fd, &isf))
|
|
1174 return false;
|
|
1175 }
|
|
1176 return true;
|
|
1177 }
|
|
1178 else
|
|
1179 {
|
|
1180 FuncDeclaration *fdstart = s->isFuncDeclaration();
|
|
1181 //printf("%s fdstart = %p\n", s->kind(), fdstart);
|
|
1182 if (overloadApply(fdstart, (void *)fd, &isf))
|
|
1183 return false;
|
|
1184
|
|
1185 return !fd->parent->isTemplateMixin();
|
|
1186 }
|
|
1187 }
|
|
1188
|
|
1189 /****************
|
|
1190 * Find virtual function matching identifier and type.
|
|
1191 * Used to build virtual function tables for interface implementations.
|
|
1192 */
|
|
1193
|
|
1194 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
|
|
1195 {
|
|
1196 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
|
|
1197 FuncDeclaration *fdmatch = NULL;
|
|
1198 FuncDeclaration *fdambig = NULL;
|
|
1199
|
|
1200 ClassDeclaration *cd = this;
|
|
1201 Dsymbols *vtbl = &cd->vtbl;
|
|
1202 while (1)
|
|
1203 {
|
|
1204 for (size_t i = 0; i < vtbl->dim; i++)
|
|
1205 {
|
|
1206 FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration();
|
|
1207 if (!fd)
|
|
1208 continue; // the first entry might be a ClassInfo
|
|
1209
|
|
1210 //printf("\t[%d] = %s\n", i, fd->toChars());
|
|
1211 if (ident == fd->ident &&
|
|
1212 fd->type->covariant(tf) == 1)
|
|
1213 {
|
|
1214 //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration());
|
|
1215 if (!fdmatch)
|
|
1216 goto Lfd;
|
|
1217 if (fd == fdmatch)
|
|
1218 goto Lfdmatch;
|
|
1219
|
|
1220 {
|
|
1221 // Function type matcing: exact > covariant
|
|
1222 MATCH m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch;
|
|
1223 MATCH m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch;
|
|
1224 if (m1 > m2)
|
|
1225 goto Lfd;
|
|
1226 else if (m1 < m2)
|
|
1227 goto Lfdmatch;
|
|
1228 }
|
|
1229
|
|
1230 {
|
|
1231 MATCH m1 = (tf->mod == fd ->type->mod) ? MATCHexact : MATCHnomatch;
|
|
1232 MATCH m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch;
|
|
1233 if (m1 > m2)
|
|
1234 goto Lfd;
|
|
1235 else if (m1 < m2)
|
|
1236 goto Lfdmatch;
|
|
1237 }
|
|
1238
|
|
1239 {
|
|
1240 // The way of definition: non-mixin > mixin
|
|
1241 MATCH m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
|
|
1242 MATCH m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
|
|
1243 if (m1 > m2)
|
|
1244 goto Lfd;
|
|
1245 else if (m1 < m2)
|
|
1246 goto Lfdmatch;
|
|
1247 }
|
|
1248
|
|
1249 fdambig = fd;
|
|
1250 //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars());
|
|
1251 continue;
|
|
1252
|
|
1253 Lfd:
|
|
1254 fdmatch = fd;
|
|
1255 fdambig = NULL;
|
|
1256 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars());
|
|
1257 continue;
|
|
1258
|
|
1259 Lfdmatch:
|
|
1260 continue;
|
|
1261 }
|
|
1262 //else printf("\t\t%d\n", fd->type->covariant(tf));
|
|
1263 }
|
|
1264 if (!cd)
|
|
1265 break;
|
|
1266 vtbl = &cd->vtblFinal;
|
|
1267 cd = cd->baseClass;
|
|
1268 }
|
|
1269
|
|
1270 if (fdambig)
|
|
1271 error("ambiguous virtual function %s", fdambig->toChars());
|
|
1272 return fdmatch;
|
|
1273 }
|
|
1274
|
|
1275 void ClassDeclaration::interfaceSemantic(Scope *)
|
|
1276 {
|
|
1277 vtblInterfaces = new BaseClasses();
|
|
1278 vtblInterfaces->reserve(interfaces.length);
|
|
1279
|
|
1280 for (size_t i = 0; i < interfaces.length; i++)
|
|
1281 {
|
|
1282 BaseClass *b = interfaces.ptr[i];
|
|
1283 vtblInterfaces->push(b);
|
|
1284 b->copyBaseInterfaces(vtblInterfaces);
|
|
1285 }
|
|
1286 }
|
|
1287
|
|
1288 /****************************************
|
|
1289 */
|
|
1290
|
|
1291 bool ClassDeclaration::isCOMclass() const
|
|
1292 {
|
|
1293 return com;
|
|
1294 }
|
|
1295
|
|
1296 bool ClassDeclaration::isCOMinterface() const
|
|
1297 {
|
|
1298 return false;
|
|
1299 }
|
|
1300
|
|
1301 bool ClassDeclaration::isCPPclass() const
|
|
1302 {
|
|
1303 return cpp;
|
|
1304 }
|
|
1305
|
|
1306 bool ClassDeclaration::isCPPinterface() const
|
|
1307 {
|
|
1308 return false;
|
|
1309 }
|
|
1310
|
|
1311
|
|
1312 /****************************************
|
|
1313 */
|
|
1314
|
|
1315 bool ClassDeclaration::isAbstract()
|
|
1316 {
|
|
1317 if (isabstract != ABSfwdref)
|
|
1318 return isabstract == ABSyes;
|
|
1319
|
|
1320 /* Bugzilla 11169: Resolve forward references to all class member functions,
|
|
1321 * and determine whether this class is abstract.
|
|
1322 */
|
|
1323 struct SearchAbstract
|
|
1324 {
|
|
1325 static int fp(Dsymbol *s, void *)
|
|
1326 {
|
|
1327 FuncDeclaration *fd = s->isFuncDeclaration();
|
|
1328 if (!fd)
|
|
1329 return 0;
|
|
1330 if (fd->storage_class & STCstatic)
|
|
1331 return 0;
|
|
1332
|
|
1333 if (fd->_scope)
|
|
1334 fd->semantic(NULL);
|
|
1335
|
|
1336 if (fd->isAbstract())
|
|
1337 return 1;
|
|
1338 return 0;
|
|
1339 }
|
|
1340 };
|
|
1341
|
|
1342 for (size_t i = 0; i < members->dim; i++)
|
|
1343 {
|
|
1344 Dsymbol *s = (*members)[i];
|
|
1345 if (s->apply(&SearchAbstract::fp, this))
|
|
1346 {
|
|
1347 isabstract = ABSyes;
|
|
1348 return true;
|
|
1349 }
|
|
1350 }
|
|
1351
|
|
1352 /* Iterate inherited member functions and check their abstract attribute.
|
|
1353 */
|
|
1354 for (size_t i = 1; i < vtbl.dim; i++)
|
|
1355 {
|
|
1356 FuncDeclaration *fd = vtbl[i]->isFuncDeclaration();
|
|
1357 //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd->loc.toChars(), fd->toChars());
|
|
1358 if (!fd || fd->isAbstract())
|
|
1359 {
|
|
1360 isabstract = ABSyes;
|
|
1361 return true;
|
|
1362 }
|
|
1363 }
|
|
1364
|
|
1365 isabstract = ABSno;
|
|
1366 return false;
|
|
1367 }
|
|
1368
|
|
1369
|
|
1370 /****************************************
|
|
1371 * Determine if slot 0 of the vtbl[] is reserved for something else.
|
|
1372 * For class objects, yes, this is where the classinfo ptr goes.
|
|
1373 * For COM interfaces, no.
|
|
1374 * For non-COM interfaces, yes, this is where the Interface ptr goes.
|
|
1375 * Returns:
|
|
1376 * 0 vtbl[0] is first virtual function pointer
|
|
1377 * 1 vtbl[0] is classinfo/interfaceinfo pointer
|
|
1378 */
|
|
1379
|
|
1380 int ClassDeclaration::vtblOffset() const
|
|
1381 {
|
|
1382 return cpp ? 0 : 1;
|
|
1383 }
|
|
1384
|
|
1385 /****************************************
|
|
1386 */
|
|
1387
|
|
1388 const char *ClassDeclaration::kind() const
|
|
1389 {
|
|
1390 return "class";
|
|
1391 }
|
|
1392
|
|
1393 /****************************************
|
|
1394 */
|
|
1395
|
|
1396 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
|
|
1397 {
|
|
1398 aclasses->push(this);
|
|
1399 }
|
|
1400
|
|
1401 /********************************* InterfaceDeclaration ****************************/
|
|
1402
|
|
1403 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
|
|
1404 : ClassDeclaration(loc, id, baseclasses, NULL, false)
|
|
1405 {
|
|
1406 if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
|
|
1407 {
|
|
1408 com = true;
|
|
1409 cpp = true; // IUnknown is also a C++ interface
|
|
1410 }
|
|
1411 }
|
|
1412
|
|
1413 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
|
|
1414 {
|
|
1415 InterfaceDeclaration *id =
|
|
1416 s ? (InterfaceDeclaration *)s
|
|
1417 : new InterfaceDeclaration(loc, ident, NULL);
|
|
1418 return ClassDeclaration::syntaxCopy(id);
|
|
1419 }
|
|
1420
|
|
1421 Scope *InterfaceDeclaration::newScope(Scope *sc)
|
|
1422 {
|
|
1423 Scope *sc2 = ClassDeclaration::newScope(sc);
|
|
1424 if (com)
|
|
1425 sc2->linkage = LINKwindows;
|
|
1426 else if (cpp)
|
|
1427 sc2->linkage = LINKcpp;
|
|
1428 else if (isobjc)
|
|
1429 sc2->linkage = LINKobjc;
|
|
1430 return sc2;
|
|
1431 }
|
|
1432
|
|
1433 void InterfaceDeclaration::semantic(Scope *sc)
|
|
1434 {
|
|
1435 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
|
|
1436 if (semanticRun >= PASSsemanticdone)
|
|
1437 return;
|
|
1438 unsigned errors = global.errors;
|
|
1439
|
|
1440 //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
|
|
1441
|
|
1442 Scope *scx = NULL;
|
|
1443 if (_scope)
|
|
1444 {
|
|
1445 sc = _scope;
|
|
1446 scx = _scope; // save so we don't make redundant copies
|
|
1447 _scope = NULL;
|
|
1448 }
|
|
1449
|
|
1450 if (!parent)
|
|
1451 {
|
|
1452 assert(sc->parent && sc->func);
|
|
1453 parent = sc->parent;
|
|
1454 }
|
|
1455 assert(parent && !isAnonymous());
|
|
1456
|
|
1457 if (this->errors)
|
|
1458 type = Type::terror;
|
|
1459 type = type->semantic(loc, sc);
|
|
1460
|
|
1461 if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
|
|
1462 {
|
|
1463 TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
|
|
1464 if (ti && isError(ti))
|
|
1465 ((TypeClass *)type)->sym = this;
|
|
1466 }
|
|
1467
|
|
1468 // Ungag errors when not speculative
|
|
1469 Ungag ungag = ungagSpeculative();
|
|
1470
|
|
1471 if (semanticRun == PASSinit)
|
|
1472 {
|
|
1473 protection = sc->protection;
|
|
1474
|
|
1475 storage_class |= sc->stc;
|
|
1476 if (storage_class & STCdeprecated)
|
|
1477 isdeprecated = true;
|
|
1478
|
|
1479 userAttribDecl = sc->userAttribDecl;
|
|
1480 }
|
|
1481 else if (symtab)
|
|
1482 {
|
|
1483 if (sizeok == SIZEOKdone || !scx)
|
|
1484 {
|
|
1485 semanticRun = PASSsemanticdone;
|
|
1486 return;
|
|
1487 }
|
|
1488 }
|
|
1489 semanticRun = PASSsemantic;
|
|
1490
|
|
1491 if (baseok < BASEOKdone)
|
|
1492 {
|
|
1493 baseok = BASEOKin;
|
|
1494
|
|
1495 // Expand any tuples in baseclasses[]
|
|
1496 for (size_t i = 0; i < baseclasses->dim; )
|
|
1497 {
|
|
1498 BaseClass *b = (*baseclasses)[i];
|
|
1499 b->type = resolveBase(this, sc, scx, b->type);
|
|
1500
|
|
1501 Type *tb = b->type->toBasetype();
|
|
1502 if (tb->ty == Ttuple)
|
|
1503 {
|
|
1504 TypeTuple *tup = (TypeTuple *)tb;
|
|
1505 baseclasses->remove(i);
|
|
1506 size_t dim = Parameter::dim(tup->arguments);
|
|
1507 for (size_t j = 0; j < dim; j++)
|
|
1508 {
|
|
1509 Parameter *arg = Parameter::getNth(tup->arguments, j);
|
|
1510 b = new BaseClass(arg->type);
|
|
1511 baseclasses->insert(i + j, b);
|
|
1512 }
|
|
1513 }
|
|
1514 else
|
|
1515 i++;
|
|
1516 }
|
|
1517
|
|
1518 if (baseok >= BASEOKdone)
|
|
1519 {
|
|
1520 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
|
|
1521 if (semanticRun >= PASSsemanticdone)
|
|
1522 return;
|
|
1523 goto Lancestorsdone;
|
|
1524 }
|
|
1525
|
|
1526 if (!baseclasses->dim && sc->linkage == LINKcpp)
|
|
1527 cpp = true;
|
|
1528 if (sc->linkage == LINKobjc)
|
|
1529 objc()->setObjc(this);
|
|
1530
|
|
1531 // Check for errors, handle forward references
|
|
1532 for (size_t i = 0; i < baseclasses->dim; )
|
|
1533 {
|
|
1534 BaseClass *b = (*baseclasses)[i];
|
|
1535 Type *tb = b->type->toBasetype();
|
|
1536 TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
|
|
1537 if (!tc || !tc->sym->isInterfaceDeclaration())
|
|
1538 {
|
|
1539 if (b->type != Type::terror)
|
|
1540 error("base type must be interface, not %s", b->type->toChars());
|
|
1541 baseclasses->remove(i);
|
|
1542 continue;
|
|
1543 }
|
|
1544
|
|
1545 // Check for duplicate interfaces
|
|
1546 for (size_t j = 0; j < i; j++)
|
|
1547 {
|
|
1548 BaseClass *b2 = (*baseclasses)[j];
|
|
1549 if (b2->sym == tc->sym)
|
|
1550 {
|
|
1551 error("inherits from duplicate interface %s", b2->sym->toChars());
|
|
1552 baseclasses->remove(i);
|
|
1553 continue;
|
|
1554 }
|
|
1555 }
|
|
1556
|
|
1557 if (tc->sym == this || isBaseOf2(tc->sym))
|
|
1558 {
|
|
1559 error("circular inheritance of interface");
|
|
1560 baseclasses->remove(i);
|
|
1561 continue;
|
|
1562 }
|
|
1563
|
|
1564 if (tc->sym->isDeprecated())
|
|
1565 {
|
|
1566 if (!isDeprecated())
|
|
1567 {
|
|
1568 // Deriving from deprecated class makes this one deprecated too
|
|
1569 isdeprecated = true;
|
|
1570
|
|
1571 tc->checkDeprecated(loc, sc);
|
|
1572 }
|
|
1573 }
|
|
1574
|
|
1575 b->sym = tc->sym;
|
|
1576
|
|
1577 if (tc->sym->baseok < BASEOKdone)
|
|
1578 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
|
|
1579 if (tc->sym->baseok < BASEOKdone)
|
|
1580 {
|
|
1581 //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
|
|
1582 if (tc->sym->_scope)
|
|
1583 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
|
|
1584 baseok = BASEOKnone;
|
|
1585 }
|
|
1586 i++;
|
|
1587 }
|
|
1588 if (baseok == BASEOKnone)
|
|
1589 {
|
|
1590 // Forward referencee of one or more bases, try again later
|
|
1591 _scope = scx ? scx : sc->copy();
|
|
1592 _scope->setNoFree();
|
|
1593 _scope->_module->addDeferredSemantic(this);
|
|
1594 return;
|
|
1595 }
|
|
1596 baseok = BASEOKdone;
|
|
1597
|
|
1598 interfaces.length = baseclasses->dim;
|
|
1599 interfaces.ptr = baseclasses->tdata();
|
|
1600
|
|
1601 for (size_t i = 0; i < interfaces.length; i++)
|
|
1602 {
|
|
1603 BaseClass *b = interfaces.ptr[i];
|
|
1604 // If this is an interface, and it derives from a COM interface,
|
|
1605 // then this is a COM interface too.
|
|
1606 if (b->sym->isCOMinterface())
|
|
1607 com = true;
|
|
1608 if (b->sym->isCPPinterface())
|
|
1609 cpp = true;
|
|
1610 }
|
|
1611
|
|
1612 interfaceSemantic(sc);
|
|
1613 }
|
|
1614 Lancestorsdone:
|
|
1615
|
|
1616 if (!members) // if opaque declaration
|
|
1617 {
|
|
1618 semanticRun = PASSsemanticdone;
|
|
1619 return;
|
|
1620 }
|
|
1621 if (!symtab)
|
|
1622 symtab = new DsymbolTable();
|
|
1623
|
|
1624 for (size_t i = 0; i < baseclasses->dim; i++)
|
|
1625 {
|
|
1626 BaseClass *b = (*baseclasses)[i];
|
|
1627 Type *tb = b->type->toBasetype();
|
|
1628 assert(tb->ty == Tclass);
|
|
1629 TypeClass *tc = (TypeClass *)tb;
|
|
1630
|
|
1631 if (tc->sym->semanticRun < PASSsemanticdone)
|
|
1632 {
|
|
1633 // Forward referencee of one or more bases, try again later
|
|
1634 _scope = scx ? scx : sc->copy();
|
|
1635 _scope->setNoFree();
|
|
1636 if (tc->sym->_scope)
|
|
1637 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
|
|
1638 _scope->_module->addDeferredSemantic(this);
|
|
1639 return;
|
|
1640 }
|
|
1641 }
|
|
1642
|
|
1643 if (baseok == BASEOKdone)
|
|
1644 {
|
|
1645 baseok = BASEOKsemanticdone;
|
|
1646
|
|
1647 // initialize vtbl
|
|
1648 if (vtblOffset())
|
|
1649 vtbl.push(this); // leave room at vtbl[0] for classinfo
|
|
1650
|
|
1651 // Cat together the vtbl[]'s from base interfaces
|
|
1652 for (size_t i = 0; i < interfaces.length; i++)
|
|
1653 {
|
|
1654 BaseClass *b = interfaces.ptr[i];
|
|
1655
|
|
1656 // Skip if b has already appeared
|
|
1657 for (size_t k = 0; k < i; k++)
|
|
1658 {
|
|
1659 if (b == interfaces.ptr[k])
|
|
1660 goto Lcontinue;
|
|
1661 }
|
|
1662
|
|
1663 // Copy vtbl[] from base class
|
|
1664 if (b->sym->vtblOffset())
|
|
1665 {
|
|
1666 size_t d = b->sym->vtbl.dim;
|
|
1667 if (d > 1)
|
|
1668 {
|
|
1669 vtbl.reserve(d - 1);
|
|
1670 for (size_t j = 1; j < d; j++)
|
|
1671 vtbl.push(b->sym->vtbl[j]);
|
|
1672 }
|
|
1673 }
|
|
1674 else
|
|
1675 {
|
|
1676 vtbl.append(&b->sym->vtbl);
|
|
1677 }
|
|
1678
|
|
1679 Lcontinue:
|
|
1680 ;
|
|
1681 }
|
|
1682 }
|
|
1683
|
|
1684 for (size_t i = 0; i < members->dim; i++)
|
|
1685 {
|
|
1686 Dsymbol *s = (*members)[i];
|
|
1687 s->addMember(sc, this);
|
|
1688 }
|
|
1689
|
|
1690 Scope *sc2 = newScope(sc);
|
|
1691
|
|
1692 /* Set scope so if there are forward references, we still might be able to
|
|
1693 * resolve individual members like enums.
|
|
1694 */
|
|
1695 for (size_t i = 0; i < members->dim; i++)
|
|
1696 {
|
|
1697 Dsymbol *s = (*members)[i];
|
|
1698 //printf("setScope %s %s\n", s->kind(), s->toChars());
|
|
1699 s->setScope(sc2);
|
|
1700 }
|
|
1701
|
|
1702 for (size_t i = 0; i < members->dim; i++)
|
|
1703 {
|
|
1704 Dsymbol *s = (*members)[i];
|
|
1705 s->importAll(sc2);
|
|
1706 }
|
|
1707
|
|
1708 for (size_t i = 0; i < members->dim; i++)
|
|
1709 {
|
|
1710 Dsymbol *s = (*members)[i];
|
|
1711 s->semantic(sc2);
|
|
1712 }
|
|
1713
|
|
1714 Module::dprogress++;
|
|
1715 semanticRun = PASSsemanticdone;
|
|
1716 //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
|
|
1717 //members->print();
|
|
1718
|
|
1719 sc2->pop();
|
|
1720
|
|
1721 if (global.errors != errors)
|
|
1722 {
|
|
1723 // The type is no good.
|
|
1724 type = Type::terror;
|
|
1725 }
|
|
1726
|
|
1727 assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
|
|
1728 }
|
|
1729
|
|
1730 /*******************************************
|
|
1731 * Determine if 'this' is a base class of cd.
|
|
1732 * (Actually, if it is an interface supported by cd)
|
|
1733 * Output:
|
|
1734 * *poffset offset to start of class
|
|
1735 * OFFSET_RUNTIME must determine offset at runtime
|
|
1736 * Returns:
|
|
1737 * false not a base
|
|
1738 * true is a base
|
|
1739 */
|
|
1740
|
|
1741 bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
|
|
1742 {
|
|
1743 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
|
|
1744 assert(!baseClass);
|
|
1745 for (size_t j = 0; j < cd->interfaces.length; j++)
|
|
1746 {
|
|
1747 BaseClass *b = cd->interfaces.ptr[j];
|
|
1748
|
|
1749 //printf("\tX base %s\n", b->sym->toChars());
|
|
1750 if (this == b->sym)
|
|
1751 {
|
|
1752 //printf("\tfound at offset %d\n", b->offset);
|
|
1753 if (poffset)
|
|
1754 {
|
|
1755 // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980
|
|
1756 *poffset = cd->sizeok == SIZEOKdone ? b->offset : OFFSET_FWDREF;
|
|
1757 }
|
|
1758 //printf("\tfound at offset %d\n", b->offset);
|
|
1759 return true;
|
|
1760 }
|
|
1761 if (isBaseOf(b, poffset))
|
|
1762 return true;
|
|
1763 }
|
|
1764
|
|
1765 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
|
|
1766 return true;
|
|
1767
|
|
1768 if (poffset)
|
|
1769 *poffset = 0;
|
|
1770 return false;
|
|
1771 }
|
|
1772
|
|
1773 bool InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
|
|
1774 {
|
|
1775 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym->toChars());
|
|
1776 for (size_t j = 0; j < bc->baseInterfaces.length; j++)
|
|
1777 {
|
|
1778 BaseClass *b = &bc->baseInterfaces.ptr[j];
|
|
1779
|
|
1780 //printf("\tY base %s\n", b->sym->toChars());
|
|
1781 if (this == b->sym)
|
|
1782 {
|
|
1783 //printf("\tfound at offset %d\n", b->offset);
|
|
1784 if (poffset)
|
|
1785 {
|
|
1786 *poffset = b->offset;
|
|
1787 }
|
|
1788 return true;
|
|
1789 }
|
|
1790 if (isBaseOf(b, poffset))
|
|
1791 {
|
|
1792 return true;
|
|
1793 }
|
|
1794 }
|
|
1795 if (poffset)
|
|
1796 *poffset = 0;
|
|
1797 return false;
|
|
1798 }
|
|
1799
|
|
1800 /****************************************
|
|
1801 * Determine if slot 0 of the vtbl[] is reserved for something else.
|
|
1802 * For class objects, yes, this is where the ClassInfo ptr goes.
|
|
1803 * For COM interfaces, no.
|
|
1804 * For non-COM interfaces, yes, this is where the Interface ptr goes.
|
|
1805 */
|
|
1806
|
|
1807 int InterfaceDeclaration::vtblOffset() const
|
|
1808 {
|
|
1809 if (isCOMinterface() || isCPPinterface())
|
|
1810 return 0;
|
|
1811 return 1;
|
|
1812 }
|
|
1813
|
|
1814 bool InterfaceDeclaration::isCOMinterface() const
|
|
1815 {
|
|
1816 return com;
|
|
1817 }
|
|
1818
|
|
1819 bool InterfaceDeclaration::isCPPinterface() const
|
|
1820 {
|
|
1821 return cpp;
|
|
1822 }
|
|
1823
|
|
1824 /*******************************************
|
|
1825 */
|
|
1826
|
|
1827 const char *InterfaceDeclaration::kind() const
|
|
1828 {
|
|
1829 return "interface";
|
|
1830 }
|
|
1831
|
|
1832
|
|
1833 /******************************** BaseClass *****************************/
|
|
1834
|
|
1835 BaseClass::BaseClass()
|
|
1836 {
|
|
1837 this->type = NULL;
|
|
1838 this->sym = NULL;
|
|
1839 this->offset = 0;
|
|
1840
|
|
1841 this->baseInterfaces.length = 0;
|
|
1842 this->baseInterfaces.ptr = NULL;
|
|
1843 }
|
|
1844
|
|
1845 BaseClass::BaseClass(Type *type)
|
|
1846 {
|
|
1847 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
|
|
1848 this->type = type;
|
|
1849 this->sym = NULL;
|
|
1850 this->offset = 0;
|
|
1851
|
|
1852 this->baseInterfaces.length = 0;
|
|
1853 this->baseInterfaces.ptr = NULL;
|
|
1854 }
|
|
1855
|
|
1856 /****************************************
|
|
1857 * Fill in vtbl[] for base class based on member functions of class cd.
|
|
1858 * Input:
|
|
1859 * vtbl if !=NULL, fill it in
|
|
1860 * newinstance !=0 means all entries must be filled in by members
|
|
1861 * of cd, not members of any base classes of cd.
|
|
1862 * Returns:
|
|
1863 * true if any entries were filled in by members of cd (not exclusively
|
|
1864 * by base classes)
|
|
1865 */
|
|
1866
|
|
1867 bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance)
|
|
1868 {
|
|
1869 bool result = false;
|
|
1870
|
|
1871 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym->toChars(), cd->toChars());
|
|
1872 if (vtbl)
|
|
1873 vtbl->setDim(sym->vtbl.dim);
|
|
1874
|
|
1875 // first entry is ClassInfo reference
|
|
1876 for (size_t j = sym->vtblOffset(); j < sym->vtbl.dim; j++)
|
|
1877 {
|
|
1878 FuncDeclaration *ifd = sym->vtbl[j]->isFuncDeclaration();
|
|
1879 FuncDeclaration *fd;
|
|
1880 TypeFunction *tf;
|
|
1881
|
|
1882 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
|
|
1883
|
|
1884 assert(ifd);
|
|
1885 // Find corresponding function in this class
|
|
1886 tf = ifd->type->toTypeFunction();
|
|
1887 fd = cd->findFunc(ifd->ident, tf);
|
|
1888 if (fd && !fd->isAbstract())
|
|
1889 {
|
|
1890 //printf(" found\n");
|
|
1891 // Check that calling conventions match
|
|
1892 if (fd->linkage != ifd->linkage)
|
|
1893 fd->error("linkage doesn't match interface function");
|
|
1894
|
|
1895 // Check that it is current
|
|
1896 //printf("newinstance = %d fd->toParent() = %s ifd->toParent() = %s\n",
|
|
1897 //newinstance, fd->toParent()->toChars(), ifd->toParent()->toChars());
|
|
1898 if (newinstance && fd->toParent() != cd && ifd->toParent() == sym)
|
|
1899 cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
|
|
1900
|
|
1901 if (fd->toParent() == cd)
|
|
1902 result = true;
|
|
1903 }
|
|
1904 else
|
|
1905 {
|
|
1906 //printf(" not found %p\n", fd);
|
|
1907 // BUG: should mark this class as abstract?
|
|
1908 if (!cd->isAbstract())
|
|
1909 cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
|
|
1910
|
|
1911 fd = NULL;
|
|
1912 }
|
|
1913 if (vtbl)
|
|
1914 (*vtbl)[j] = fd;
|
|
1915 }
|
|
1916
|
|
1917 return result;
|
|
1918 }
|
|
1919
|
|
1920 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
|
|
1921 {
|
|
1922 //printf("+copyBaseInterfaces(), %s\n", sym->toChars());
|
|
1923 // if (baseInterfaces.length)
|
|
1924 // return;
|
|
1925
|
|
1926 baseInterfaces.length = sym->interfaces.length;
|
|
1927 baseInterfaces.ptr = (BaseClass *)mem.xcalloc(baseInterfaces.length, sizeof(BaseClass));
|
|
1928
|
|
1929 //printf("%s.copyBaseInterfaces()\n", sym->toChars());
|
|
1930 for (size_t i = 0; i < baseInterfaces.length; i++)
|
|
1931 {
|
|
1932 void *pb = &baseInterfaces.ptr[i];
|
|
1933 BaseClass *b2 = sym->interfaces.ptr[i];
|
|
1934
|
|
1935 assert(b2->vtbl.dim == 0); // should not be filled yet
|
|
1936 BaseClass *b = (BaseClass *)memcpy(pb, b2, sizeof(BaseClass));
|
|
1937
|
|
1938 if (i) // single inheritance is i==0
|
|
1939 vtblInterfaces->push(b); // only need for M.I.
|
|
1940 b->copyBaseInterfaces(vtblInterfaces);
|
|
1941 }
|
|
1942 //printf("-copyBaseInterfaces\n");
|
|
1943 }
|