d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
[official-gcc.git] / gcc / d / dmd / denum.d
blob98bf4dd2aad1cb7063de4e713c0b30e03190f0c4
1 /**
2 * Define `enum` declarations and `enum` members.
4 * Specification: $(LINK2 https://dlang.org/spec/enum.html, Enums)
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/denum.d, _denum.d)
10 * Documentation: https://dlang.org/phobos/dmd_denum.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/denum.d
12 * References: https://dlang.org/spec/enum.html
15 module dmd.denum;
17 import core.stdc.stdio;
19 import dmd.astenums;
20 import dmd.attrib;
21 import dmd.errors;
22 import dmd.gluelayer;
23 import dmd.declaration;
24 import dmd.dscope;
25 import dmd.dsymbol;
26 import dmd.dsymbolsem;
27 import dmd.expression;
28 import dmd.id;
29 import dmd.identifier;
30 import dmd.init;
31 import dmd.location;
32 import dmd.mtype;
33 import dmd.typesem;
34 import dmd.visitor;
36 /***********************************************************
37 * AST node for `EnumDeclaration`
38 * https://dlang.org/spec/enum.html#EnumDeclaration
40 extern (C++) final class EnumDeclaration : ScopeDsymbol
42 /* The separate, and distinct, cases are:
43 * 1. enum { ... }
44 * 2. enum : memtype { ... }
45 * 3. enum id { ... }
46 * 4. enum id : memtype { ... }
47 * 5. enum id : memtype;
48 * 6. enum id;
50 Type type; // the TypeEnum
51 Type memtype; // type of the members
53 Visibility visibility;
54 Expression maxval;
55 Expression minval;
56 Expression defaultval; // default initializer
58 // `bool` fields that are compacted into bit fields in a string mixin
59 private extern (D) static struct BitFields
61 bool isdeprecated;
62 bool added;
63 bool inuse;
66 import dmd.common.bitfields : generateBitFields;
67 mixin(generateBitFields!(BitFields, ubyte));
69 extern (D) this(const ref Loc loc, Identifier ident, Type memtype)
71 super(loc, ident);
72 //printf("EnumDeclaration() %p %s : %s\n", this, toChars(), memtype.toChars());
73 type = new TypeEnum(this);
74 this.memtype = memtype;
75 visibility = Visibility(Visibility.Kind.undefined);
78 override EnumDeclaration syntaxCopy(Dsymbol s)
80 assert(!s);
81 auto ed = new EnumDeclaration(loc, ident, memtype ? memtype.syntaxCopy() : null);
82 ScopeDsymbol.syntaxCopy(ed);
83 return ed;
86 override void addMember(Scope* sc, ScopeDsymbol sds)
88 version (none)
90 printf("EnumDeclaration::addMember() %s\n", toChars());
91 for (size_t i = 0; i < members.length; i++)
93 EnumMember em = (*members)[i].isEnumMember();
94 printf(" member %s\n", em.toChars());
97 if (!isAnonymous())
99 ScopeDsymbol.addMember(sc, sds);
102 addEnumMembers(this, sc, sds);
105 override void setScope(Scope* sc)
107 if (semanticRun > PASS.initial)
108 return;
109 ScopeDsymbol.setScope(sc);
112 override bool oneMember(Dsymbol* ps, Identifier ident)
114 if (isAnonymous())
115 return Dsymbol.oneMembers(members, ps, ident);
116 return Dsymbol.oneMember(ps, ident);
119 override Type getType()
121 return type;
124 override const(char)* kind() const
126 return "enum";
129 override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
131 //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident.toChars());
132 if (_scope)
134 // Try one last time to resolve this enum
135 dsymbolSemantic(this, _scope);
138 Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
139 return s;
142 // is Dsymbol deprecated?
143 override bool isDeprecated() const
145 return isdeprecated;
148 override Visibility visible() pure nothrow @nogc @safe
150 return visibility;
154 /****************
155 * Determine if enum is a special one.
156 * Returns:
157 * `true` if special
159 bool isSpecial() const nothrow @nogc
161 return isSpecialEnumIdent(ident) && memtype;
164 Expression getDefaultValue(const ref Loc loc)
166 Expression handleErrors(){
167 defaultval = ErrorExp.get();
168 return defaultval;
170 //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
171 // https://issues.dlang.org/show_bug.cgi?id=23904
172 // Return defaultval only if it is not ErrorExp.
173 // A speculative context may set defaultval to ErrorExp;
174 // subsequent non-speculative contexts need to be able
175 // to print the error.
176 if (defaultval && !defaultval.isErrorExp())
177 return defaultval;
179 if (isCsymbol())
180 return memtype.defaultInit(loc, true);
182 if (_scope)
183 dsymbolSemantic(this, _scope);
184 if (errors)
185 return handleErrors();
186 if (!members)
188 if (isSpecial())
190 /* Allow these special enums to not need a member list
192 return defaultval = memtype.defaultInit(loc);
195 error(loc, "%s `%s` is opaque and has no default initializer", kind, toPrettyChars);
196 return handleErrors();
199 foreach (const i; 0 .. members.length)
201 EnumMember em = (*members)[i].isEnumMember();
202 if (em)
204 if (em.semanticRun < PASS.semanticdone)
206 error(loc, "%s `%s` forward reference of `%s.init`", kind, toPrettyChars, toChars());
207 return handleErrors();
210 defaultval = em.value;
211 return defaultval;
214 return handleErrors();
217 Type getMemtype(const ref Loc loc)
219 if (_scope)
221 /* Enum is forward referenced. We don't need to resolve the whole thing,
222 * just the base type
224 if (memtype)
226 Loc locx = loc.isValid() ? loc : this.loc;
227 memtype = memtype.typeSemantic(locx, _scope);
229 else
231 // Run semantic to get the type from a possible first member value
232 dsymbolSemantic(this, _scope);
235 if (!memtype)
237 if (!isAnonymous() && (members || semanticRun >= PASS.semanticdone))
238 memtype = Type.tint32;
239 else
241 Loc locx = loc.isValid() ? loc : this.loc;
242 error(locx, "is forward referenced looking for base type");
243 return Type.terror;
246 return memtype;
249 override inout(EnumDeclaration) isEnumDeclaration() inout
251 return this;
254 Symbol* sinit;
256 override void accept(Visitor v)
258 v.visit(this);
262 /***********************************************************
263 * AST node representing a member of an enum.
264 * https://dlang.org/spec/enum.html#EnumMember
265 * https://dlang.org/spec/enum.html#AnonymousEnumMember
267 extern (C++) final class EnumMember : VarDeclaration
269 /* Can take the following forms:
270 * 1. id
271 * 2. id = value
272 * 3. type id = value
274 @property ref value() { return (cast(ExpInitializer)_init).exp; }
276 // A cast() is injected to 'value' after dsymbolSemantic(),
277 // but 'origValue' will preserve the original value,
278 // or previous value + 1 if none was specified.
279 Expression origValue;
281 Type origType;
283 EnumDeclaration ed;
285 extern (D) this(const ref Loc loc, Identifier id, Expression value, Type origType)
287 super(loc, null, id ? id : Id.empty, new ExpInitializer(loc, value));
288 this.origValue = value;
289 this.origType = origType;
292 extern(D) this(Loc loc, Identifier id, Expression value, Type memtype,
293 StorageClass stc, UserAttributeDeclaration uad, DeprecatedDeclaration dd)
295 this(loc, id, value, memtype);
296 storage_class = stc;
297 userAttribDecl = uad;
298 depdecl = dd;
301 override EnumMember syntaxCopy(Dsymbol s)
303 assert(!s);
304 return new EnumMember(
305 loc, ident,
306 value ? value.syntaxCopy() : null,
307 origType ? origType.syntaxCopy() : null,
308 storage_class,
309 userAttribDecl ? userAttribDecl.syntaxCopy(s) : null,
310 depdecl ? depdecl.syntaxCopy(s) : null);
313 override const(char)* kind() const
315 return "enum member";
318 override inout(EnumMember) isEnumMember() inout
320 return this;
323 override void accept(Visitor v)
325 v.visit(this);
329 /******************************************
330 * Check for special enum names.
332 * Special enum names are used by the C++ name mangler to represent
333 * C++ types that are not basic D types.
334 * Params:
335 * ident = identifier to check for specialness
336 * Returns:
337 * `true` if it is special
339 bool isSpecialEnumIdent(const Identifier ident) @nogc nothrow
341 return ident == Id.__c_long ||
342 ident == Id.__c_ulong ||
343 ident == Id.__c_longlong ||
344 ident == Id.__c_ulonglong ||
345 ident == Id.__c_long_double ||
346 ident == Id.__c_wchar_t ||
347 ident == Id.__c_complex_float ||
348 ident == Id.__c_complex_double ||
349 ident == Id.__c_complex_real;