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