]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/cond.c
Merge dmd upstream 6d5b853d3
[thirdparty/gcc.git] / gcc / d / dmd / cond.c
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/cond.c
9 */
10
11 #include "root/dsystem.h" // strcmp()
12
13 #include "mars.h"
14 #include "id.h"
15 #include "init.h"
16 #include "declaration.h"
17 #include "identifier.h"
18 #include "expression.h"
19 #include "cond.h"
20 #include "module.h"
21 #include "template.h"
22 #include "mtype.h"
23 #include "scope.h"
24 #include "arraytypes.h"
25 #include "tokens.h"
26
27 Expression *semantic(Expression *e, Scope *sc);
28 bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors);
29
30 int findCondition(Strings *ids, Identifier *ident)
31 {
32 if (ids)
33 {
34 for (size_t i = 0; i < ids->dim; i++)
35 {
36 const char *id = (*ids)[i];
37
38 if (strcmp(id, ident->toChars()) == 0)
39 return true;
40 }
41 }
42
43 return false;
44 }
45
46 /* ============================================================ */
47
48 Condition::Condition(Loc loc)
49 {
50 this->loc = loc;
51 inc = 0;
52 }
53
54 /* ============================================================ */
55
56 DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
57 : Condition(Loc())
58 {
59 this->mod = mod;
60 this->level = level;
61 this->ident = ident;
62 }
63
64 Condition *DVCondition::syntaxCopy()
65 {
66 return this; // don't need to copy
67 }
68
69 /* ============================================================ */
70
71 void DebugCondition::setGlobalLevel(unsigned level)
72 {
73 global.params.debuglevel = level;
74 }
75
76 void DebugCondition::addGlobalIdent(const char *ident)
77 {
78 if (!global.params.debugids)
79 global.params.debugids = new Strings();
80 global.params.debugids->push(ident);
81 }
82
83
84 DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
85 : DVCondition(mod, level, ident)
86 {
87 }
88
89 // Helper for printing dependency information
90 void printDepsConditional(Scope *sc, DVCondition* condition, const char* depType)
91 {
92 if (!global.params.moduleDeps || global.params.moduleDepsFile)
93 return;
94 OutBuffer *ob = global.params.moduleDeps;
95 Module* imod = sc ? sc->instantiatingModule() : condition->mod;
96 if (!imod)
97 return;
98 ob->writestring(depType);
99 ob->writestring(imod->toPrettyChars());
100 ob->writestring(" (");
101 escapePath(ob, imod->srcfile->toChars());
102 ob->writestring(") : ");
103 if (condition->ident)
104 ob->printf("%s\n", condition->ident->toChars());
105 else
106 ob->printf("%d\n", condition->level);
107 }
108
109
110 int DebugCondition::include(Scope *sc, ScopeDsymbol *)
111 {
112 //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
113 if (inc == 0)
114 {
115 inc = 2;
116 bool definedInModule = false;
117 if (ident)
118 {
119 if (findCondition(mod->debugids, ident))
120 {
121 inc = 1;
122 definedInModule = true;
123 }
124 else if (findCondition(global.params.debugids, ident))
125 inc = 1;
126 else
127 { if (!mod->debugidsNot)
128 mod->debugidsNot = new Strings();
129 mod->debugidsNot->push(ident->toChars());
130 }
131 }
132 else if (level <= global.params.debuglevel || level <= mod->debuglevel)
133 inc = 1;
134 if (!definedInModule)
135 printDepsConditional(sc, this, "depsDebug ");
136 }
137 return (inc == 1);
138 }
139
140 /* ============================================================ */
141
142 void VersionCondition::setGlobalLevel(unsigned level)
143 {
144 global.params.versionlevel = level;
145 }
146
147 static bool isReserved(const char *ident)
148 {
149 static const char* reserved[] =
150 {
151 "DigitalMars",
152 "GNU",
153 "LDC",
154 "SDC",
155 "Windows",
156 "Win32",
157 "Win64",
158 "linux",
159 "OSX",
160 "FreeBSD",
161 "OpenBSD",
162 "NetBSD",
163 "DragonFlyBSD",
164 "BSD",
165 "Solaris",
166 "Posix",
167 "AIX",
168 "Haiku",
169 "SkyOS",
170 "SysV3",
171 "SysV4",
172 "Hurd",
173 "Android",
174 "Cygwin",
175 "MinGW",
176 "FreeStanding",
177 "X86",
178 "X86_64",
179 "ARM",
180 "ARM_Thumb",
181 "ARM_SoftFloat",
182 "ARM_SoftFP",
183 "ARM_HardFloat",
184 "AArch64",
185 "Epiphany",
186 "PPC",
187 "PPC_SoftFloat",
188 "PPC_HardFloat",
189 "PPC64",
190 "IA64",
191 "MIPS32",
192 "MIPS64",
193 "MIPS_O32",
194 "MIPS_N32",
195 "MIPS_O64",
196 "MIPS_N64",
197 "MIPS_EABI",
198 "MIPS_SoftFloat",
199 "MIPS_HardFloat",
200 "NVPTX",
201 "NVPTX64",
202 "SPARC",
203 "SPARC_V8Plus",
204 "SPARC_SoftFloat",
205 "SPARC_HardFloat",
206 "SPARC64",
207 "S390",
208 "S390X",
209 "HPPA",
210 "HPPA64",
211 "SH",
212 "Alpha",
213 "Alpha_SoftFloat",
214 "Alpha_HardFloat",
215 "LittleEndian",
216 "BigEndian",
217 "ELFv1",
218 "ELFv2",
219 "CRuntime_Digitalmars",
220 "CRuntime_Glibc",
221 "CRuntime_Microsoft",
222 "D_Coverage",
223 "D_Ddoc",
224 "D_InlineAsm_X86",
225 "D_InlineAsm_X86_64",
226 "D_LP64",
227 "D_X32",
228 "D_HardFloat",
229 "D_SoftFloat",
230 "D_PIC",
231 "D_SIMD",
232 "D_Version2",
233 "D_NoBoundsChecks",
234 "unittest",
235 "assert",
236 "all",
237 "none",
238 NULL
239 };
240
241 for (unsigned i = 0; reserved[i]; i++)
242 {
243 if (strcmp(ident, reserved[i]) == 0)
244 return true;
245 }
246
247 if (ident[0] == 'D' && ident[1] == '_')
248 return true;
249 return false;
250 }
251
252 void checkReserved(Loc loc, const char *ident)
253 {
254 if (isReserved(ident))
255 error(loc, "version identifier '%s' is reserved and cannot be set", ident);
256 }
257
258 void VersionCondition::addGlobalIdent(const char *ident)
259 {
260 checkReserved(Loc(), ident);
261 addPredefinedGlobalIdent(ident);
262 }
263
264 void VersionCondition::addPredefinedGlobalIdent(const char *ident)
265 {
266 if (!global.params.versionids)
267 global.params.versionids = new Strings();
268 global.params.versionids->push(ident);
269 }
270
271
272 VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident)
273 : DVCondition(mod, level, ident)
274 {
275 }
276
277 int VersionCondition::include(Scope *sc, ScopeDsymbol *)
278 {
279 //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
280 //if (ident) printf("\tident = '%s'\n", ident->toChars());
281 if (inc == 0)
282 {
283 inc = 2;
284 bool definedInModule=false;
285 if (ident)
286 {
287 if (findCondition(mod->versionids, ident))
288 {
289 inc = 1;
290 definedInModule = true;
291 }
292 else if (findCondition(global.params.versionids, ident))
293 inc = 1;
294 else
295 {
296 if (!mod->versionidsNot)
297 mod->versionidsNot = new Strings();
298 mod->versionidsNot->push(ident->toChars());
299 }
300 }
301 else if (level <= global.params.versionlevel || level <= mod->versionlevel)
302 inc = 1;
303 if (!definedInModule && (!ident || (!isReserved(ident->toChars()) && ident != Id::_unittest && ident != Id::_assert)))
304 printDepsConditional(sc, this, "depsVersion ");
305 }
306 return (inc == 1);
307 }
308
309 /**************************** StaticIfCondition *******************************/
310
311 StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
312 : Condition(loc)
313 {
314 this->exp = exp;
315 this->nest = 0;
316 }
317
318 Condition *StaticIfCondition::syntaxCopy()
319 {
320 return new StaticIfCondition(loc, exp->syntaxCopy());
321 }
322
323 int StaticIfCondition::include(Scope *sc, ScopeDsymbol *sds)
324 {
325 if (inc == 0)
326 {
327 if (exp->op == TOKerror || nest > 100)
328 {
329 error(loc, (nest > 1000) ? "unresolvable circular static if expression"
330 : "error evaluating static if expression");
331 goto Lerror;
332 }
333
334 if (!sc)
335 {
336 error(loc, "static if conditional cannot be at global scope");
337 inc = 2;
338 return 0;
339 }
340
341 ++nest;
342 sc = sc->push(sc->scopesym);
343 sc->sds = sds; // sds gets any addMember()
344
345 bool errors = false;
346 bool result = evalStaticCondition(sc, exp, exp, errors);
347 sc->pop();
348 --nest;
349
350 // Prevent repeated condition evaluation.
351 // See: fail_compilation/fail7815.d
352 if (inc != 0)
353 return (inc == 1);
354 if (errors)
355 goto Lerror;
356 if (result)
357 inc = 1;
358 else
359 inc = 2;
360 }
361 return (inc == 1);
362
363 Lerror:
364 if (!global.gag)
365 inc = 2; // so we don't see the error message again
366 return 0;
367 }