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