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 
Initializer(Loc loc)30 Initializer::Initializer(Loc loc)
31 {
32     this->loc = loc;
33 }
34 
arraySyntaxCopy(Initializers * ai)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 
toChars()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 
ErrorInitializer()58 ErrorInitializer::ErrorInitializer()
59     : Initializer(Loc())
60 {
61 }
62 
syntaxCopy()63 Initializer *ErrorInitializer::syntaxCopy()
64 {
65     return this;
66 }
67 
68 /********************************** VoidInitializer ***************************/
69 
VoidInitializer(Loc loc)70 VoidInitializer::VoidInitializer(Loc loc)
71     : Initializer(loc)
72 {
73     type = NULL;
74 }
75 
syntaxCopy()76 Initializer *VoidInitializer::syntaxCopy()
77 {
78     return new VoidInitializer(loc);
79 }
80 
81 /********************************** StructInitializer *************************/
82 
StructInitializer(Loc loc)83 StructInitializer::StructInitializer(Loc loc)
84     : Initializer(loc)
85 {
86 }
87 
syntaxCopy()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 
addInit(Identifier * field,Initializer * value)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 
ArrayInitializer(Loc loc)111 ArrayInitializer::ArrayInitializer(Loc loc)
112     : Initializer(loc)
113 {
114     dim = 0;
115     type = NULL;
116     sem = false;
117 }
118 
syntaxCopy()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 
addInit(Expression * index,Initializer * value)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 
isAssociativeArray()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 
toAssocArrayLiteral()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 
ExpInitializer(Loc loc,Expression * exp)194 ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
195     : Initializer(loc)
196 {
197     this->exp = exp;
198     this->expandTuples = false;
199 }
200 
syntaxCopy()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 
hasNonConstPointers(Expression * e)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 
arrayHasNonConstPointers(Expressions * elems)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
283