2 // Copyright (c) 1999-2006 by Digital Mars
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.
19 #include "aggregate.h"
25 #include "declaration.h"
26 #include "aggregate.h"
27 #include "expression.h"
32 /* Code to do access checks
35 int hasPackageAccess(Scope
*sc
, Dsymbol
*s
);
37 /****************************************
38 * Return PROT access for Dsymbol smember in this declaration.
41 enum PROT
AggregateDeclaration::getAccess(Dsymbol
*smember
)
46 enum PROT
StructDeclaration::getAccess(Dsymbol
*smember
)
48 enum PROT access_ret
= PROTnone
;
51 printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
52 toChars(), smember
->toChars());
54 if (smember
->toParent() == this)
56 access_ret
= smember
->prot();
58 else if (smember
->isDeclaration()->isStatic())
60 access_ret
= smember
->prot();
65 enum PROT
ClassDeclaration::getAccess(Dsymbol
*smember
)
67 enum PROT access_ret
= PROTnone
;
70 printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
71 toChars(), smember
->toChars());
73 if (smember
->toParent() == this)
75 access_ret
= smember
->prot();
82 if (smember
->isDeclaration()->isStatic())
84 access_ret
= smember
->prot();
87 for (i
= 0; i
< baseclasses
.dim
; i
++)
88 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
90 access
= b
->base
->getAccess(smember
);
97 access
= PROTnone
; // private members of base class not accessible
104 // If access is to be tightened
105 if (b
->protection
< access
)
106 access
= b
->protection
;
108 // Pick path with loosest access
109 if (access
> access_ret
)
119 printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
120 toChars(), smember
->toChars(), access_ret
);
125 /********************************************************
126 * Helper function for ClassDeclaration::accessCheck()
132 static int accessCheckX(
135 AggregateDeclaration
*dthis
,
136 AggregateDeclaration
*cdscope
)
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");
146 if (dthis
->hasPrivateAccess(sfunc
) ||
147 dthis
->isFriendOf(cdscope
))
149 if (smember
->toParent() == dthis
)
153 ClassDeclaration
*cdthis
= dthis
->isClassDeclaration();
156 for (int i
= 0; i
< cdthis
->baseclasses
.dim
; i
++)
157 { BaseClass
*b
= (BaseClass
*)cdthis
->baseclasses
.data
[i
];
160 access
= b
->base
->getAccess(smember
);
161 if (access
>= PROTprotected
||
162 accessCheckX(smember
, sfunc
, b
->base
, cdscope
)
172 if (smember
->toParent() != dthis
)
174 ClassDeclaration
*cdthis
= dthis
->isClassDeclaration();
177 for (int i
= 0; i
< cdthis
->baseclasses
.dim
; i
++)
178 { BaseClass
*b
= (BaseClass
*)cdthis
->baseclasses
.data
[i
];
180 if (accessCheckX(smember
, sfunc
, b
->base
, cdscope
))
189 /*******************************
190 * Do access check for member of this class, this class being the
191 * type of the 'this' pointer used to access smember.
194 void AggregateDeclaration::accessCheck(Loc loc
, Scope
*sc
, Dsymbol
*smember
)
198 FuncDeclaration
*f
= sc
->func
;
199 AggregateDeclaration
*cdscope
= sc
->getStructClassScope();
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
);
209 Dsymbol
*smemberparent
= smember
->toParent();
210 if (!smemberparent
|| !smemberparent
->isAggregateDeclaration())
213 printf("not an aggregate member\n");
215 return; // then it is accessible
218 // BUG: should enable this check
219 //assert(smember->parent->isBaseOf(this, NULL));
221 if (smemberparent
== this)
222 { enum PROT access
= smember
->prot();
224 result
= access
>= PROTpublic
||
225 hasPrivateAccess(f
) ||
226 isFriendOf(cdscope
) ||
227 (access
== PROTpackage
&& hasPackageAccess(sc
, this));
229 printf("result1 = %d\n", result
);
232 else if ((access
= this->getAccess(smember
)) >= PROTpublic
)
236 printf("result2 = %d\n", result
);
239 else if (access
== PROTpackage
&& hasPackageAccess(sc
, this))
243 printf("result3 = %d\n", result
);
248 result
= accessCheckX(smember
, f
, this, cdscope
);
250 printf("result4 = %d\n", result
);
255 error(loc
, "member %s is not accessible", smember
->toChars());
259 /****************************************
260 * Determine if this is the same or friend of cd.
263 int AggregateDeclaration::isFriendOf(AggregateDeclaration
*cd
)
266 printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd
? cd
->toChars() : "null");
271 // Friends if both are in the same module
272 //if (toParent() == cd->toParent())
273 if (cd
&& getModule() == cd
->getModule())
276 printf("\tin same module\n");
282 printf("\tnot friend\n");
287 /****************************************
288 * Determine if scope sc has package level access to s.
291 int hasPackageAccess(Scope
*sc
, Dsymbol
*s
)
294 printf("hasPackageAccess(s = '%s', sc = '%p')\n", s
->toChars(), sc
);
297 for (; s
; s
= s
->parent
)
299 if (s
->isPackage() && !s
->isModule())
304 printf("\tthis is in package '%s'\n", s
->toChars());
307 if (s
&& s
== sc
->module
->parent
)
310 printf("\ts is in same package as sc\n");
317 printf("\tno package access\n");
322 /**********************************
323 * Determine if smember has access to private members of this declaration.
326 int AggregateDeclaration::hasPrivateAccess(Dsymbol
*smember
)
329 { AggregateDeclaration
*cd
= NULL
;
330 Dsymbol
*smemberparent
= smember
->toParent();
332 cd
= smemberparent
->isAggregateDeclaration();
335 printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
336 toChars(), smember
->toChars());
339 if (this == cd
) // smember is a member of this class
344 return 1; // so we get private access
347 // If both are members of the same module, grant access
349 { Dsymbol
*sp
= smember
->toParent();
350 if (sp
->isFuncDeclaration() && smember
->isFuncDeclaration())
355 if (!cd
&& toParent() == smember
->toParent())
362 if (!cd
&& getModule() == smember
->getModule())
376 /****************************************
377 * Check access to d for expression e.d
380 void accessCheck(Loc loc
, Scope
*sc
, Expression
*e
, Declaration
*d
)
384 { printf("accessCheck(%s . %s)\n", e
->toChars(), d
->toChars());
385 printf("\te->type = %s\n", e
->type
->toChars());
389 //printf("accessCheck(%s)\n", d->toChars());
394 if (d
->prot() == PROTprivate
&& d
->getModule() != sc
->module
||
395 d
->prot() == PROTpackage
&& !hasPackageAccess(sc
, d
))
397 error(loc
, "%s %s.%s is not accessible from %s",
398 d
->kind(), d
->getModule()->toChars(), d
->toChars(), sc
->module
->toChars());
400 else if (e
->type
->ty
== Tclass
)
402 ClassDeclaration
*cd
;
404 cd
= (ClassDeclaration
*)(((TypeClass
*)e
->type
)->sym
);
406 if (e
->op
== TOKsuper
)
407 { ClassDeclaration
*cd2
;
409 cd2
= sc
->func
->toParent()->isClassDeclaration();
414 cd
->accessCheck(loc
, sc
, d
);
416 else if (e
->type
->ty
== Tstruct
)
418 StructDeclaration
*cd
;
420 cd
= (StructDeclaration
*)(((TypeStruct
*)e
->type
)->sym
);
421 cd
->accessCheck(loc
, sc
, d
);