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 33 Initializer::Initializer(Loc loc) 34 { 35 this->loc = loc; 36 } 37 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 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 61 ErrorInitializer::ErrorInitializer() 62 : Initializer(Loc()) 63 { 64 } 65 66 Initializer *ErrorInitializer::syntaxCopy() 67 { 68 return this; 69 } 70 71 /********************************** VoidInitializer ***************************/ 72 73 VoidInitializer::VoidInitializer(Loc loc) 74 : Initializer(loc) 75 { 76 type = NULL; 77 } 78 79 Initializer *VoidInitializer::syntaxCopy() 80 { 81 return new VoidInitializer(loc); 82 } 83 84 /********************************** StructInitializer *************************/ 85 86 StructInitializer::StructInitializer(Loc loc) 87 : Initializer(loc) 88 { 89 } 90 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 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 114 ArrayInitializer::ArrayInitializer(Loc loc) 115 : Initializer(loc) 116 { 117 dim = 0; 118 type = NULL; 119 sem = false; 120 } 121 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 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 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 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 197 ExpInitializer::ExpInitializer(Loc loc, Expression *exp) 198 : Initializer(loc) 199 { 200 this->exp = exp; 201 this->expandTuples = false; 202 } 203 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 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 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