]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/init.c
d: Merge upstream dmd 7132b3537
[thirdparty/gcc.git] / gcc / d / dmd / init.c
1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 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/init.c
9 */
10
11 #include "root/dsystem.h"
12 #include "root/checkedint.h"
13
14 #include "mars.h"
15 #include "init.h"
16 #include "expression.h"
17 #include "statement.h"
18 #include "identifier.h"
19 #include "declaration.h"
20 #include "aggregate.h"
21 #include "scope.h"
22 #include "mtype.h"
23 #include "hdrgen.h"
24 #include "template.h"
25 #include "id.h"
26 #include "tokens.h"
27
28 /********************************** Initializer *******************************/
29
30 Initializer::Initializer(Loc loc)
31 {
32 this->loc = loc;
33 }
34
35 Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
36 {
37 Initializers *a = NULL;
38 if (ai)
39 {
40 a = new Initializers();
41 a->setDim(ai->length);
42 for (size_t i = 0; i < a->length; i++)
43 (*a)[i] = (*ai)[i]->syntaxCopy();
44 }
45 return a;
46 }
47
48 const char *Initializer::toChars()
49 {
50 OutBuffer buf;
51 HdrGenState hgs;
52 ::toCBuffer(this, &buf, &hgs);
53 return buf.extractChars();
54 }
55
56 /********************************** ErrorInitializer ***************************/
57
58 ErrorInitializer::ErrorInitializer()
59 : Initializer(Loc())
60 {
61 }
62
63 Initializer *ErrorInitializer::syntaxCopy()
64 {
65 return this;
66 }
67
68 /********************************** VoidInitializer ***************************/
69
70 VoidInitializer::VoidInitializer(Loc loc)
71 : Initializer(loc)
72 {
73 type = NULL;
74 }
75
76 Initializer *VoidInitializer::syntaxCopy()
77 {
78 return new VoidInitializer(loc);
79 }
80
81 /********************************** StructInitializer *************************/
82
83 StructInitializer::StructInitializer(Loc loc)
84 : Initializer(loc)
85 {
86 }
87
88 Initializer *StructInitializer::syntaxCopy()
89 {
90 StructInitializer *ai = new StructInitializer(loc);
91 assert(field.length == value.length);
92 ai->field.setDim(field.length);
93 ai->value.setDim(value.length);
94 for (size_t i = 0; i < field.length; i++)
95 {
96 ai->field[i] = field[i];
97 ai->value[i] = value[i]->syntaxCopy();
98 }
99 return ai;
100 }
101
102 void StructInitializer::addInit(Identifier *field, Initializer *value)
103 {
104 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
105 this->field.push(field);
106 this->value.push(value);
107 }
108
109 /********************************** ArrayInitializer ************************************/
110
111 ArrayInitializer::ArrayInitializer(Loc loc)
112 : Initializer(loc)
113 {
114 dim = 0;
115 type = NULL;
116 sem = false;
117 }
118
119 Initializer *ArrayInitializer::syntaxCopy()
120 {
121 //printf("ArrayInitializer::syntaxCopy()\n");
122 ArrayInitializer *ai = new ArrayInitializer(loc);
123 assert(index.length == value.length);
124 ai->index.setDim(index.length);
125 ai->value.setDim(value.length);
126 for (size_t i = 0; i < ai->value.length; i++)
127 {
128 ai->index[i] = index[i] ? index[i]->syntaxCopy() : NULL;
129 ai->value[i] = value[i]->syntaxCopy();
130 }
131 return ai;
132 }
133
134 void ArrayInitializer::addInit(Expression *index, Initializer *value)
135 {
136 this->index.push(index);
137 this->value.push(value);
138 dim = 0;
139 type = NULL;
140 }
141
142 bool ArrayInitializer::isAssociativeArray()
143 {
144 for (size_t i = 0; i < value.length; i++)
145 {
146 if (index[i])
147 return true;
148 }
149 return false;
150 }
151
152 /********************************
153 * If possible, convert array initializer to associative array initializer.
154 */
155
156 Expression *ArrayInitializer::toAssocArrayLiteral()
157 {
158 Expression *e;
159
160 //printf("ArrayInitializer::toAssocArrayInitializer()\n");
161 //static int i; if (++i == 2) halt();
162 Expressions *keys = new Expressions();
163 keys->setDim(value.length);
164 Expressions *values = new Expressions();
165 values->setDim(value.length);
166
167 for (size_t i = 0; i < value.length; i++)
168 {
169 e = index[i];
170 if (!e)
171 goto Lno;
172 (*keys)[i] = e;
173
174 Initializer *iz = value[i];
175 if (!iz)
176 goto Lno;
177 e = initializerToExpression(iz);
178 if (!e)
179 goto Lno;
180 (*values)[i] = e;
181 }
182 e = new AssocArrayLiteralExp(loc, keys, values);
183 return e;
184
185 Lno:
186 delete keys;
187 delete values;
188 error(loc, "not an associative array initializer");
189 return new ErrorExp();
190 }
191
192 /********************************** ExpInitializer ************************************/
193
194 ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
195 : Initializer(loc)
196 {
197 this->exp = exp;
198 this->expandTuples = false;
199 }
200
201 Initializer *ExpInitializer::syntaxCopy()
202 {
203 return new ExpInitializer(loc, exp->syntaxCopy());
204 }
205
206 #if 1 // should be removed and rely on ctfeInterpreter()
207 bool arrayHasNonConstPointers(Expressions *elems);
208
209 bool hasNonConstPointers(Expression *e)
210 {
211 if (e->type->ty == Terror)
212 return false;
213
214 if (e->op == TOKnull)
215 return false;
216 if (e->op == TOKstructliteral)
217 {
218 StructLiteralExp *se = (StructLiteralExp *)e;
219 return arrayHasNonConstPointers(se->elements);
220 }
221 if (e->op == TOKarrayliteral)
222 {
223 if (!e->type->nextOf()->hasPointers())
224 return false;
225 ArrayLiteralExp *ae = (ArrayLiteralExp *)e;
226 return arrayHasNonConstPointers(ae->elements);
227 }
228 if (e->op == TOKassocarrayliteral)
229 {
230 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e;
231 if (ae->type->nextOf()->hasPointers() &&
232 arrayHasNonConstPointers(ae->values))
233 return true;
234 if (((TypeAArray *)ae->type)->index->hasPointers())
235 return arrayHasNonConstPointers(ae->keys);
236 return false;
237 }
238 if (e->op == TOKaddress)
239 {
240 AddrExp *ae = (AddrExp *)e;
241 if (ae->e1->op == TOKstructliteral)
242 {
243 StructLiteralExp *se = (StructLiteralExp *)ae->e1;
244 if (!(se->stageflags & stageSearchPointers))
245 {
246 int old = se->stageflags;
247 se->stageflags |= stageSearchPointers;
248 bool ret = arrayHasNonConstPointers(se->elements);
249 se->stageflags = old;
250 return ret;
251 }
252 else
253 {
254 return false;
255 }
256 }
257 return true;
258 }
259 if (e->type->ty== Tpointer && e->type->nextOf()->ty != Tfunction)
260 {
261 if (e->op == TOKsymoff) // address of a global is OK
262 return false;
263 if (e->op == TOKint64) // cast(void *)int is OK
264 return false;
265 if (e->op == TOKstring) // "abc".ptr is OK
266 return false;
267 return true;
268 }
269 return false;
270 }
271
272 bool arrayHasNonConstPointers(Expressions *elems)
273 {
274 for (size_t i = 0; i < elems->length; i++)
275 {
276 Expression *e = (*elems)[i];
277 if (e && hasNonConstPointers(e))
278 return true;
279 }
280 return false;
281 }
282 #endif