]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/cond.c
ipa-param-manip: Be careful about a reallocating hash_map
[thirdparty/gcc.git] / gcc / d / dmd / cond.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
a3b38b77 3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
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/cond.c
9 */
10
f9ab59ff 11#include "root/dsystem.h" // strcmp()
b4c522fa
IB
12
13#include "mars.h"
14#include "id.h"
15#include "init.h"
5b74dd0a 16#include "aggregate.h"
b4c522fa
IB
17#include "declaration.h"
18#include "identifier.h"
19#include "expression.h"
20#include "cond.h"
21#include "module.h"
22#include "template.h"
23#include "mtype.h"
24#include "scope.h"
5b74dd0a 25#include "statement.h"
b4c522fa
IB
26#include "arraytypes.h"
27#include "tokens.h"
28
b4c522fa
IB
29bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
30
5bc13e52 31int findCondition(Identifiers *ids, Identifier *ident)
b4c522fa
IB
32{
33 if (ids)
34 {
2cbc99d1 35 for (size_t i = 0; i < ids->length; i++)
b4c522fa 36 {
5bc13e52 37 Identifier *id = (*ids)[i];
b4c522fa 38
5bc13e52 39 if (id == ident)
b4c522fa
IB
40 return true;
41 }
42 }
43
44 return false;
45}
46
47/* ============================================================ */
48
49Condition::Condition(Loc loc)
50{
51 this->loc = loc;
52 inc = 0;
53}
54
55/* ============================================================ */
56
5b74dd0a
IB
57StaticForeach::StaticForeach(Loc loc, ForeachStatement *aggrfe, ForeachRangeStatement *rangefe)
58{
59 assert(!!aggrfe ^ !!rangefe);
60 this->loc = loc;
61 this->aggrfe = aggrfe;
62 this->rangefe = rangefe;
63 this->needExpansion = false;
64}
65
66StaticForeach *StaticForeach::syntaxCopy()
67{
68 return new StaticForeach(
69 loc,
70 aggrfe ? (ForeachStatement *)aggrfe->syntaxCopy() : NULL,
71 rangefe ? (ForeachRangeStatement *)rangefe->syntaxCopy() : NULL
72 );
73}
74
75/*****************************************
76 * Turn an aggregate which is an array into an expression tuple
77 * of its elements. I.e., lower
78 * static foreach (x; [1, 2, 3, 4]) { ... }
79 * to
80 * static foreach (x; AliasSeq!(1, 2, 3, 4)) { ... }
81 */
82
83static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc)
84{
85 Expression *aggr = sfe->aggrfe->aggr;
86 Expression *el = new ArrayLengthExp(aggr->loc, aggr);
87 sc = sc->startCTFE();
a3b38b77 88 el = expressionSemantic(el, sc);
5b74dd0a
IB
89 sc = sc->endCTFE();
90 el = el->optimize(WANTvalue);
91 el = el->ctfeInterpret();
92 if (el->op == TOKint64)
93 {
ce56fd94
IB
94 Expressions *es;
95 if (ArrayLiteralExp *ale = aggr->isArrayLiteralExp())
5b74dd0a 96 {
ce56fd94
IB
97 // Directly use the elements of the array for the TupleExp creation
98 es = ale->elements;
99 }
100 else
101 {
102 size_t length = (size_t)el->toInteger();
103 es = new Expressions();
104 es->setDim(length);
105 for (size_t i = 0; i < length; i++)
106 {
107 IntegerExp *index = new IntegerExp(sfe->loc, i, Type::tsize_t);
108 Expression *value = new IndexExp(aggr->loc, aggr, index);
109 (*es)[i] = value;
110 }
5b74dd0a
IB
111 }
112 sfe->aggrfe->aggr = new TupleExp(aggr->loc, es);
a3b38b77 113 sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
5b74dd0a 114 sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
68f46862 115 sfe->aggrfe->aggr = sfe->aggrfe->aggr->ctfeInterpret();
5b74dd0a
IB
116 }
117 else
118 {
119 sfe->aggrfe->aggr = new ErrorExp();
120 }
121}
122
123/*****************************************
124 * Wrap a statement into a function literal and call it.
125 *
126 * Params:
127 * loc = The source location.
128 * s = The statement.
129 * Returns:
130 * AST of the expression `(){ s; }()` with location loc.
131 */
132
133static Expression *wrapAndCall(Loc loc, Statement *s)
134{
c3a2ba10 135 TypeFunction *tf = new TypeFunction(ParameterList(), NULL, LINKdefault, 0);
5b74dd0a
IB
136 FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, loc, tf, TOKreserved, NULL);
137 fd->fbody = s;
138 FuncExp *fe = new FuncExp(loc, fd);
139 Expression *ce = new CallExp(loc, fe, new Expressions());
140 return ce;
141}
142
143/*****************************************
144 * Create a `foreach` statement from `aggrefe/rangefe` with given
145 * `foreach` variables and body `s`.
146 *
147 * Params:
148 * loc = The source location.
149 * parameters = The foreach variables.
150 * s = The `foreach` body.
151 * Returns:
152 * `foreach (parameters; aggregate) s;` or
153 * `foreach (parameters; lower .. upper) s;`
154 * Where aggregate/lower, upper are as for the current StaticForeach.
155 */
156
157static Statement *createForeach(StaticForeach *sfe, Loc loc, Parameters *parameters, Statement *s)
158{
159 if (sfe->aggrfe)
160 {
161 return new ForeachStatement(loc, sfe->aggrfe->op, parameters, sfe->aggrfe->aggr->syntaxCopy(), s, loc);
162 }
163 else
164 {
2cbc99d1 165 assert(sfe->rangefe && parameters->length == 1);
5b74dd0a
IB
166 return new ForeachRangeStatement(loc, sfe->rangefe->op, (*parameters)[0],
167 sfe->rangefe->lwr->syntaxCopy(),
168 sfe->rangefe->upr->syntaxCopy(), s, loc);
169 }
170}
171
172/*****************************************
173 * For a `static foreach` with multiple loop variables, the
174 * aggregate is lowered to an array of tuples. As D does not have
175 * built-in tuples, we need a suitable tuple type. This generates
176 * a `struct` that serves as the tuple type. This type is only
177 * used during CTFE and hence its typeinfo will not go to the
178 * object file.
179 *
180 * Params:
181 * loc = The source location.
182 * e = The expressions we wish to store in the tuple.
183 * sc = The current scope.
184 * Returns:
185 * A struct type of the form
186 * struct Tuple
187 * {
188 * typeof(AliasSeq!(e)) tuple;
189 * }
190 */
191
192static TypeStruct *createTupleType(Loc loc, Expressions *e)
193{ // TODO: move to druntime?
194 Identifier *sid = Identifier::generateId("Tuple");
195 StructDeclaration *sdecl = new StructDeclaration(loc, sid, false);
196 sdecl->storage_class |= STCstatic;
197 sdecl->members = new Dsymbols();
198 Identifier *fid = Identifier::idPool("tuple");
199 Type *ty = new TypeTypeof(loc, new TupleExp(loc, e));
200 sdecl->members->push(new VarDeclaration(loc, ty, fid, NULL));
201 TypeStruct *r = (TypeStruct *)sdecl->type;
68f46862
IB
202 if (global.params.useTypeInfo && Type::dtypeinfo)
203 r->vtinfo = TypeInfoStructDeclaration::create(r); // prevent typeinfo from going to object file
5b74dd0a
IB
204 return r;
205}
206
207/*****************************************
208 * Create the AST for an instantiation of a suitable tuple type.
209 *
210 * Params:
211 * loc = The source location.
212 * type = A Tuple type, created with createTupleType.
213 * e = The expressions we wish to store in the tuple.
214 * Returns:
215 * An AST for the expression `Tuple(e)`.
216 */
217
218static Expression *createTuple(Loc loc, TypeStruct *type, Expressions *e)
219{ // TODO: move to druntime?
220 return new CallExp(loc, new TypeExp(loc, type), e);
221}
222
223/*****************************************
224 * Lower any aggregate that is not an array to an array using a
225 * regular foreach loop within CTFE. If there are multiple
226 * `static foreach` loop variables, an array of tuples is
227 * generated. In thise case, the field `needExpansion` is set to
228 * true to indicate that the static foreach loop expansion will
229 * need to expand the tuples into multiple variables.
230 *
231 * For example, `static foreach (x; range) { ... }` is lowered to:
232 *
233 * static foreach (x; {
234 * typeof({
235 * foreach (x; range) return x;
236 * }())[] __res;
237 * foreach (x; range) __res ~= x;
238 * return __res;
239 * }()) { ... }
240 *
241 * Finally, call `lowerArrayAggregate` to turn the produced
242 * array into an expression tuple.
243 *
244 * Params:
245 * sc = The current scope.
246 */
247
248static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
249{
2cbc99d1 250 size_t nvars = sfe->aggrfe ? sfe->aggrfe->parameters->length : 1;
5b74dd0a
IB
251 Loc aloc = sfe->aggrfe ? sfe->aggrfe->aggr->loc : sfe->rangefe->lwr->loc;
252 // We need three sets of foreach loop variables because the
253 // lowering contains three foreach loops.
254 Parameters *pparams[3] = {new Parameters(), new Parameters(), new Parameters()};
255 for (size_t i = 0; i < nvars; i++)
256 {
257 for (size_t j = 0; j < 3; j++)
258 {
259 Parameters *params = pparams[j];
260 Parameter *p = sfe->aggrfe ? (*sfe->aggrfe->parameters)[i] : sfe->rangefe->prm;
dddea6d4 261 params->push(new Parameter(p->storageClass, p->type, p->ident, NULL, NULL));
5b74dd0a
IB
262 }
263 }
264 Expression *res[2];
265 TypeStruct *tplty = NULL;
266 if (nvars == 1) // only one `static foreach` variable, generate identifiers.
267 {
268 for (size_t i = 0; i < 2; i++)
269 {
270 res[i] = new IdentifierExp(aloc, (*pparams[i])[0]->ident);
271 }
272 }
273 else // multiple `static foreach` variables, generate tuples.
274 {
275 for (size_t i = 0; i < 2; i++)
276 {
277 Expressions *e = new Expressions();
2cbc99d1 278 for (size_t j = 0; j < pparams[0]->length; j++)
5b74dd0a
IB
279 {
280 Parameter *p = (*pparams[i])[j];
281 e->push(new IdentifierExp(aloc, p->ident));
282 }
283 if (!tplty)
284 {
285 tplty = createTupleType(aloc, e);
286 }
287 res[i] = createTuple(aloc, tplty, e);
288 }
289 sfe->needExpansion = true; // need to expand the tuples later
290 }
291 // generate remaining code for the new aggregate which is an
292 // array (see documentation comment).
293 if (sfe->rangefe)
294 {
295 sc = sc->startCTFE();
a3b38b77 296 sfe->rangefe->lwr = expressionSemantic(sfe->rangefe->lwr, sc);
5b74dd0a 297 sfe->rangefe->lwr = resolveProperties(sc, sfe->rangefe->lwr);
a3b38b77 298 sfe->rangefe->upr = expressionSemantic(sfe->rangefe->upr, sc);
5b74dd0a
IB
299 sfe->rangefe->upr = resolveProperties(sc, sfe->rangefe->upr);
300 sc = sc->endCTFE();
301 sfe->rangefe->lwr = sfe->rangefe->lwr->optimize(WANTvalue);
302 sfe->rangefe->lwr = sfe->rangefe->lwr->ctfeInterpret();
303 sfe->rangefe->upr = sfe->rangefe->upr->optimize(WANTvalue);
304 sfe->rangefe->upr = sfe->rangefe->upr->ctfeInterpret();
305 }
306 Statements *s1 = new Statements();
307 Statements *sfebody = new Statements();
308 if (tplty) sfebody->push(new ExpStatement(sfe->loc, tplty->sym));
309 sfebody->push(new ReturnStatement(aloc, res[0]));
310 s1->push(createForeach(sfe, aloc, pparams[0], new CompoundStatement(aloc, sfebody)));
311 s1->push(new ExpStatement(aloc, new AssertExp(aloc, new IntegerExp(aloc, 0, Type::tint32))));
312 Type *ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
313 Type *aty = ety->arrayOf();
314 Identifier *idres = Identifier::generateId("__res");
315 VarDeclaration *vard = new VarDeclaration(aloc, aty, idres, NULL);
316 Statements *s2 = new Statements();
68f46862
IB
317
318 // Run 'typeof' gagged to avoid duplicate errors and if it fails just create
319 // an empty foreach to expose them.
320 unsigned olderrors = global.startGagging();
321 ety = typeSemantic(ety, aloc, sc);
322 if (global.endGagging(olderrors))
323 s2->push(createForeach(sfe, aloc, pparams[1], NULL));
324 else
325 {
326 s2->push(new ExpStatement(aloc, vard));
327 Expression *catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
328 s2->push(createForeach(sfe, aloc, pparams[1], new ExpStatement(aloc, catass)));
329 s2->push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
330 }
ce56fd94
IB
331
332 Expression *aggr;
333 Type *indexty;
334
68f46862 335 if (sfe->rangefe && (indexty = ety)->isintegral())
ce56fd94
IB
336 {
337 sfe->rangefe->lwr->type = indexty;
338 sfe->rangefe->upr->type = indexty;
339 IntRange lwrRange = getIntRange(sfe->rangefe->lwr);
340 IntRange uprRange = getIntRange(sfe->rangefe->upr);
341
342 const dinteger_t lwr = sfe->rangefe->lwr->toInteger();
343 dinteger_t upr = sfe->rangefe->upr->toInteger();
344 size_t length = 0;
345
346 if (lwrRange.imin <= uprRange.imax)
347 length = (size_t)(upr - lwr);
348
349 Expressions *exps = new Expressions();
350 exps->setDim(length);
351
352 if (sfe->rangefe->op == TOKforeach)
353 {
354 for (size_t i = 0; i < length; i++)
355 (*exps)[i] = new IntegerExp(aloc, lwr + i, indexty);
356 }
357 else
358 {
359 --upr;
360 for (size_t i = 0; i < length; i++)
361 (*exps)[i] = new IntegerExp(aloc, upr - i, indexty);
362 }
363 aggr = new ArrayLiteralExp(aloc, indexty->arrayOf(), exps);
364 }
365 else
366 {
367 aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
368 sc = sc->startCTFE();
a3b38b77 369 aggr = expressionSemantic(aggr, sc);
ce56fd94
IB
370 aggr = resolveProperties(sc, aggr);
371 sc = sc->endCTFE();
372 aggr = aggr->optimize(WANTvalue);
373 aggr = aggr->ctfeInterpret();
374 }
5b74dd0a
IB
375
376 assert(!!sfe->aggrfe ^ !!sfe->rangefe);
377 sfe->aggrfe = new ForeachStatement(sfe->loc, TOKforeach, pparams[2], aggr,
378 sfe->aggrfe ? sfe->aggrfe->_body : sfe->rangefe->_body,
379 sfe->aggrfe ? sfe->aggrfe->endloc : sfe->rangefe->endloc);
380 sfe->rangefe = NULL;
381 lowerArrayAggregate(sfe, sc); // finally, turn generated array into expression tuple
382}
383
384/*****************************************
385 * Perform `static foreach` lowerings that are necessary in order
386 * to finally expand the `static foreach` using
387 * `ddmd.statementsem.makeTupleForeach`.
388 */
389
390void staticForeachPrepare(StaticForeach *sfe, Scope *sc)
391{
392 assert(sc);
393 if (sfe->aggrfe)
394 {
395 sc = sc->startCTFE();
a3b38b77 396 sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
5b74dd0a
IB
397 sc = sc->endCTFE();
398 sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
5b74dd0a
IB
399 }
400
401 if (sfe->aggrfe && sfe->aggrfe->aggr->type->toBasetype()->ty == Terror)
402 {
403 return;
404 }
405
406 if (!staticForeachReady(sfe))
407 {
408 if (sfe->aggrfe && sfe->aggrfe->aggr->type->toBasetype()->ty == Tarray)
409 {
410 lowerArrayAggregate(sfe, sc);
411 }
412 else
413 {
414 lowerNonArrayAggregate(sfe, sc);
415 }
416 }
417}
418
419/*****************************************
420 * Returns:
421 * `true` iff ready to call `ddmd.statementsem.makeTupleForeach`.
422 */
423
424bool staticForeachReady(StaticForeach *sfe)
425{
426 return sfe->aggrfe && sfe->aggrfe->aggr && sfe->aggrfe->aggr->type &&
427 sfe->aggrfe->aggr->type->toBasetype()->ty == Ttuple;
428}
429
430/* ============================================================ */
431
b4c522fa
IB
432DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
433 : Condition(Loc())
434{
435 this->mod = mod;
436 this->level = level;
437 this->ident = ident;
438}
439
440Condition *DVCondition::syntaxCopy()
441{
442 return this; // don't need to copy
443}
444
445/* ============================================================ */
446
b4c522fa
IB
447void DebugCondition::addGlobalIdent(const char *ident)
448{
5bc13e52
IB
449 if (!global.debugids)
450 global.debugids = new Identifiers();
451 global.debugids->push(Identifier::idPool(ident));
b4c522fa
IB
452}
453
454
455DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
456 : DVCondition(mod, level, ident)
457{
458}
459
460// Helper for printing dependency information
461void printDepsConditional(Scope *sc, DVCondition* condition, const char* depType)
462{
d8930b13 463 if (!global.params.moduleDeps || global.params.moduleDepsFile.length)
b4c522fa
IB
464 return;
465 OutBuffer *ob = global.params.moduleDeps;
466 Module* imod = sc ? sc->instantiatingModule() : condition->mod;
467 if (!imod)
468 return;
469 ob->writestring(depType);
470 ob->writestring(imod->toPrettyChars());
471 ob->writestring(" (");
472 escapePath(ob, imod->srcfile->toChars());
473 ob->writestring(") : ");
474 if (condition->ident)
475 ob->printf("%s\n", condition->ident->toChars());
476 else
477 ob->printf("%d\n", condition->level);
478}
479
480
d3da83f6 481int DebugCondition::include(Scope *sc)
b4c522fa
IB
482{
483 //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
484 if (inc == 0)
485 {
486 inc = 2;
487 bool definedInModule = false;
488 if (ident)
489 {
490 if (findCondition(mod->debugids, ident))
491 {
492 inc = 1;
493 definedInModule = true;
494 }
5bc13e52 495 else if (findCondition(global.debugids, ident))
b4c522fa
IB
496 inc = 1;
497 else
498 { if (!mod->debugidsNot)
5bc13e52
IB
499 mod->debugidsNot = new Identifiers();
500 mod->debugidsNot->push(ident);
b4c522fa
IB
501 }
502 }
503 else if (level <= global.params.debuglevel || level <= mod->debuglevel)
504 inc = 1;
505 if (!definedInModule)
506 printDepsConditional(sc, this, "depsDebug ");
507 }
508 return (inc == 1);
509}
510
511/* ============================================================ */
512
b4c522fa
IB
513static bool isReserved(const char *ident)
514{
515 static const char* reserved[] =
516 {
517 "DigitalMars",
518 "GNU",
519 "LDC",
520 "SDC",
521 "Windows",
522 "Win32",
523 "Win64",
524 "linux",
525 "OSX",
526 "FreeBSD",
527 "OpenBSD",
528 "NetBSD",
529 "DragonFlyBSD",
530 "BSD",
531 "Solaris",
532 "Posix",
533 "AIX",
534 "Haiku",
535 "SkyOS",
536 "SysV3",
537 "SysV4",
538 "Hurd",
539 "Android",
9503d7b1
IB
540 "PlayStation",
541 "PlayStation4",
b4c522fa
IB
542 "Cygwin",
543 "MinGW",
544 "FreeStanding",
545 "X86",
546 "X86_64",
547 "ARM",
548 "ARM_Thumb",
549 "ARM_SoftFloat",
550 "ARM_SoftFP",
551 "ARM_HardFloat",
552 "AArch64",
553 "Epiphany",
554 "PPC",
555 "PPC_SoftFloat",
556 "PPC_HardFloat",
557 "PPC64",
558 "IA64",
559 "MIPS32",
560 "MIPS64",
561 "MIPS_O32",
562 "MIPS_N32",
563 "MIPS_O64",
564 "MIPS_N64",
565 "MIPS_EABI",
566 "MIPS_SoftFloat",
567 "MIPS_HardFloat",
9503d7b1 568 "MSP430",
b4c522fa
IB
569 "NVPTX",
570 "NVPTX64",
9503d7b1
IB
571 "RISCV32",
572 "RISCV64",
b4c522fa
IB
573 "SPARC",
574 "SPARC_V8Plus",
575 "SPARC_SoftFloat",
576 "SPARC_HardFloat",
577 "SPARC64",
578 "S390",
579 "S390X",
580 "HPPA",
581 "HPPA64",
582 "SH",
583 "Alpha",
584 "Alpha_SoftFloat",
585 "Alpha_HardFloat",
586 "LittleEndian",
587 "BigEndian",
588 "ELFv1",
589 "ELFv2",
590 "CRuntime_Digitalmars",
591 "CRuntime_Glibc",
592 "CRuntime_Microsoft",
9503d7b1
IB
593 "CRuntime_Musl",
594 "CRuntime_UClibc",
595 "CppRuntime_Clang",
596 "CppRuntime_DigitalMars",
597 "CppRuntime_Gcc",
598 "CppRuntime_Microsoft",
599 "CppRuntime_Sun",
b4c522fa
IB
600 "D_Coverage",
601 "D_Ddoc",
602 "D_InlineAsm_X86",
603 "D_InlineAsm_X86_64",
604 "D_LP64",
605 "D_X32",
606 "D_HardFloat",
607 "D_SoftFloat",
608 "D_PIC",
609 "D_SIMD",
610 "D_Version2",
611 "D_NoBoundsChecks",
612 "unittest",
613 "assert",
614 "all",
615 "none",
616 NULL
617 };
618
619 for (unsigned i = 0; reserved[i]; i++)
620 {
621 if (strcmp(ident, reserved[i]) == 0)
622 return true;
623 }
624
625 if (ident[0] == 'D' && ident[1] == '_')
626 return true;
627 return false;
628}
629
630void checkReserved(Loc loc, const char *ident)
631{
632 if (isReserved(ident))
a3b38b77 633 error(loc, "version identifier `%s` is reserved and cannot be set", ident);
b4c522fa
IB
634}
635
636void VersionCondition::addGlobalIdent(const char *ident)
637{
638 checkReserved(Loc(), ident);
639 addPredefinedGlobalIdent(ident);
640}
641
642void VersionCondition::addPredefinedGlobalIdent(const char *ident)
643{
5bc13e52
IB
644 if (!global.versionids)
645 global.versionids = new Identifiers();
646 global.versionids->push(Identifier::idPool(ident));
b4c522fa
IB
647}
648
649
650VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
651 : DVCondition(mod, level, ident)
652{
653}
654
d3da83f6 655int VersionCondition::include(Scope *sc)
b4c522fa
IB
656{
657 //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
658 //if (ident) printf("\tident = '%s'\n", ident->toChars());
659 if (inc == 0)
660 {
661 inc = 2;
662 bool definedInModule=false;
663 if (ident)
664 {
665 if (findCondition(mod->versionids, ident))
666 {
667 inc = 1;
668 definedInModule = true;
669 }
5bc13e52 670 else if (findCondition(global.versionids, ident))
b4c522fa
IB
671 inc = 1;
672 else
673 {
674 if (!mod->versionidsNot)
5bc13e52
IB
675 mod->versionidsNot = new Identifiers();
676 mod->versionidsNot->push(ident);
b4c522fa
IB
677 }
678 }
679 else if (level <= global.params.versionlevel || level <= mod->versionlevel)
680 inc = 1;
681 if (!definedInModule && (!ident || (!isReserved(ident->toChars()) && ident != Id::_unittest && ident != Id::_assert)))
682 printDepsConditional(sc, this, "depsVersion ");
683 }
684 return (inc == 1);
685}
686
687/**************************** StaticIfCondition *******************************/
688
689StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
690 : Condition(loc)
691{
692 this->exp = exp;
b4c522fa
IB
693}
694
695Condition *StaticIfCondition::syntaxCopy()
696{
697 return new StaticIfCondition(loc, exp->syntaxCopy());
698}
699
d3da83f6 700int StaticIfCondition::include(Scope *sc)
b4c522fa
IB
701{
702 if (inc == 0)
703 {
b4c522fa
IB
704 if (!sc)
705 {
706 error(loc, "static if conditional cannot be at global scope");
707 inc = 2;
708 return 0;
709 }
710
b4c522fa 711 sc = sc->push(sc->scopesym);
b4c522fa
IB
712
713 bool errors = false;
27d8c351
IB
714
715 if (!exp)
716 goto Lerror;
717
b4c522fa
IB
718 bool result = evalStaticCondition(sc, exp, exp, errors);
719 sc->pop();
b4c522fa
IB
720
721 // Prevent repeated condition evaluation.
722 // See: fail_compilation/fail7815.d
723 if (inc != 0)
724 return (inc == 1);
725 if (errors)
726 goto Lerror;
727 if (result)
728 inc = 1;
729 else
730 inc = 2;
731 }
732 return (inc == 1);
733
734Lerror:
735 if (!global.gag)
736 inc = 2; // so we don't see the error message again
737 return 0;
738}