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