Mercurial > projects > ldc
annotate dmd/cond.c @ 650:aa6a0b7968f7
Added test case for bug #100
Removed dubious check for not emitting static private global in other modules without access. This should be handled properly somewhere else, it's causing unresolved global errors for stuff that should work (in MiniD)
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 05 Oct 2008 17:28:15 +0200 |
parents | 23538d0f0d5b |
children | eef8ac26c66c |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2006 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <assert.h> | |
13 | |
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 "lexer.h" | |
23 #ifdef _DH | |
24 #include "mtype.h" | |
25 #include "scope.h" | |
26 #endif | |
27 | |
28 int findCondition(Array *ids, Identifier *ident) | |
29 { | |
30 if (ids) | |
31 { | |
32 for (int i = 0; i < ids->dim; i++) | |
33 { | |
34 char *id = (char *)ids->data[i]; | |
35 | |
36 if (strcmp(id, ident->toChars()) == 0) | |
37 return TRUE; | |
38 } | |
39 } | |
40 | |
41 return FALSE; | |
42 } | |
43 | |
44 /* ============================================================ */ | |
45 | |
46 Condition::Condition(Loc loc) | |
47 { | |
48 this->loc = loc; | |
49 inc = 0; | |
50 } | |
51 | |
52 /* ============================================================ */ | |
53 | |
54 DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident) | |
55 : Condition(0) | |
56 { | |
57 this->mod = mod; | |
58 this->level = level; | |
59 this->ident = ident; | |
60 } | |
61 | |
62 Condition *DVCondition::syntaxCopy() | |
63 { | |
64 return this; // don't need to copy | |
65 } | |
66 | |
67 /* ============================================================ */ | |
68 | |
69 void DebugCondition::setGlobalLevel(unsigned level) | |
70 { | |
71 global.params.debuglevel = level; | |
72 } | |
73 | |
74 void DebugCondition::addGlobalIdent(char *ident) | |
75 { | |
76 if (!global.params.debugids) | |
77 global.params.debugids = new Array(); | |
78 global.params.debugids->push(ident); | |
79 } | |
80 | |
81 | |
82 DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident) | |
83 : DVCondition(mod, level, ident) | |
84 { | |
85 } | |
86 | |
87 int DebugCondition::include(Scope *sc, ScopeDsymbol *s) | |
88 { | |
89 //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); | |
90 if (inc == 0) | |
91 { | |
92 inc = 2; | |
93 if (ident) | |
94 { | |
95 if (findCondition(mod->debugids, ident)) | |
96 inc = 1; | |
97 else if (findCondition(global.params.debugids, ident)) | |
98 inc = 1; | |
99 else | |
100 { if (!mod->debugidsNot) | |
101 mod->debugidsNot = new Array(); | |
102 mod->debugidsNot->push(ident->toChars()); | |
103 } | |
104 } | |
105 else if (level <= global.params.debuglevel || level <= mod->debuglevel) | |
106 inc = 1; | |
107 } | |
108 return (inc == 1); | |
109 } | |
110 | |
111 void DebugCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
112 { | |
113 if (ident) | |
114 buf->printf("debug (%s)", ident->toChars()); | |
115 else | |
116 buf->printf("debug (%u)", level); | |
117 } | |
118 | |
119 /* ============================================================ */ | |
120 | |
121 void VersionCondition::setGlobalLevel(unsigned level) | |
122 { | |
123 global.params.versionlevel = level; | |
124 } | |
125 | |
126 void VersionCondition::checkPredefined(Loc loc, char *ident) | |
127 { | |
128 static char* reserved[] = | |
129 { | |
445
cc40db549aea
Changed the handling of variadic intrinsics a bit.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
275
diff
changeset
|
130 "DigitalMars", "LLVM", "LLVMDC", "LLVM64", |
275
665b81613475
[svn r296] Removed: the 'suite' dir, it never took off!
lindquist
parents:
1
diff
changeset
|
131 "X86", "X86_64", "PPC", "PPC64", |
1 | 132 "Windows", "Win32", "Win64", |
587
23538d0f0d5b
Fixed a few mini tests issues.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
445
diff
changeset
|
133 "linux", "darwin", "Posix", |
1 | 134 "LittleEndian", "BigEndian", |
135 "all", | |
136 "none", | |
137 }; | |
138 | |
139 for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) | |
140 { | |
141 if (strcmp(ident, reserved[i]) == 0) | |
142 goto Lerror; | |
143 } | |
144 | |
145 if (ident[0] == 'D' && ident[1] == '_') | |
146 goto Lerror; | |
147 | |
148 return; | |
149 | |
150 Lerror: | |
151 error(loc, "version identifier '%s' is reserved and cannot be set", ident); | |
152 } | |
153 | |
154 void VersionCondition::addGlobalIdent(char *ident) | |
155 { | |
156 checkPredefined(0, ident); | |
157 addPredefinedGlobalIdent(ident); | |
158 } | |
159 | |
160 void VersionCondition::addPredefinedGlobalIdent(char *ident) | |
161 { | |
162 if (!global.params.versionids) | |
163 global.params.versionids = new Array(); | |
164 global.params.versionids->push(ident); | |
165 } | |
166 | |
167 | |
168 VersionCondition::VersionCondition(Module *mod, unsigned level, Identifier *ident) | |
169 : DVCondition(mod, level, ident) | |
170 { | |
171 } | |
172 | |
173 int VersionCondition::include(Scope *sc, ScopeDsymbol *s) | |
174 { | |
175 //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); | |
176 //if (ident) printf("\tident = '%s'\n", ident->toChars()); | |
177 if (inc == 0) | |
178 { | |
179 inc = 2; | |
180 if (ident) | |
181 { | |
182 if (findCondition(mod->versionids, ident)) | |
183 inc = 1; | |
184 else if (findCondition(global.params.versionids, ident)) | |
185 inc = 1; | |
186 else | |
187 { | |
188 if (!mod->versionidsNot) | |
189 mod->versionidsNot = new Array(); | |
190 mod->versionidsNot->push(ident->toChars()); | |
191 } | |
192 } | |
193 else if (level <= global.params.versionlevel || level <= mod->versionlevel) | |
194 inc = 1; | |
195 } | |
196 return (inc == 1); | |
197 } | |
198 | |
199 void VersionCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
200 { | |
201 if (ident) | |
202 buf->printf("version (%s)", ident->toChars()); | |
203 else | |
204 buf->printf("version (%u)", level); | |
205 } | |
206 | |
207 | |
208 /**************************** StaticIfCondition *******************************/ | |
209 | |
210 StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp) | |
211 : Condition(loc) | |
212 { | |
213 this->exp = exp; | |
214 } | |
215 | |
216 Condition *StaticIfCondition::syntaxCopy() | |
217 { | |
218 return new StaticIfCondition(loc, exp->syntaxCopy()); | |
219 } | |
220 | |
221 int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) | |
222 { | |
223 #if 0 | |
224 printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s); | |
225 if (s) | |
226 { | |
227 printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind()); | |
228 } | |
229 #endif | |
230 if (inc == 0) | |
231 { | |
232 if (!sc) | |
233 { | |
234 error(loc, "static if conditional cannot be at global scope"); | |
235 inc = 2; | |
236 return 0; | |
237 } | |
238 | |
239 sc = sc->push(sc->scopesym); | |
240 sc->sd = s; // s gets any addMember() | |
241 sc->flags |= SCOPEstaticif; | |
242 Expression *e = exp->semantic(sc); | |
243 sc->pop(); | |
244 e = e->optimize(WANTvalue | WANTinterpret); | |
245 if (e->isBool(TRUE)) | |
246 inc = 1; | |
247 else if (e->isBool(FALSE)) | |
248 inc = 2; | |
249 else | |
250 { | |
251 e->error("expression %s is not constant or does not evaluate to a bool", e->toChars()); | |
252 inc = 2; | |
253 } | |
254 } | |
255 return (inc == 1); | |
256 } | |
257 | |
258 void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
259 { | |
260 buf->writestring("static if("); | |
261 exp->toCBuffer(buf, hgs); | |
262 buf->writeByte(')'); | |
263 } | |
264 | |
265 | |
266 /**************************** IftypeCondition *******************************/ | |
267 | |
268 IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec) | |
269 : Condition(loc) | |
270 { | |
271 this->targ = targ; | |
272 this->id = id; | |
273 this->tok = tok; | |
274 this->tspec = tspec; | |
275 } | |
276 | |
277 Condition *IftypeCondition::syntaxCopy() | |
278 { | |
279 return new IftypeCondition(loc, | |
280 targ->syntaxCopy(), | |
281 id, | |
282 tok, | |
283 tspec ? tspec->syntaxCopy() : NULL); | |
284 } | |
285 | |
286 int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) | |
287 { | |
288 //printf("IftypeCondition::include()\n"); | |
289 if (inc == 0) | |
290 { | |
291 if (!sc) | |
292 { | |
293 error(loc, "iftype conditional cannot be at global scope"); | |
294 inc = 2; | |
295 return 0; | |
296 } | |
297 unsigned errors = global.errors; | |
298 global.gag++; // suppress printing of error messages | |
299 targ = targ->semantic(loc, sc); | |
300 global.gag--; | |
301 if (errors != global.errors) // if any errors happened | |
302 { inc = 2; // then condition is false | |
303 global.errors = errors; | |
304 } | |
305 else if (id && tspec) | |
306 { | |
307 /* Evaluate to TRUE if targ matches tspec. | |
308 * If TRUE, declare id as an alias for the specialized type. | |
309 */ | |
310 | |
311 MATCH m; | |
312 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
313 | |
314 TemplateParameters parameters; | |
315 parameters.setDim(1); | |
316 parameters.data[0] = (void *)&tp; | |
317 | |
318 Objects dedtypes; | |
319 dedtypes.setDim(1); | |
320 | |
321 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
322 if (m == MATCHnomatch || | |
323 (m != MATCHexact && tok == TOKequal)) | |
324 inc = 2; | |
325 else | |
326 { | |
327 inc = 1; | |
328 Type *tded = (Type *)dedtypes.data[0]; | |
329 if (!tded) | |
330 tded = targ; | |
331 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
332 s->semantic(sc); | |
333 sc->insert(s); | |
334 if (sd) | |
335 s->addMember(sc, sd, 1); | |
336 } | |
337 } | |
338 else if (id) | |
339 { | |
340 /* Declare id as an alias for type targ. Evaluate to TRUE | |
341 */ | |
342 Dsymbol *s = new AliasDeclaration(loc, id, targ); | |
343 s->semantic(sc); | |
344 sc->insert(s); | |
345 if (sd) | |
346 s->addMember(sc, sd, 1); | |
347 inc = 1; | |
348 } | |
349 else if (tspec) | |
350 { | |
351 /* Evaluate to TRUE if targ matches tspec | |
352 */ | |
353 tspec = tspec->semantic(loc, sc); | |
354 //printf("targ = %s\n", targ->toChars()); | |
355 //printf("tspec = %s\n", tspec->toChars()); | |
356 if (tok == TOKcolon) | |
357 { if (targ->implicitConvTo(tspec)) | |
358 inc = 1; | |
359 else | |
360 inc = 2; | |
361 } | |
362 else /* == */ | |
363 { if (targ->equals(tspec)) | |
364 inc = 1; | |
365 else | |
366 inc = 2; | |
367 } | |
368 } | |
369 else | |
370 inc = 1; | |
371 //printf("inc = %d\n", inc); | |
372 } | |
373 return (inc == 1); | |
374 } | |
375 | |
376 void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
377 { | |
378 buf->writestring("iftype("); | |
379 targ->toCBuffer(buf, id, hgs); | |
380 if (tspec) | |
381 { | |
382 if (tok == TOKcolon) | |
383 buf->writestring(" : "); | |
384 else | |
385 buf->writestring(" == "); | |
386 tspec->toCBuffer(buf, NULL, hgs); | |
387 } | |
388 buf->writeByte(')'); | |
389 } | |
390 | |
391 |