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