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());
260 /****************************************
261 * Determine if this is the same or friend of cd.
264 int AggregateDeclaration::isFriendOf(AggregateDeclaration
*cd
)
267 printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd
? cd
->toChars() : "null");
272 // Friends if both are in the same module
273 //if (toParent() == cd->toParent())
274 if (cd
&& getModule() == cd
->getModule())
277 printf("\tin same module\n");
283 printf("\tnot friend\n");
288 /****************************************
289 * Determine if scope sc has package level access to s.
292 int hasPackageAccess(Scope
*sc
, Dsymbol
*s
)
295 printf("hasPackageAccess(s = '%s', sc = '%p')\n", s
->toChars(), sc
);
298 for (; s
; s
= s
->parent
)
300 if (s
->isPackage() && !s
->isModule())
305 printf("\tthis is in package '%s'\n", s
->toChars());
308 if (s
&& s
== sc
->module
->parent
)
311 printf("\ts is in same package as sc\n");
318 printf("\tno package access\n");
323 /**********************************
324 * Determine if smember has access to private members of this declaration.
327 int AggregateDeclaration::hasPrivateAccess(Dsymbol
*smember
)
330 { AggregateDeclaration
*cd
= NULL
;
331 Dsymbol
*smemberparent
= smember
->toParent();
333 cd
= smemberparent
->isAggregateDeclaration();
336 printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n",
337 toChars(), smember
->toChars());
340 if (this == cd
) // smember is a member of this class
345 return 1; // so we get private access
348 // If both are members of the same module, grant access
350 { Dsymbol
*sp
= smember
->toParent();
351 if (sp
->isFuncDeclaration() && smember
->isFuncDeclaration())
356 if (!cd
&& toParent() == smember
->toParent())
363 if (!cd
&& getModule() == smember
->getModule())
377 /****************************************
378 * Check access to d for expression e.d
381 void accessCheck(Loc loc
, Scope
*sc
, Expression
*e
, Declaration
*d
)
385 { printf("accessCheck(%s . %s)\n", e
->toChars(), d
->toChars());
386 printf("\te->type = %s\n", e
->type
->toChars());
390 //printf("accessCheck(%s)\n", d->toChars());
395 if (d
->prot() == PROTprivate
&& d
->getModule() != sc
->module
||
396 d
->prot() == PROTpackage
&& !hasPackageAccess(sc
, d
))
398 error(loc
, "%s %s.%s is not accessible from %s",
399 d
->kind(), d
->getModule()->toChars(), d
->toChars(), sc
->module
->toChars());
401 else if (e
->type
->ty
== Tclass
)
403 ClassDeclaration
*cd
;
405 cd
= (ClassDeclaration
*)(((TypeClass
*)e
->type
)->sym
);
407 if (e
->op
== TOKsuper
)
408 { ClassDeclaration
*cd2
;
410 cd2
= sc
->func
->toParent()->isClassDeclaration();
415 cd
->accessCheck(loc
, sc
, d
);
417 else if (e
->type
->ty
== Tstruct
)
419 StructDeclaration
*cd
;
421 cd
= (StructDeclaration
*)(((TypeStruct
*)e
->type
)->sym
);
422 cd
->accessCheck(loc
, sc
, d
);