8080import edu .rice .cs .plt .tuple .Option ;
8181import edu .rice .cs .plt .lambda .Lambda ;
8282import edu .rice .cs .plt .lambda .Lambda2 ;
83- import edu .rice .cs .plt .lambda .Thunk ;
8483
8584import edu .rice .cs .dynamicjava .Options ;
8685import edu .rice .cs .dynamicjava .symbol .*;
@@ -191,13 +190,12 @@ public void checkConstructorCall(ConstructorCall node) {
191190
192191 try {
193192 ConstructorInvocation inv = ts .lookupConstructor (type , targs , args , Option .<Type >none ());
194-
195- // TODO: Check accessibility of constructor
196193 // Note that super constructor calls *have to* be accessible, even if accessibility
197194 // checking is turned off -- a call to a private constructor cannot be compiled
198195 // in a way that it will run successfully (since constructor calls are the only code
199196 // that is directly compiled rather than being interpreted, we don't have this problem
200197 // elsewhere)
198+ checkAccessibility (inv .constructor (), node , true );
201199 checkThrownExceptions (inv .thrown (), node );
202200 node .setArguments (CollectUtil .makeList (inv .args ()));
203201 setConstructor (node , inv .constructor ());
@@ -212,6 +210,44 @@ public void checkConstructorCall(ConstructorCall node) {
212210 }
213211 }
214212
213+ /** Verify that the given symbol is accessible. */
214+ public void checkAccessibility (Access .Limited symbol , Node node ) {
215+ checkAccessibility (symbol , node , false );
216+ }
217+
218+ /**
219+ * Verify that the given symbol is accessible. If {@code alwaysCheckPrivate}, private access is
220+ * checked even when the options dictate otherwise.
221+ */
222+ private void checkAccessibility (Access .Limited symbol , Node node , boolean alwaysCheckPrivate ) {
223+ switch (symbol .accessibility ()) {
224+ case PRIVATE :
225+ if (alwaysCheckPrivate || opt .enforcePrivateAccess () || opt .enforceAllAccess ()) {
226+ if (!symbol .accessModule ().equals (context .accessModule ())) {
227+ setErrorStrings (node , symbol .declaredName ());
228+ throw new ExecutionError ("illegal.private.access" , node );
229+ }
230+ }
231+ break ;
232+ case PACKAGE :
233+ if (opt .enforceAllAccess ()) {
234+ if (!symbol .accessModule ().packageName ().equals (context .accessModule ().packageName ())) {
235+ setErrorStrings (node , symbol .declaredName ());
236+ throw new ExecutionError ("illegal.package.access" , node );
237+ }
238+ }
239+ break ;
240+ case PROTECTED :
241+ if (opt .enforceAllAccess ()) {
242+ // TODO: implement protected-access checks
243+ }
244+ break ;
245+ case PUBLIC :
246+ // access is always valid
247+ break ;
248+ }
249+ }
250+
215251 /** Verify that the thrown exceptions are expected in this context. */
216252 private void checkThrownExceptions (Iterable <? extends Type > thrownTypes , Node node ) {
217253 Iterable <Type > allowed = IterUtil .compose (TypeSystem .RUNTIME_EXCEPTION ,
@@ -301,7 +337,10 @@ else if (context.fieldExists(first.image(), ts)) {
301337 }
302338 try {
303339 DJClass c = context .getTopLevelClass (className , ts );
304- if (c != null ) { classType = ts .makeClassType (c ); }
340+ if (c != null ) {
341+ checkAccessibility (c , node );
342+ classType = ts .makeClassType (c );
343+ }
305344 else {
306345 classType = context .getTypeVariable (className , ts );
307346 if (classType == null ) {
@@ -332,7 +371,9 @@ else if (ts.containsClass(classType, memberName.image())) {
332371 className += "." + last .image ();
333372 classIds .add (last );
334373 try {
335- classType = ts .lookupStaticClass (classType , memberName .image (), IterUtil .<Type >empty ());
374+ ClassType memberType = ts .lookupStaticClass (classType , memberName .image (), IterUtil .<Type >empty ());
375+ checkAccessibility (memberType .ofClass (), node );
376+ classType = memberType ;
336377 }
337378 catch (InvalidTargetException e ) { throw new RuntimeException ("ts.containsClass lied" ); }
338379 catch (InvalidTypeArgumentException e ) { throw new ExecutionError ("type.argument.arity" , node ); }
@@ -430,8 +471,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
430471 setType (obj , t );
431472 ref = ts .lookupField (obj , node .getFieldName ());
432473 }
433-
434- // TODO: Check accessibility of field
474+ checkAccessibility (ref .field (), node );
435475 setField (node , ref .field ());
436476 setVariableType (node , ref .type ());
437477 if (!ref .field ().isStatic ()) {
@@ -459,7 +499,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
459499 try {
460500 ObjectFieldReference ref = ts .lookupField (receiver , node .getFieldName ());
461501 node .setExpression (ref .object ());
462- // TODO: Check accessibility of field
502+ checkAccessibility ( ref . field (), node );
463503 setField (node , ref .field ());
464504 setVariableType (node , ref .type ());
465505 Type result = ts .capture (ref .type ());
@@ -486,7 +526,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
486526 setType (obj , t );
487527 try {
488528 FieldReference ref = ts .lookupField (obj , node .getFieldName ());
489- // TODO: Check accessibility of field
529+ checkAccessibility ( ref . field (), node );
490530 setField (node , ref .field ());
491531 setDJClass (node , c );
492532 setVariableType (node , ref .type ());
@@ -508,7 +548,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
508548 Type t = checkTypeName (node .getFieldType ());
509549 try {
510550 FieldReference ref = ts .lookupStaticField (t , node .getFieldName ());
511- // TODO: Check accessibility of field
551+ checkAccessibility ( ref . field (), node );
512552 setField (node , ref .field ());
513553 setVariableType (node , ref .type ());
514554 Type result = ts .capture (ref .type ());
@@ -517,7 +557,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
517557 }
518558 catch (TypeSystemException e ) {
519559 setErrorStrings (node , ts .userRepresentation (t ), node .getFieldName ());
520- throw new ExecutionError ("no.such.field" , node );
560+ throw new ExecutionError ("no.such.static. field" , node );
521561 }
522562 }
523563
@@ -534,7 +574,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
534574 ClassType t ;
535575 if (context .localFunctionExists (node .getMethodName (), ts )) {
536576 Iterable <LocalFunction > matches = context .getLocalFunctions (node .getMethodName (), ts );
537- t = ts .makeClassType (new FunctionWrapperClass (context .getPackage (), matches ));
577+ t = ts .makeClassType (new FunctionWrapperClass (context .accessModule (), matches ));
538578 }
539579 else {
540580 try {
@@ -557,8 +597,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
557597 setType (obj , t );
558598 inv = ts .lookupMethod (obj , node .getMethodName (), targs , args , expected );
559599 }
560-
561- // TODO: Check accessibility of method
600+ checkAccessibility (inv .method (), node );
562601 checkThrownExceptions (inv .thrown (), node );
563602 node .setArguments (CollectUtil .makeList (inv .args ()));
564603 setMethod (node , inv .method ());
@@ -620,7 +659,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
620659 try {
621660 // Note: Changes made below may also need to be made in the TypeSystem's boxing & unboxing implementations
622661 ObjectMethodInvocation inv = ts .lookupMethod (receiver , node .getMethodName (), targs , args , expected );
623- // TODO: Check accessibility of method
662+ checkAccessibility ( inv . method (), node );
624663 checkThrownExceptions (inv .thrown (), node );
625664 node .setExpression (inv .object ());
626665 node .setArguments (CollectUtil .makeList (inv .args ()));
@@ -662,7 +701,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
662701 setType (obj , t );
663702 try {
664703 MethodInvocation inv = ts .lookupMethod (obj , node .getMethodName (), targs , args , expected );
665- // TODO: Check accessibility of method
704+ checkAccessibility ( inv . method (), node );
666705 checkThrownExceptions (inv .thrown (), node );
667706 node .setArguments (CollectUtil .makeList (inv .args ()));
668707 setMethod (node , inv .method ());
@@ -699,7 +738,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
699738 try {
700739 // Note: Changes made below may also need to be made in the TypeSystem's boxing & unboxing implementations
701740 MethodInvocation inv = ts .lookupStaticMethod (t , node .getMethodName (), targs , args , expected );
702- // TODO: Check accessibility of method
741+ checkAccessibility ( inv . method (), node );
703742 checkThrownExceptions (inv .thrown (), node );
704743 node .setArguments (CollectUtil .makeList (inv .args ()));
705744 setMethod (node , inv .method ());
@@ -713,7 +752,7 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
713752 }
714753 catch (TypeSystemException e ) {
715754 setErrorStrings (node , ts .userRepresentation (t ), node .getMethodName (), nodeTypesString (args ));
716- throw new ExecutionError ("no.such.method" , node );
755+ throw new ExecutionError ("no.such.static. method" , node );
717756 }
718757 }
719758
@@ -812,7 +851,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
812851
813852 try {
814853 ConstructorInvocation inv = ts .lookupConstructor (t , targs , args , expected );
815- // TODO: Check accessibility of constructor
854+ checkAccessibility ( inv . constructor (), node );
816855 checkThrownExceptions (inv .thrown (), node );
817856 node .setArguments (CollectUtil .makeList (inv .args ()));
818857 setConstructor (node , inv .constructor ());
@@ -850,7 +889,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
850889 // Super constructor invocation is something besides Object()
851890 try {
852891 ConstructorInvocation inv = ts .lookupConstructor (t , targs , args , expected );
853- // TODO: Check accessibility of constructor
892+ checkAccessibility ( inv . constructor (), node );
854893 checkThrownExceptions (inv .thrown (), node );
855894 node .setArguments (CollectUtil .makeList (inv .args ()));
856895 }
@@ -864,7 +903,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
864903 }
865904
866905 TreeClassLoader loader = new TreeClassLoader (context .getClassLoader (), opt );
867- TreeClass c = new TreeClass (context .makeAnonymousClassName (), null , node , loader , opt );
906+ TreeClass c = new TreeClass (context .makeAnonymousClassName (), null , context . accessModule (), node , loader , opt );
868907 setDJClass (node , c );
869908 ClassChecker checker = new ClassChecker (c , loader , context , opt );
870909 checker .initializeClassSignatures (node );
@@ -888,8 +927,12 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
888927 }
889928
890929 try {
891- Type t = ts .lookupClass (node .getExpression (), node .getClassName (), classTargs );
892- // TODO: Check that t is not a static member of enclosing
930+ ClassType t = ts .lookupClass (node .getExpression (), node .getClassName (), classTargs );
931+ checkAccessibility (t .ofClass (), node );
932+ if (t .ofClass ().isStatic ()) {
933+ setErrorStrings (node , node .getClassName (), ts .userRepresentation (getType (node .getExpression ())));
934+ throw new ExecutionError ("static.inner.allocation" , node );
935+ }
893936 if (!ts .isConcrete (t )) {
894937 throw new ExecutionError ("allocation.type" , node );
895938 }
@@ -904,7 +947,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
904947
905948 try {
906949 ConstructorInvocation inv = ts .lookupConstructor (t , targs , args , expected );
907- // TODO: Check accessibility of constructor
950+ checkAccessibility ( inv . constructor (), node );
908951 checkThrownExceptions (inv .thrown (), node );
909952 node .setArguments (CollectUtil .makeList (inv .args ()));
910953 setConstructor (node , inv .constructor ());
@@ -940,8 +983,12 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
940983 }
941984
942985 try {
943- Type t = ts .lookupClass (node .getExpression (), node .getClassName (), classTargs );
944- // TODO: Check that t is not a static member of enclosing
986+ ClassType t = ts .lookupClass (node .getExpression (), node .getClassName (), classTargs );
987+ checkAccessibility (t .ofClass (), node );
988+ if (t .ofClass ().isStatic ()) {
989+ setErrorStrings (node , node .getClassName (), ts .userRepresentation (getType (node .getExpression ())));
990+ throw new ExecutionError ("static.inner.allocation" , node );
991+ }
945992 if (!ts .isExtendable (t )) {
946993 throw new ExecutionError ("allocation.type" , node );
947994 }
@@ -957,7 +1004,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
9571004
9581005 try {
9591006 ConstructorInvocation inv = ts .lookupConstructor (t , targs , args , expected );
960- // TODO: Check accessibility of constructor
1007+ checkAccessibility ( inv . constructor (), node );
9611008 checkThrownExceptions (inv .thrown (), node );
9621009 node .setArguments (CollectUtil .makeList (inv .args ()));
9631010 }
@@ -978,7 +1025,7 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
9781025 }
9791026
9801027 TreeClassLoader loader = new TreeClassLoader (context .getClassLoader (), opt );
981- TreeClass c = new TreeClass (context .makeAnonymousClassName (), null , node , loader , opt );
1028+ TreeClass c = new TreeClass (context .makeAnonymousClassName (), null , context . accessModule (), node , loader , opt );
9821029 setDJClass (node , c );
9831030 ClassChecker checker = new ClassChecker (c , loader , context , opt );
9841031 checker .initializeClassSignatures (node );
0 commit comments