Mercurial > projects > ldc
annotate dmd/access.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | eeb8b95ea92e |
children | eb7cb41ee585 |
rev | line source |
---|---|
336 | 1 |
2 // Copyright (c) 1999-2006 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <assert.h> | |
14 | |
15 #include "root.h" | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
16 #include "rmem.h" |
336 | 17 |
18 #include "enum.h" | |
19 #include "aggregate.h" | |
20 #include "init.h" | |
21 #include "attrib.h" | |
22 #include "scope.h" | |
23 #include "id.h" | |
24 #include "mtype.h" | |
25 #include "declaration.h" | |
26 #include "aggregate.h" | |
27 #include "expression.h" | |
28 #include "module.h" | |
29 | |
30 #define LOG 0 | |
31 | |
32 /* Code to do access checks | |
33 */ | |
34 | |
35 int hasPackageAccess(Scope *sc, Dsymbol *s); | |
36 | |
37 /**************************************** | |
38 * Return PROT access for Dsymbol smember in this declaration. | |
39 */ | |
40 | |
41 enum PROT AggregateDeclaration::getAccess(Dsymbol *smember) | |
42 { | |
43 return PROTpublic; | |
44 } | |
45 | |
46 enum PROT StructDeclaration::getAccess(Dsymbol *smember) | |
47 { | |
48 enum PROT access_ret = PROTnone; | |
49 | |
50 #if LOG | |
51 printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n", | |
52 toChars(), smember->toChars()); | |
53 #endif | |
54 if (smember->toParent() == this) | |
55 { | |
56 access_ret = smember->prot(); | |
57 } | |
58 else if (smember->isDeclaration()->isStatic()) | |
59 { | |
60 access_ret = smember->prot(); | |
61 } | |
62 return access_ret; | |
63 } | |
64 | |
65 enum PROT ClassDeclaration::getAccess(Dsymbol *smember) | |
66 { | |
67 enum PROT access_ret = PROTnone; | |
68 | |
69 #if LOG | |
70 printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n", | |
71 toChars(), smember->toChars()); | |
72 #endif | |
73 if (smember->toParent() == this) | |
74 { | |
75 access_ret = smember->prot(); | |
76 } | |
77 else | |
78 { | |
79 enum PROT access; | |
80 int i; | |
81 | |
82 if (smember->isDeclaration()->isStatic()) | |
83 { | |
84 access_ret = smember->prot(); | |
85 } | |
86 | |
87 for (i = 0; i < baseclasses.dim; i++) | |
88 { BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
89 | |
90 access = b->base->getAccess(smember); | |
91 switch (access) | |
92 { | |
93 case PROTnone: | |
94 break; | |
95 | |
96 case PROTprivate: | |
97 access = PROTnone; // private members of base class not accessible | |
98 break; | |
99 | |
100 case PROTpackage: | |
101 case PROTprotected: | |
102 case PROTpublic: | |
103 case PROTexport: | |
104 // If access is to be tightened | |
105 if (b->protection < access) | |
106 access = b->protection; | |
107 | |
108 // Pick path with loosest access | |
109 if (access > access_ret) | |
110 access_ret = access; | |
111 break; | |
112 | |
113 default: | |
114 assert(0); | |
115 } | |
116 } | |
117 } | |
118 #if LOG | |
119 printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n", | |
120 toChars(), smember->toChars(), access_ret); | |
121 #endif | |
122 return access_ret; | |
123 } | |
124 | |
125 /******************************************************** | |
126 * Helper function for ClassDeclaration::accessCheck() | |
127 * Returns: | |
128 * 0 no access | |
129 * 1 access | |
130 */ | |
131 | |
132 static int accessCheckX( | |
133 Dsymbol *smember, | |
134 Dsymbol *sfunc, | |
135 AggregateDeclaration *dthis, | |
136 AggregateDeclaration *cdscope) | |
137 { | |
138 assert(dthis); | |
139 | |
140 #if 0 | |
141 printf("accessCheckX for %s.%s in function %s() in scope %s\n", | |
142 dthis->toChars(), smember->toChars(), | |
143 sfunc ? sfunc->toChars() : "NULL", | |
144 cdscope ? cdscope->toChars() : "NULL"); | |
145 #endif | |
146 if (dthis->hasPrivateAccess(sfunc) || | |
147 dthis->isFriendOf(cdscope)) | |
148 { | |
149 if (smember->toParent() == dthis) | |
150 return 1; | |
151 else | |
152 { | |
153 ClassDeclaration *cdthis = dthis->isClassDeclaration(); | |
154 if (cdthis) | |
155 { | |
156 for (int i = 0; i < cdthis->baseclasses.dim; i++) | |
157 { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; | |
158 enum PROT access; | |
159 | |
160 access = b->base->getAccess(smember); | |
161 if (access >= PROTprotected || | |
162 accessCheckX(smember, sfunc, b->base, cdscope) | |
163 ) | |
164 return 1; | |
165 | |
166 } | |
167 } | |
168 } | |
169 } | |
170 else | |
171 { | |
172 if (smember->toParent() != dthis) | |
173 { | |
174 ClassDeclaration *cdthis = dthis->isClassDeclaration(); | |
175 if (cdthis) | |
176 { | |
177 for (int i = 0; i < cdthis->baseclasses.dim; i++) | |
178 { BaseClass *b = (BaseClass *)cdthis->baseclasses.data[i]; | |
179 | |
180 if (accessCheckX(smember, sfunc, b->base, cdscope)) | |
181 return 1; | |
182 } | |
183 } | |
184 } | |
185 } | |
186 return 0; | |
187 } | |
188 | |
189 /******************************* | |
190 * Do access check for member of this class, this class being the | |
191 * type of the 'this' pointer used to access smember. | |
192 */ | |
193 | |
194 void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) | |
195 { | |
196 int result; | |
197 | |
198 FuncDeclaration *f = sc->func; | |
199 AggregateDeclaration *cdscope = sc->getStructClassScope(); | |
200 enum PROT access; | |
201 | |
202 #if LOG | |
203 printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", | |
204 toChars(), smember->toChars(), | |
205 f ? f->toChars() : NULL, | |
206 cdscope ? cdscope->toChars() : NULL); | |
207 #endif | |
208 | |
209 Dsymbol *smemberparent = smember->toParent(); | |
210 if (!smemberparent || !smemberparent->isAggregateDeclaration()) | |
211 { | |
212 #if LOG | |
213 printf("not an aggregate member\n"); | |
214 #endif | |
215 return; // then it is accessible | |
216 } | |
217 | |
218 // BUG: should enable this check | |
219 //assert(smember->parent->isBaseOf(this, NULL)); | |
220 | |
221 if (smemberparent == this) | |
222 { enum PROT access = smember->prot(); | |
223 | |
224 result = access >= PROTpublic || | |
225 hasPrivateAccess(f) || | |
226 isFriendOf(cdscope) || | |
227 (access == PROTpackage && hasPackageAccess(sc, this)); | |
228 #if LOG | |
229 printf("result1 = %d\n", result); | |
230 #endif | |
231 } | |
232 else if ((access = this->getAccess(smember)) >= PROTpublic) | |
233 { | |
234 result = 1; | |
235 #if LOG | |
236 printf("result2 = %d\n", result); | |
237 #endif | |
238 } | |
239 else if (access == PROTpackage && hasPackageAccess(sc, this)) | |
240 { | |
241 result = 1; | |
242 #if LOG | |
243 printf("result3 = %d\n", result); | |
244 #endif | |
245 } | |
246 else | |
247 { | |
248 result = accessCheckX(smember, f, this, cdscope); | |
249 #if LOG | |
250 printf("result4 = %d\n", result); | |
251 #endif | |
252 } | |
253 if (!result) | |
254 { | |
255 error(loc, "member %s is not accessible", smember->toChars()); | |
256 halt(); | |
257 } | |
258 } | |
259 | |
1133
eeb8b95ea92e
Cleanup DMD 1.041 merge.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1103
diff
changeset
|
260 /**************************************** |
336 | 261 * Determine if this is the same or friend of cd. |
262 */ | |
263 | |
264 int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd) | |
265 { | |
266 #if LOG | |
267 printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null"); | |
268 #endif | |
269 if (this == cd) | |
270 return 1; | |
271 | |
272 // Friends if both are in the same module | |
273 //if (toParent() == cd->toParent()) | |
274 if (cd && getModule() == cd->getModule()) | |
275 { | |
276 #if LOG | |
277 printf("\tin same module\n"); | |
278 #endif | |
279 return 1; | |
280 } | |
281 | |
282 #if LOG | |
283 printf("\tnot friend\n"); | |
284 #endif | |
285 return 0; | |
286 } | |
287 | |
288 /**************************************** | |
289 * Determine if scope sc has package level access to s. | |
290 */ | |
291 | |
292 int hasPackageAccess(Scope *sc, Dsymbol *s) | |
293 { | |
294 #if LOG | |
295 printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc); | |
296 #endif | |
297 | |
298 for (; s; s = s->parent) | |
299 { | |
300 if (s->isPackage() && !s->isModule()) | |
301 break; | |
302 } | |
303 #if LOG | |
304 if (s) | |
305 printf("\tthis is in package '%s'\n", s->toChars()); | |
306 #endif | |
307 | |
308 if (s && s == sc->module->parent) | |
309 { | |
310 #if LOG | |
311 printf("\ts is in same package as sc\n"); | |
312 #endif | |
313 return 1; | |
314 } | |
315 | |
316 | |
317 #if LOG | |
318 printf("\tno package access\n"); | |
319 #endif | |
320 return 0; | |
321 } | |
322 | |
323 /********************************** | |
324 * Determine if smember has access to private members of this declaration. | |
325 */ | |
326 | |
327 int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember) | |
328 { | |
329 if (smember) | |
330 { AggregateDeclaration *cd = NULL; | |
331 Dsymbol *smemberparent = smember->toParent(); | |
332 if (smemberparent) | |
333 cd = smemberparent->isAggregateDeclaration(); | |
334 | |
335 #if LOG | |
336 printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n", | |
337 toChars(), smember->toChars()); | |
338 #endif | |
339 | |
340 if (this == cd) // smember is a member of this class | |
341 { | |
342 #if LOG | |
343 printf("\tyes 1\n"); | |
344 #endif | |
345 return 1; // so we get private access | |
346 } | |
347 | |
348 // If both are members of the same module, grant access | |
349 while (1) | |
350 { Dsymbol *sp = smember->toParent(); | |
351 if (sp->isFuncDeclaration() && smember->isFuncDeclaration()) | |
352 smember = sp; | |
353 else | |
354 break; | |
355 } | |
356 if (!cd && toParent() == smember->toParent()) | |
357 { | |
358 #if LOG | |
359 printf("\tyes 2\n"); | |
360 #endif | |
361 return 1; | |
362 } | |
363 if (!cd && getModule() == smember->getModule()) | |
364 { | |
365 #if LOG | |
366 printf("\tyes 3\n"); | |
367 #endif | |
368 return 1; | |
369 } | |
370 } | |
371 #if LOG | |
372 printf("\tno\n"); | |
373 #endif | |
374 return 0; | |
375 } | |
376 | |
377 /**************************************** | |
378 * Check access to d for expression e.d | |
379 */ | |
380 | |
381 void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d) | |
382 { | |
383 #if LOG | |
384 if (e) | |
385 { printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars()); | |
386 printf("\te->type = %s\n", e->type->toChars()); | |
387 } | |
388 else | |
389 { | |
390 //printf("accessCheck(%s)\n", d->toChars()); | |
391 } | |
392 #endif | |
393 if (!e) | |
394 { | |
395 if (d->prot() == PROTprivate && d->getModule() != sc->module || | |
396 d->prot() == PROTpackage && !hasPackageAccess(sc, d)) | |
397 | |
398 error(loc, "%s %s.%s is not accessible from %s", | |
399 d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars()); | |
400 } | |
401 else if (e->type->ty == Tclass) | |
402 { // Do access check | |
403 ClassDeclaration *cd; | |
404 | |
405 cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym); | |
406 #if 1 | |
407 if (e->op == TOKsuper) | |
408 { ClassDeclaration *cd2; | |
409 | |
410 cd2 = sc->func->toParent()->isClassDeclaration(); | |
411 if (cd2) | |
412 cd = cd2; | |
413 } | |
414 #endif | |
415 cd->accessCheck(loc, sc, d); | |
416 } | |
417 else if (e->type->ty == Tstruct) | |
418 { // Do access check | |
419 StructDeclaration *cd; | |
420 | |
421 cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym); | |
422 cd->accessCheck(loc, sc, d); | |
423 } | |
424 } |