d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
[official-gcc.git] / gcc / d / dmd / objc.d
blob359474c588ada024fe713ba8f104752e345c1045
1 /**
2 * Interfacing with Objective-C.
4 * Specification: $(LINK2 https://dlang.org/spec/objc_interface.html, Interfacing to Objective-C)
6 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/objc.d, _objc.d)
10 * Documentation: https://dlang.org/phobos/dmd_objc.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/objc.d
14 module dmd.objc;
16 import dmd.aggregate;
17 import dmd.arraytypes;
18 import dmd.astenums;
19 import dmd.attrib;
20 import dmd.cond;
21 import dmd.dclass;
22 import dmd.declaration;
23 import dmd.denum;
24 import dmd.dmangle;
25 import dmd.dmodule;
26 import dmd.dscope;
27 import dmd.dstruct;
28 import dmd.dsymbol;
29 import dmd.dsymbolsem;
30 import dmd.errors;
31 import dmd.expression;
32 import dmd.expressionsem;
33 import dmd.func;
34 import dmd.globals;
35 import dmd.gluelayer;
36 import dmd.hdrgen;
37 import dmd.id;
38 import dmd.identifier;
39 import dmd.location;
40 import dmd.mtype;
41 import dmd.root.array;
42 import dmd.common.outbuffer;
43 import dmd.root.stringtable;
44 import dmd.target;
45 import dmd.tokens;
47 struct ObjcSelector
49 // MARK: Selector
50 private __gshared StringTable!(ObjcSelector*) stringtable;
51 private __gshared int incnum = 0;
52 const(char)* stringvalue;
53 size_t stringlen;
54 size_t paramCount;
56 extern (C++) static void _init()
58 stringtable._init();
61 extern (D) this(const(char)* sv, size_t len, size_t pcount) @safe
63 stringvalue = sv;
64 stringlen = len;
65 paramCount = pcount;
68 extern (D) static ObjcSelector* lookup(const(char)* s)
70 size_t len = 0;
71 size_t pcount = 0;
72 const(char)* i = s;
73 while (*i != 0)
75 ++len;
76 if (*i == ':')
77 ++pcount;
78 ++i;
80 return lookup(s, len, pcount);
83 extern (D) static ObjcSelector* lookup(const(char)* s, size_t len, size_t pcount)
85 auto sv = stringtable.update(s, len);
86 ObjcSelector* sel = sv.value;
87 if (!sel)
89 sel = new ObjcSelector(sv.toDchars(), len, pcount);
90 sv.value = sel;
92 return sel;
95 extern (C++) static ObjcSelector* create(FuncDeclaration fdecl)
97 OutBuffer buf;
98 TypeFunction ftype = cast(TypeFunction)fdecl.type;
99 const id = fdecl.ident.toString();
100 const nparams = ftype.parameterList.length;
101 // Special case: property setter
102 if (ftype.isproperty && nparams == 1)
104 // rewrite "identifier" as "setIdentifier"
105 char firstChar = id[0];
106 if (firstChar >= 'a' && firstChar <= 'z')
107 firstChar = cast(char)(firstChar - 'a' + 'A');
108 buf.writestring("set");
109 buf.writeByte(firstChar);
110 buf.write(id[1 .. id.length - 1]);
111 buf.writeByte(':');
112 goto Lcomplete;
114 // write identifier in selector
115 buf.write(id[]);
116 // add mangled type and colon for each parameter
117 if (nparams)
119 buf.writeByte('_');
120 foreach (i, fparam; ftype.parameterList)
122 mangleToBuffer(fparam.type, buf);
123 buf.writeByte(':');
126 Lcomplete:
127 buf.writeByte('\0');
128 // the slice is not expected to include a terminating 0
129 return lookup(cast(const(char)*)buf[].ptr, buf.length - 1, nparams);
132 extern (D) const(char)[] toString() const pure
134 return stringvalue[0 .. stringlen];
138 private __gshared Objc _objc;
140 Objc objc()
142 return _objc;
147 * Contains all data for a class declaration that is needed for the Objective-C
148 * integration.
150 extern (C++) struct ObjcClassDeclaration
152 /// `true` if this class is a metaclass.
153 bool isMeta = false;
155 /// `true` if this class is externally defined.
156 bool isExtern = false;
158 /// Name of this class.
159 Identifier identifier;
161 /// The class declaration this belongs to.
162 ClassDeclaration classDeclaration;
164 /// The metaclass of this class.
165 ClassDeclaration metaclass;
167 /// List of non-inherited methods.
168 FuncDeclaration[] methodList;
170 extern (D) this(ClassDeclaration classDeclaration) @safe
172 this.classDeclaration = classDeclaration;
175 bool isRootClass() const @safe
177 return classDeclaration.classKind == ClassKind.objc &&
178 !metaclass &&
179 !classDeclaration.baseClass;
184 * Contains all data for a function declaration that is needed for the
185 * Objective-C integration.
187 extern (C++) struct ObjcFuncDeclaration
189 /// The method selector (member functions only).
190 ObjcSelector* selector;
192 /// The implicit selector parameter.
193 VarDeclaration selectorParameter;
195 /// `true` if this function declaration is declared optional.
196 bool isOptional;
199 // Should be an interface
200 extern(C++) abstract class Objc
202 static void _init()
204 if (target.objc.supported)
205 _objc = new Supported;
206 else
207 _objc = new Unsupported;
211 * Deinitializes the global state of the compiler.
213 * This can be used to restore the state set by `_init` to its original
214 * state.
216 static void deinitialize()
218 _objc = _objc.init;
221 abstract void setObjc(ClassDeclaration cd);
222 abstract void setObjc(InterfaceDeclaration);
225 * Returns a pretty textual representation of the given class declaration.
227 * Params:
228 * classDeclaration = the class declaration to return the textual representation for
229 * qualifyTypes = `true` if types should be qualified in the result
231 * Returns: the textual representation
233 abstract const(char)* toPrettyChars(ClassDeclaration classDeclaration, bool qualifyTypes) const;
235 abstract void setSelector(FuncDeclaration, Scope* sc);
236 abstract void validateSelector(FuncDeclaration fd);
237 abstract void checkLinkage(FuncDeclaration fd);
240 * Returns `true` if the given function declaration is virtual.
242 * Function declarations with Objective-C linkage and which are static or
243 * final are considered virtual.
245 * Params:
246 * fd = the function declaration to check if it's virtual
248 * Returns: `true` if the given function declaration is virtual
250 abstract bool isVirtual(const FuncDeclaration fd) const;
253 * Marks the given function declaration as optional.
255 * A function declaration is considered optional if it's annotated with the
256 * UDA: `@(core.attribute.optional)`. Only function declarations inside
257 * interface declarations and with Objective-C linkage can be declared as
258 * optional.
260 * Params:
261 * functionDeclaration = the function declaration to be set as optional
262 * sc = the scope from the semantic phase
264 abstract void setAsOptional(FuncDeclaration functionDeclaration, Scope* sc) const;
267 * Validates function declarations declared optional.
269 * Params:
270 * functionDeclaration = the function declaration to validate
272 abstract void validateOptional(FuncDeclaration functionDeclaration) const;
275 * Gets the parent of the given function declaration.
277 * Handles Objective-C static member functions, which are virtual functions
278 * of the metaclass, by returning the parent class declaration to the
279 * metaclass.
281 * Params:
282 * fd = the function declaration to get the parent of
283 * cd = the current parent, i.e. the class declaration the given function
284 * declaration belongs to
286 * Returns: the parent
288 abstract ClassDeclaration getParent(FuncDeclaration fd,
289 ClassDeclaration cd) const;
292 * Adds the given function to the list of Objective-C methods.
294 * This list will later be used output the necessary Objective-C module info.
296 * Params:
297 * fd = the function declaration to be added to the list
298 * cd = the class declaration the function belongs to
300 abstract void addToClassMethodList(FuncDeclaration fd,
301 ClassDeclaration cd) const;
304 * Returns the `this` pointer of the given function declaration.
306 * This is only used for class/static methods. For instance methods, no
307 * Objective-C specialization is necessary.
309 * Params:
310 * funcDeclaration = the function declaration to get the `this` pointer for
312 * Returns: the `this` pointer of the given function declaration, or `null`
313 * if the given function declaration is not an Objective-C method.
315 abstract inout(AggregateDeclaration) isThis(inout FuncDeclaration funcDeclaration) const;
318 * Creates the selector parameter for the given function declaration.
320 * Objective-C methods has an extra hidden parameter that comes after the
321 * `this` parameter. The selector parameter is of the Objective-C type `SEL`
322 * and contains the selector which this method was called with.
324 * Params:
325 * fd = the function declaration to create the parameter for
326 * sc = the scope from the semantic phase
328 * Returns: the newly created selector parameter or `null` for
329 * non-Objective-C functions
331 abstract VarDeclaration createSelectorParameter(FuncDeclaration fd, Scope* sc) const;
334 * Creates and sets the metaclass on the given class/interface declaration.
336 * Will only be performed on regular Objective-C classes, not on metaclasses.
338 * Params:
339 * classDeclaration = the class/interface declaration to set the metaclass on
341 abstract void setMetaclass(InterfaceDeclaration interfaceDeclaration, Scope* sc) const;
343 /// ditto
344 abstract void setMetaclass(ClassDeclaration classDeclaration, Scope* sc) const;
347 * Returns Objective-C runtime metaclass of the given class declaration.
349 * `ClassDeclaration.ObjcClassDeclaration.metaclass` contains the metaclass
350 * from the semantic point of view. This function returns the metaclass from
351 * the Objective-C runtime's point of view. Here, the metaclass of a
352 * metaclass is the root metaclass, not `null`. The root metaclass's
353 * metaclass is itself.
355 * Params:
356 * classDeclaration = The class declaration to return the metaclass of
358 * Returns: the Objective-C runtime metaclass of the given class declaration
360 abstract ClassDeclaration getRuntimeMetaclass(ClassDeclaration classDeclaration) const;
363 abstract void addSymbols(AttribDeclaration attribDeclaration,
364 ClassDeclarations* classes, ClassDeclarations* categories) const;
367 abstract void addSymbols(ClassDeclaration classDeclaration,
368 ClassDeclarations* classes, ClassDeclarations* categories) const;
371 * Issues a compile time error if the `.offsetof`/`.tupleof` property is
372 * used on a field of an Objective-C class.
374 * To solve the fragile base class problem in Objective-C, fields have a
375 * dynamic offset instead of a static offset. The compiler outputs a
376 * statically known offset which later the dynamic loader can update, if
377 * necessary, when the application is loaded. Due to this behavior it
378 * doesn't make sense to be able to get the offset of a field at compile
379 * time, because this offset might not actually be the same at runtime.
381 * To get the offset of a field that is correct at runtime, functionality
382 * from the Objective-C runtime can be used instead.
384 * Params:
385 * expression = the `.offsetof`/`.tupleof` expression
386 * aggregateDeclaration = the aggregate declaration the field of the
387 * `.offsetof`/`.tupleof` expression belongs to
388 * type = the type of the receiver of the `.tupleof` expression
390 * See_Also:
391 * $(LINK2 https://en.wikipedia.org/wiki/Fragile_binary_interface_problem,
392 * Fragile Binary Interface Problem)
394 * See_Also:
395 * $(LINK2 https://developer.apple.com/documentation/objectivec/objective_c_runtime,
396 * Objective-C Runtime)
398 abstract void checkOffsetof(Expression expression, AggregateDeclaration aggregateDeclaration) const;
400 /// ditto
401 abstract void checkTupleof(Expression expression, TypeClass type) const;
404 extern(C++) private final class Unsupported : Objc
406 extern(D) final this()
408 ObjcGlue.initialize();
411 override void setObjc(ClassDeclaration cd)
413 .error(cd.loc, "%s `%s` Objective-C classes not supported", cd.kind, cd.toPrettyChars);
416 override void setObjc(InterfaceDeclaration id)
418 .error(id.loc, "%s `%s` Objective-C interfaces not supported", id.kind, id.toPrettyChars);
421 override const(char)* toPrettyChars(ClassDeclaration, bool qualifyTypes) const
423 assert(0, "Should never be called when Objective-C is not supported");
426 override void setSelector(FuncDeclaration, Scope*)
428 // noop
431 override void validateSelector(FuncDeclaration)
433 // noop
436 override void checkLinkage(FuncDeclaration)
438 // noop
441 override bool isVirtual(const FuncDeclaration) const
443 assert(0, "Should never be called when Objective-C is not supported");
446 override void setAsOptional(FuncDeclaration, Scope*) const
448 // noop
451 override void validateOptional(FuncDeclaration) const
453 // noop
456 override ClassDeclaration getParent(FuncDeclaration, ClassDeclaration cd) const
458 return cd;
461 override void addToClassMethodList(FuncDeclaration, ClassDeclaration) const
463 // noop
466 override inout(AggregateDeclaration) isThis(inout FuncDeclaration funcDeclaration) const
468 return null;
471 override VarDeclaration createSelectorParameter(FuncDeclaration, Scope*) const
473 return null;
476 override void setMetaclass(InterfaceDeclaration, Scope*) const
478 // noop
481 override void setMetaclass(ClassDeclaration, Scope*) const
483 // noop
486 override ClassDeclaration getRuntimeMetaclass(ClassDeclaration classDeclaration) const
488 assert(0, "Should never be called when Objective-C is not supported");
491 override void addSymbols(AttribDeclaration attribDeclaration,
492 ClassDeclarations* classes, ClassDeclarations* categories) const
494 // noop
497 override void addSymbols(ClassDeclaration classDeclaration,
498 ClassDeclarations* classes, ClassDeclarations* categories) const
500 // noop
503 override void checkOffsetof(Expression expression, AggregateDeclaration aggregateDeclaration) const
505 // noop
508 override void checkTupleof(Expression expression, TypeClass type) const
510 // noop
514 extern(C++) private final class Supported : Objc
516 extern(D) final this()
518 VersionCondition.addPredefinedGlobalIdent("D_ObjectiveC");
520 ObjcGlue.initialize();
521 ObjcSelector._init();
524 override void setObjc(ClassDeclaration cd)
526 cd.classKind = ClassKind.objc;
527 cd.objc.isExtern = (cd.storage_class & STC.extern_) > 0;
530 override void setObjc(InterfaceDeclaration id)
532 id.classKind = ClassKind.objc;
533 id.objc.isExtern = true;
536 override const(char)* toPrettyChars(ClassDeclaration cd, bool qualifyTypes) const
538 return cd.parent.toPrettyChars(qualifyTypes);
541 override void setSelector(FuncDeclaration fd, Scope* sc)
543 foreachUda(fd, sc, (e) {
544 if (!e.isStructLiteralExp())
545 return 0;
547 auto literal = e.isStructLiteralExp();
548 assert(literal.sd);
550 if (!isCoreUda(literal.sd, Id.udaSelector))
551 return 0;
553 if (fd.objc.selector)
555 .error(fd.loc, "%s `%s` can only have one Objective-C selector per method", fd.kind, fd.toPrettyChars);
556 return 1;
559 assert(literal.elements.length == 1);
560 auto se = (*literal.elements)[0].toStringExp();
561 assert(se);
563 fd.objc.selector = ObjcSelector.lookup(se.toUTF8(sc).peekString().ptr);
565 return 0;
569 override void validateSelector(FuncDeclaration fd)
571 if (!fd.objc.selector)
572 return;
573 TypeFunction tf = cast(TypeFunction)fd.type;
574 if (fd.objc.selector.paramCount != tf.parameterList.parameters.length)
575 .error(fd.loc, "%s `%s` number of colons in Objective-C selector must match number of parameters", fd.kind, fd.toPrettyChars);
576 if (fd.parent && fd.parent.isTemplateInstance())
577 .error(fd.loc, "%s `%s` template cannot have an Objective-C selector attached", fd.kind, fd.toPrettyChars);
580 override void checkLinkage(FuncDeclaration fd)
582 if (fd._linkage != LINK.objc && fd.objc.selector)
583 .error(fd.loc, "%s `%s` must have Objective-C linkage to attach a selector", fd.kind, fd.toPrettyChars);
586 override bool isVirtual(const FuncDeclaration fd) const
589 assert(fd.selector);
590 assert(fd.isMember);
594 if (fd.toParent.isInterfaceDeclaration && fd.isFinal)
595 return false;
597 // * final member functions are kept virtual with Objective-C linkage
598 // because the Objective-C runtime always use dynamic dispatch.
599 // * static member functions are kept virtual too, as they represent
600 // methods of the metaclass.
601 with (fd.visibility)
602 return !(kind == Visibility.Kind.private_ || kind == Visibility.Kind.package_);
605 override void setAsOptional(FuncDeclaration fd, Scope* sc) const
607 const count = declaredAsOptionalCount(fd, sc);
608 fd.objc.isOptional = count > 0;
610 if (count > 1)
611 .error(fd.loc, "%s `%s` can only declare a function as optional once", fd.kind, fd.toPrettyChars);
614 /// Returns: the number of times `fd` has been declared as optional.
615 private int declaredAsOptionalCount(FuncDeclaration fd , Scope* sc) const
617 int count;
619 foreachUda(fd, sc, (e) {
620 if (!e.isTypeExp())
621 return 0;
623 auto typeExp = e.isTypeExp();
625 if (typeExp.type.ty != Tenum)
626 return 0;
628 auto typeEnum = cast(TypeEnum) typeExp.type;
630 if (isCoreUda(typeEnum.sym, Id.udaOptional))
631 count++;
633 return 0;
636 return count;
639 override void validateOptional(FuncDeclaration fd) const
641 if (!fd.objc.isOptional)
642 return;
644 if (fd._linkage != LINK.objc)
646 .error(fd.loc, "%s `%s` only functions with Objective-C linkage can be declared as optional", fd.kind, fd.toPrettyChars);
648 const linkage = linkageToString(fd._linkage);
650 errorSupplemental(fd.loc, "function is declared with %.*s linkage",
651 cast(uint) linkage.length, linkage.ptr);
654 auto parent = fd.parent;
656 if (parent && parent.isTemplateInstance())
658 .error(fd.loc, "%s `%s` template cannot be optional", fd.kind, fd.toPrettyChars);
659 parent = parent.parent;
660 assert(parent);
663 if (parent && !parent.isInterfaceDeclaration())
665 .error(fd.loc, "%s `%s` only functions declared inside interfaces can be optional", fd.kind, fd.toPrettyChars);
666 errorSupplemental(fd.loc, "function is declared inside %s", fd.parent.kind);
670 override ClassDeclaration getParent(FuncDeclaration fd, ClassDeclaration cd) const
671 out(metaclass)
673 assert(metaclass);
677 if (cd.classKind == ClassKind.objc && fd.isStatic && !cd.objc.isMeta)
678 return cd.objc.metaclass;
679 else
680 return cd;
683 override void addToClassMethodList(FuncDeclaration fd, ClassDeclaration cd) const
686 assert(fd.parent.isClassDeclaration);
690 if (cd.classKind != ClassKind.objc)
691 return;
693 if (!fd.objc.selector)
694 return;
696 assert(fd.isStatic ? cd.objc.isMeta : !cd.objc.isMeta);
698 cd.objc.methodList ~= fd;
701 override inout(AggregateDeclaration) isThis(inout FuncDeclaration funcDeclaration) const
703 with(funcDeclaration)
705 if (!objc.selector)
706 return null;
708 // Use Objective-C class object as 'this'
709 auto cd = isMember2().isClassDeclaration();
711 if (cd.classKind == ClassKind.objc)
713 if (!cd.objc.isMeta)
714 return cd.objc.metaclass;
717 return null;
721 override VarDeclaration createSelectorParameter(FuncDeclaration fd, Scope* sc) const
724 assert(fd.selectorParameter is null);
728 if (!fd.objc.selector)
729 return null;
731 auto ident = Identifier.generateAnonymousId("_cmd");
732 auto var = new VarDeclaration(fd.loc, Type.tvoidptr, ident, null);
733 var.storage_class |= STC.parameter;
734 var.dsymbolSemantic(sc);
735 if (!sc.insert(var))
736 assert(false);
737 var.parent = fd;
739 return var;
742 override void setMetaclass(InterfaceDeclaration interfaceDeclaration, Scope* sc) const
744 auto newMetaclass(Loc loc, BaseClasses* metaBases)
746 auto ident = createMetaclassIdentifier(interfaceDeclaration);
747 return new InterfaceDeclaration(loc, ident, metaBases);
750 .setMetaclass!newMetaclass(interfaceDeclaration, sc);
753 override void setMetaclass(ClassDeclaration classDeclaration, Scope* sc) const
755 auto newMetaclass(Loc loc, BaseClasses* metaBases)
757 auto ident = createMetaclassIdentifier(classDeclaration);
758 return new ClassDeclaration(loc, ident, metaBases, new Dsymbols(), 0);
761 .setMetaclass!newMetaclass(classDeclaration, sc);
764 override ClassDeclaration getRuntimeMetaclass(ClassDeclaration classDeclaration) const
766 if (!classDeclaration.objc.metaclass && classDeclaration.objc.isMeta)
768 if (classDeclaration.baseClass)
769 return getRuntimeMetaclass(classDeclaration.baseClass);
770 else
771 return classDeclaration;
773 else
774 return classDeclaration.objc.metaclass;
777 override void addSymbols(AttribDeclaration attribDeclaration,
778 ClassDeclarations* classes, ClassDeclarations* categories) const
780 auto symbols = attribDeclaration.include(null);
782 if (!symbols)
783 return;
785 foreach (symbol; *symbols)
786 symbol.addObjcSymbols(classes, categories);
789 override void addSymbols(ClassDeclaration classDeclaration,
790 ClassDeclarations* classes, ClassDeclarations* categories) const
792 with (classDeclaration)
793 if (classKind == ClassKind.objc && !objc.isExtern && !objc.isMeta)
794 classes.push(classDeclaration);
797 override void checkOffsetof(Expression expression, AggregateDeclaration aggregateDeclaration) const
799 if (aggregateDeclaration.classKind != ClassKind.objc)
800 return;
802 enum errorMessage = "no property `offsetof` for member `%s` of type " ~
803 "`%s`";
805 enum supplementalMessage = "`offsetof` is not available for members " ~
806 "of Objective-C classes. Please use the Objective-C runtime instead";
808 error(expression.loc, errorMessage, expression.toChars(),
809 expression.type.toChars());
810 errorSupplemental(expression.loc, supplementalMessage);
813 override void checkTupleof(Expression expression, TypeClass type) const
815 if (type.sym.classKind != ClassKind.objc)
816 return;
818 error(expression.loc, "no property `tupleof` for type `%s`", type.toChars());
819 errorSupplemental(expression.loc, "`tupleof` is not available for members " ~
820 "of Objective-C classes. Please use the Objective-C runtime instead");
825 * Creates and sets the metaclass on the given class/interface declaration.
827 * Will only be performed on regular Objective-C classes, not on metaclasses.
829 * Params:
830 * newMetaclass = a function that returns the metaclass to set. This should
831 * return the same type as `T`.
832 * classDeclaration = the class/interface declaration to set the metaclass on
834 private void setMetaclass(alias newMetaclass, T)(T classDeclaration, Scope* sc)
835 if (is(T == ClassDeclaration) || is(T == InterfaceDeclaration))
837 static if (is(T == ClassDeclaration))
838 enum errorType = "class";
839 else
840 enum errorType = "interface";
842 with (classDeclaration)
844 if (classKind != ClassKind.objc || objc.isMeta || objc.metaclass)
845 return;
847 if (!objc.identifier)
848 objc.identifier = classDeclaration.ident;
850 auto metaBases = new BaseClasses();
852 foreach (base ; baseclasses.opSlice)
854 auto baseCd = base.sym;
855 assert(baseCd);
857 if (baseCd.classKind == ClassKind.objc)
859 assert(baseCd.objc.metaclass);
860 assert(baseCd.objc.metaclass.objc.isMeta);
861 assert(baseCd.objc.metaclass.type.ty == Tclass);
863 auto metaBase = new BaseClass(baseCd.objc.metaclass.type);
864 metaBase.sym = baseCd.objc.metaclass;
865 metaBases.push(metaBase);
867 else
869 .error(classDeclaration.loc, "%s `%s` base " ~ errorType ~ " for an Objective-C " ~
870 errorType ~ " must be `extern (Objective-C)`", classDeclaration.kind, classDeclaration.toPrettyChars);
874 objc.metaclass = newMetaclass(loc, metaBases);
875 objc.metaclass.storage_class |= STC.static_;
876 objc.metaclass.classKind = ClassKind.objc;
877 objc.metaclass.objc.isMeta = true;
878 objc.metaclass.objc.isExtern = objc.isExtern;
879 objc.metaclass.objc.identifier = objc.identifier;
881 if (baseClass)
882 objc.metaclass.baseClass = baseClass.objc.metaclass;
884 members.push(objc.metaclass);
885 objc.metaclass.addMember(sc, classDeclaration);
887 objc.metaclass.members = new Dsymbols();
888 objc.metaclass.dsymbolSemantic(sc);
892 private Identifier createMetaclassIdentifier(ClassDeclaration classDeclaration)
894 const name = "class_" ~ classDeclaration.ident.toString ~ "_Meta";
895 return Identifier.generateAnonymousId(name);