001 /*
002 * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.javac.comp;
027
028 import java.util.*;
029 import java.util.Set;
030 import javax.lang.model.element.ElementKind;
031 import javax.tools.JavaFileObject;
032
033 import com.sun.tools.javac.code.*;
034 import com.sun.tools.javac.jvm.*;
035 import com.sun.tools.javac.tree.*;
036 import com.sun.tools.javac.util.*;
037 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
038 import com.sun.tools.javac.util.List;
039
040 import com.sun.tools.javac.jvm.Target;
041 import com.sun.tools.javac.code.Symbol.*;
042 import com.sun.tools.javac.tree.JCTree.*;
043 import com.sun.tools.javac.code.Type.*;
044
045 import com.sun.source.tree.IdentifierTree;
046 import com.sun.source.tree.MemberSelectTree;
047 import com.sun.source.tree.TreeVisitor;
048 import com.sun.source.util.SimpleTreeVisitor;
049
050 import static com.sun.tools.javac.code.Flags.*;
051 import static com.sun.tools.javac.code.Kinds.*;
052 import static com.sun.tools.javac.code.TypeTags.*;
053
054 /** This is the main context-dependent analysis phase in GJC. It
055 * encompasses name resolution, type checking and constant folding as
056 * subtasks. Some subtasks involve auxiliary classes.
057 * @see Check
058 * @see Resolve
059 * @see ConstFold
060 * @see Infer
061 *
062 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
063 * you write code that depends on this, you do so at your own risk.
064 * This code and its internal interfaces are subject to change or
065 * deletion without notice.</b>
066 */
067 public class Attr extends JCTree.Visitor {
068 protected static final Context.Key<Attr> attrKey =
069 new Context.Key<Attr>();
070
071 final Names names;
072 final Log log;
073 final Symtab syms;
074 final Resolve rs;
075 final Check chk;
076 final MemberEnter memberEnter;
077 final TreeMaker make;
078 final ConstFold cfolder;
079 final Enter enter;
080 final Target target;
081 final Types types;
082 final JCDiagnostic.Factory diags;
083 final Annotate annotate;
084 final Options options;
085
086 public static Attr instance(Context context) {
087 Attr instance = context.get(attrKey);
088 if (instance == null)
089 instance = new Attr(context);
090 return instance;
091 }
092
093 protected Attr(Context context) {
094 context.put(attrKey, this);
095
096 names = Names.instance(context);
097 log = Log.instance(context);
098 syms = Symtab.instance(context);
099 rs = Resolve.instance(context);
100 chk = Check.instance(context);
101 memberEnter = MemberEnter.instance(context);
102 make = TreeMaker.instance(context);
103 enter = Enter.instance(context);
104 cfolder = ConstFold.instance(context);
105 target = Target.instance(context);
106 types = Types.instance(context);
107 diags = JCDiagnostic.Factory.instance(context);
108 annotate = Annotate.instance(context);
109
110 options = Options.instance(context);
111
112 Source source = Source.instance(context);
113 allowGenerics = source.allowGenerics();
114 allowVarargs = source.allowVarargs();
115 allowEnums = source.allowEnums();
116 allowBoxing = source.allowBoxing();
117 allowCovariantReturns = source.allowCovariantReturns();
118 allowAnonOuterThis = source.allowAnonOuterThis();
119 relax = (options.get("-retrofit") != null ||
120 options.get("-relax") != null);
121 useBeforeDeclarationWarning = options.get("useBeforeDeclarationWarning") != null;
122 }
123
124 /** Switch: relax some constraints for retrofit mode.
125 */
126 boolean relax;
127
128 /** Switch: support generics?
129 */
130 boolean allowGenerics;
131
132 /** Switch: allow variable-arity methods.
133 */
134 boolean allowVarargs;
135
136 /** Switch: support enums?
137 */
138 boolean allowEnums;
139
140 /** Switch: support boxing and unboxing?
141 */
142 boolean allowBoxing;
143
144 /** Switch: support covariant result types?
145 */
146 boolean allowCovariantReturns;
147
148 /** Switch: allow references to surrounding object from anonymous
149 * objects during constructor call?
150 */
151 boolean allowAnonOuterThis;
152
153 /**
154 * Switch: warn about use of variable before declaration?
155 * RFE: 6425594
156 */
157 boolean useBeforeDeclarationWarning;
158
159 /** Check kind and type of given tree against protokind and prototype.
160 * If check succeeds, store type in tree and return it.
161 * If check fails, store errType in tree and return it.
162 * No checks are performed if the prototype is a method type.
163 * It is not necessary in this case since we know that kind and type
164 * are correct.
165 *
166 * @param tree The tree whose kind and type is checked
167 * @param owntype The computed type of the tree
168 * @param ownkind The computed kind of the tree
169 * @param pkind The expected kind (or: protokind) of the tree
170 * @param pt The expected type (or: prototype) of the tree
171 */
172 Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) {
173 if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) {
174 if ((ownkind & ~pkind) == 0) {
175 owntype = chk.checkType(tree.pos(), owntype, pt);
176 } else {
177 log.error(tree.pos(), "unexpected.type",
178 kindNames(pkind),
179 kindName(ownkind));
180 owntype = types.createErrorType(owntype);
181 }
182 }
183 tree.type = owntype;
184 return owntype;
185 }
186
187 /** Is given blank final variable assignable, i.e. in a scope where it
188 * may be assigned to even though it is final?
189 * @param v The blank final variable.
190 * @param env The current environment.
191 */
192 boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) {
193 Symbol owner = env.info.scope.owner;
194 // owner refers to the innermost variable, method or
195 // initializer block declaration at this point.
196 return
197 v.owner == owner
198 ||
199 ((owner.name == names.init || // i.e. we are in a constructor
200 owner.kind == VAR || // i.e. we are in a variable initializer
201 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block
202 &&
203 v.owner == owner.owner
204 &&
205 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
206 }
207
208 /** Check that variable can be assigned to.
209 * @param pos The current source code position.
210 * @param v The assigned varaible
211 * @param base If the variable is referred to in a Select, the part
212 * to the left of the `.', null otherwise.
213 * @param env The current environment.
214 */
215 void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
216 if ((v.flags() & FINAL) != 0 &&
217 ((v.flags() & HASINIT) != 0
218 ||
219 !((base == null ||
220 (base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) &&
221 isAssignableAsBlankFinal(v, env)))) {
222 log.error(pos, "cant.assign.val.to.final.var", v);
223 }
224 }
225
226 /** Does tree represent a static reference to an identifier?
227 * It is assumed that tree is either a SELECT or an IDENT.
228 * We have to weed out selects from non-type names here.
229 * @param tree The candidate tree.
230 */
231 boolean isStaticReference(JCTree tree) {
232 if (tree.getTag() == JCTree.SELECT) {
233 Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected);
234 if (lsym == null || lsym.kind != TYP) {
235 return false;
236 }
237 }
238 return true;
239 }
240
241 /** Is this symbol a type?
242 */
243 static boolean isType(Symbol sym) {
244 return sym != null && sym.kind == TYP;
245 }
246
247 /** The current `this' symbol.
248 * @param env The current environment.
249 */
250 Symbol thisSym(DiagnosticPosition pos, Env<AttrContext> env) {
251 return rs.resolveSelf(pos, env, env.enclClass.sym, names._this);
252 }
253
254 /** Attribute a parsed identifier.
255 * @param tree Parsed identifier name
256 * @param topLevel The toplevel to use
257 */
258 public Symbol attribIdent(JCTree tree, JCCompilationUnit topLevel) {
259 Env<AttrContext> localEnv = enter.topLevelEnv(topLevel);
260 localEnv.enclClass = make.ClassDef(make.Modifiers(0),
261 syms.errSymbol.name,
262 null, null, null, null);
263 localEnv.enclClass.sym = syms.errSymbol;
264 return tree.accept(identAttributer, localEnv);
265 }
266 // where
267 private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer();
268 private class IdentAttributer extends SimpleTreeVisitor<Symbol,Env<AttrContext>> {
269 @Override
270 public Symbol visitMemberSelect(MemberSelectTree node, Env<AttrContext> env) {
271 Symbol site = visit(node.getExpression(), env);
272 if (site.kind == ERR)
273 return site;
274 Name name = (Name)node.getIdentifier();
275 if (site.kind == PCK) {
276 env.toplevel.packge = (PackageSymbol)site;
277 return rs.findIdentInPackage(env, (TypeSymbol)site, name, TYP | PCK);
278 } else {
279 env.enclClass.sym = (ClassSymbol)site;
280 return rs.findMemberType(env, site.asType(), name, (TypeSymbol)site);
281 }
282 }
283
284 @Override
285 public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) {
286 return rs.findIdent(env, (Name)node.getName(), TYP | PCK);
287 }
288 }
289
290 public Type coerce(Type etype, Type ttype) {
291 return cfolder.coerce(etype, ttype);
292 }
293
294 public Type attribType(JCTree node, TypeSymbol sym) {
295 Env<AttrContext> env = enter.typeEnvs.get(sym);
296 Env<AttrContext> localEnv = env.dup(node, env.info.dup());
297 return attribTree(node, localEnv, Kinds.TYP, Type.noType);
298 }
299
300 public Env<AttrContext> attribExprToTree(JCTree expr, Env<AttrContext> env, JCTree tree) {
301 breakTree = tree;
302 JavaFileObject prev = log.useSource(null);
303 try {
304 attribExpr(expr, env);
305 } catch (BreakAttr b) {
306 return b.env;
307 } finally {
308 breakTree = null;
309 log.useSource(prev);
310 }
311 return env;
312 }
313
314 public Env<AttrContext> attribStatToTree(JCTree stmt, Env<AttrContext> env, JCTree tree) {
315 breakTree = tree;
316 JavaFileObject prev = log.useSource(null);
317 try {
318 attribStat(stmt, env);
319 } catch (BreakAttr b) {
320 return b.env;
321 } finally {
322 breakTree = null;
323 log.useSource(prev);
324 }
325 return env;
326 }
327
328 private JCTree breakTree = null;
329
330 private static class BreakAttr extends RuntimeException {
331 static final long serialVersionUID = -6924771130405446405L;
332 private Env<AttrContext> env;
333 private BreakAttr(Env<AttrContext> env) {
334 this.env = env;
335 }
336 }
337
338
339 /* ************************************************************************
340 * Visitor methods
341 *************************************************************************/
342
343 /** Visitor argument: the current environment.
344 */
345 Env<AttrContext> env;
346
347 /** Visitor argument: the currently expected proto-kind.
348 */
349 int pkind;
350
351 /** Visitor argument: the currently expected proto-type.
352 */
353 Type pt;
354
355 /** Visitor result: the computed type.
356 */
357 Type result;
358
359 /** Visitor method: attribute a tree, catching any completion failure
360 * exceptions. Return the tree's type.
361 *
362 * @param tree The tree to be visited.
363 * @param env The environment visitor argument.
364 * @param pkind The protokind visitor argument.
365 * @param pt The prototype visitor argument.
366 */
367 Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt) {
368 Env<AttrContext> prevEnv = this.env;
369 int prevPkind = this.pkind;
370 Type prevPt = this.pt;
371 try {
372 this.env = env;
373 this.pkind = pkind;
374 this.pt = pt;
375 tree.accept(this);
376 if (tree == breakTree)
377 throw new BreakAttr(env);
378 return result;
379 } catch (CompletionFailure ex) {
380 tree.type = syms.errType;
381 return chk.completionError(tree.pos(), ex);
382 } finally {
383 this.env = prevEnv;
384 this.pkind = prevPkind;
385 this.pt = prevPt;
386 }
387 }
388
389 /** Derived visitor method: attribute an expression tree.
390 */
391 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
392 return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType);
393 }
394
395 /** Derived visitor method: attribute an expression tree with
396 * no constraints on the computed type.
397 */
398 Type attribExpr(JCTree tree, Env<AttrContext> env) {
399 return attribTree(tree, env, VAL, Type.noType);
400 }
401
402 /** Derived visitor method: attribute a type tree.
403 */
404 Type attribType(JCTree tree, Env<AttrContext> env) {
405 Type result = attribTree(tree, env, TYP, Type.noType);
406 return result;
407 }
408
409 /** Derived visitor method: attribute a statement or definition tree.
410 */
411 public Type attribStat(JCTree tree, Env<AttrContext> env) {
412 return attribTree(tree, env, NIL, Type.noType);
413 }
414
415 /** Attribute a list of expressions, returning a list of types.
416 */
417 List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) {
418 ListBuffer<Type> ts = new ListBuffer<Type>();
419 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)
420 ts.append(attribExpr(l.head, env, pt));
421 return ts.toList();
422 }
423
424 /** Attribute a list of statements, returning nothing.
425 */
426 <T extends JCTree> void attribStats(List<T> trees, Env<AttrContext> env) {
427 for (List<T> l = trees; l.nonEmpty(); l = l.tail)
428 attribStat(l.head, env);
429 }
430
431 /** Attribute the arguments in a method call, returning a list of types.
432 */
433 List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) {
434 ListBuffer<Type> argtypes = new ListBuffer<Type>();
435 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)
436 argtypes.append(chk.checkNonVoid(
437 l.head.pos(), types.upperBound(attribTree(l.head, env, VAL, Infer.anyPoly))));
438 return argtypes.toList();
439 }
440
441 /** Attribute a type argument list, returning a list of types.
442 */
443 List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) {
444 ListBuffer<Type> argtypes = new ListBuffer<Type>();
445 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)
446 argtypes.append(chk.checkRefType(l.head.pos(), attribType(l.head, env)));
447 return argtypes.toList();
448 }
449
450
451 /**
452 * Attribute type variables (of generic classes or methods).
453 * Compound types are attributed later in attribBounds.
454 * @param typarams the type variables to enter
455 * @param env the current environment
456 */
457 void attribTypeVariables(List<JCTypeParameter> typarams, Env<AttrContext> env) {
458 for (JCTypeParameter tvar : typarams) {
459 TypeVar a = (TypeVar)tvar.type;
460 a.tsym.flags_field |= UNATTRIBUTED;
461 a.bound = Type.noType;
462 if (!tvar.bounds.isEmpty()) {
463 List<Type> bounds = List.of(attribType(tvar.bounds.head, env));
464 for (JCExpression bound : tvar.bounds.tail)
465 bounds = bounds.prepend(attribType(bound, env));
466 types.setBounds(a, bounds.reverse());
467 } else {
468 // if no bounds are given, assume a single bound of
469 // java.lang.Object.
470 types.setBounds(a, List.of(syms.objectType));
471 }
472 a.tsym.flags_field &= ~UNATTRIBUTED;
473 }
474 for (JCTypeParameter tvar : typarams)
475 chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type);
476 attribStats(typarams, env);
477 }
478
479 void attribBounds(List<JCTypeParameter> typarams) {
480 for (JCTypeParameter typaram : typarams) {
481 Type bound = typaram.type.getUpperBound();
482 if (bound != null && bound.tsym instanceof ClassSymbol) {
483 ClassSymbol c = (ClassSymbol)bound.tsym;
484 if ((c.flags_field & COMPOUND) != 0) {
485 assert (c.flags_field & UNATTRIBUTED) != 0 : c;
486 attribClass(typaram.pos(), c);
487 }
488 }
489 }
490 }
491
492 /**
493 * Attribute the type references in a list of annotations.
494 */
495 void attribAnnotationTypes(List<JCAnnotation> annotations,
496 Env<AttrContext> env) {
497 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
498 JCAnnotation a = al.head;
499 attribType(a.annotationType, env);
500 }
501 }
502
503 /** Attribute type reference in an `extends' or `implements' clause.
504 *
505 * @param tree The tree making up the type reference.
506 * @param env The environment current at the reference.
507 * @param classExpected true if only a class is expected here.
508 * @param interfaceExpected true if only an interface is expected here.
509 */
510 Type attribBase(JCTree tree,
511 Env<AttrContext> env,
512 boolean classExpected,
513 boolean interfaceExpected,
514 boolean checkExtensible) {
515 Type t = attribType(tree, env);
516 return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible);
517 }
518 Type checkBase(Type t,
519 JCTree tree,
520 Env<AttrContext> env,
521 boolean classExpected,
522 boolean interfaceExpected,
523 boolean checkExtensible) {
524 if (t.tag == TYPEVAR && !classExpected && !interfaceExpected) {
525 // check that type variable is already visible
526 if (t.getUpperBound() == null) {
527 log.error(tree.pos(), "illegal.forward.ref");
528 return types.createErrorType(t);
529 }
530 } else {
531 t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
532 }
533 if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) {
534 log.error(tree.pos(), "intf.expected.here");
535 // return errType is necessary since otherwise there might
536 // be undetected cycles which cause attribution to loop
537 return types.createErrorType(t);
538 } else if (checkExtensible &&
539 classExpected &&
540 (t.tsym.flags() & INTERFACE) != 0) {
541 log.error(tree.pos(), "no.intf.expected.here");
542 return types.createErrorType(t);
543 }
544 if (checkExtensible &&
545 ((t.tsym.flags() & FINAL) != 0)) {
546 log.error(tree.pos(),
547 "cant.inherit.from.final", t.tsym);
548 }
549 chk.checkNonCyclic(tree.pos(), t);
550 return t;
551 }
552
553 public void visitClassDef(JCClassDecl tree) {
554 // Local classes have not been entered yet, so we need to do it now:
555 if ((env.info.scope.owner.kind & (VAR | MTH)) != 0)
556 enter.classEnter(tree, env);
557
558 ClassSymbol c = tree.sym;
559 if (c == null) {
560 // exit in case something drastic went wrong during enter.
561 result = null;
562 } else {
563 // make sure class has been completed:
564 c.complete();
565
566 // If this class appears as an anonymous class
567 // in a superclass constructor call where
568 // no explicit outer instance is given,
569 // disable implicit outer instance from being passed.
570 // (This would be an illegal access to "this before super").
571 if (env.info.isSelfCall &&
572 env.tree.getTag() == JCTree.NEWCLASS &&
573 ((JCNewClass) env.tree).encl == null)
574 {
575 c.flags_field |= NOOUTERTHIS;
576 }
577 attribClass(tree.pos(), c);
578 result = tree.type = c.type;
579 }
580 }
581
582 public void visitMethodDef(JCMethodDecl tree) {
583 MethodSymbol m = tree.sym;
584
585 Lint lint = env.info.lint.augment(m.attributes_field, m.flags());
586 Lint prevLint = chk.setLint(lint);
587 try {
588 chk.checkDeprecatedAnnotation(tree.pos(), m);
589
590 attribBounds(tree.typarams);
591
592 // If we override any other methods, check that we do so properly.
593 // JLS ???
594 chk.checkOverride(tree, m);
595
596 // Create a new environment with local scope
597 // for attributing the method.
598 Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env);
599
600 localEnv.info.lint = lint;
601
602 // Enter all type parameters into the local method scope.
603 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
604 localEnv.info.scope.enterIfAbsent(l.head.type.tsym);
605
606 ClassSymbol owner = env.enclClass.sym;
607 if ((owner.flags() & ANNOTATION) != 0 &&
608 tree.params.nonEmpty())
609 log.error(tree.params.head.pos(),
610 "intf.annotation.members.cant.have.params");
611
612 // Attribute all value parameters.
613 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
614 attribStat(l.head, localEnv);
615 }
616
617 // Check that type parameters are well-formed.
618 chk.validate(tree.typarams, localEnv);
619 if ((owner.flags() & ANNOTATION) != 0 &&
620 tree.typarams.nonEmpty())
621 log.error(tree.typarams.head.pos(),
622 "intf.annotation.members.cant.have.type.params");
623
624 // Check that result type is well-formed.
625 chk.validate(tree.restype, localEnv);
626 if ((owner.flags() & ANNOTATION) != 0)
627 chk.validateAnnotationType(tree.restype);
628
629 if ((owner.flags() & ANNOTATION) != 0)
630 chk.validateAnnotationMethod(tree.pos(), m);
631
632 // Check that all exceptions mentioned in the throws clause extend
633 // java.lang.Throwable.
634 if ((owner.flags() & ANNOTATION) != 0 && tree.thrown.nonEmpty())
635 log.error(tree.thrown.head.pos(),
636 "throws.not.allowed.in.intf.annotation");
637 for (List<JCExpression> l = tree.thrown; l.nonEmpty(); l = l.tail)
638 chk.checkType(l.head.pos(), l.head.type, syms.throwableType);
639
640 if (tree.body == null) {
641 // Empty bodies are only allowed for
642 // abstract, native, or interface methods, or for methods
643 // in a retrofit signature class.
644 if ((owner.flags() & INTERFACE) == 0 &&
645 (tree.mods.flags & (ABSTRACT | NATIVE)) == 0 &&
646 !relax)
647 log.error(tree.pos(), "missing.meth.body.or.decl.abstract");
648 if (tree.defaultValue != null) {
649 if ((owner.flags() & ANNOTATION) == 0)
650 log.error(tree.pos(),
651 "default.allowed.in.intf.annotation.member");
652 }
653 } else if ((owner.flags() & INTERFACE) != 0) {
654 log.error(tree.body.pos(), "intf.meth.cant.have.body");
655 } else if ((tree.mods.flags & ABSTRACT) != 0) {
656 log.error(tree.pos(), "abstract.meth.cant.have.body");
657 } else if ((tree.mods.flags & NATIVE) != 0) {
658 log.error(tree.pos(), "native.meth.cant.have.body");
659 } else {
660 // Add an implicit super() call unless an explicit call to
661 // super(...) or this(...) is given
662 // or we are compiling class java.lang.Object.
663 if (tree.name == names.init && owner.type != syms.objectType) {
664 JCBlock body = tree.body;
665 if (body.stats.isEmpty() ||
666 !TreeInfo.isSelfCall(body.stats.head)) {
667 body.stats = body.stats.
668 prepend(memberEnter.SuperCall(make.at(body.pos),
669 List.<Type>nil(),
670 List.<JCVariableDecl>nil(),
671 false));
672 } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&
673 (tree.mods.flags & GENERATEDCONSTR) == 0 &&
674 TreeInfo.isSuperCall(body.stats.head)) {
675 // enum constructors are not allowed to call super
676 // directly, so make sure there aren't any super calls
677 // in enum constructors, except in the compiler
678 // generated one.
679 log.error(tree.body.stats.head.pos(),
680 "call.to.super.not.allowed.in.enum.ctor",
681 env.enclClass.sym);
682 }
683 }
684
685 // Attribute method body.
686 attribStat(tree.body, localEnv);
687 }
688 localEnv.info.scope.leave();
689 result = tree.type = m.type;
690 chk.validateAnnotations(tree.mods.annotations, m);
691
692 if (tree.name == names.init) {
693 boolean isCtorEscapeSafe = ((tree.sym.flags() & SEPARABLE)!=0);
694 env.enclClass.containsEscapeSafeCtors |= isCtorEscapeSafe;
695 }
696 if (((tree.sym.flags() & SEPARABLE)!=0) && (tree.thrown.size()>0)) {
697 // separable method cannot have a throws clause
698 log.error(tree.thrown.head.pos(), "no.throws.clause.for.escapesafe");
699 }
700 }
701 finally {
702 chk.setLint(prevLint);
703 }
704 }
705
706 public void visitVarDef(JCVariableDecl tree) {
707 // Local variables have not been entered yet, so we need to do it now:
708 if (env.info.scope.owner.kind == MTH) {
709 if (tree.sym != null) {
710 // parameters have already been entered
711 env.info.scope.enter(tree.sym);
712 } else {
713 memberEnter.memberEnter(tree, env);
714 annotate.flush();
715 }
716 }
717
718 VarSymbol v = tree.sym;
719 Lint lint = env.info.lint.augment(v.attributes_field, v.flags());
720 Lint prevLint = chk.setLint(lint);
721
722 // Check that the variable's declared type is well-formed.
723 chk.validate(tree.vartype, env);
724
725 try {
726 chk.checkDeprecatedAnnotation(tree.pos(), v);
727
728 if (tree.init != null) {
729 if ((v.flags_field & FINAL) != 0 && tree.init.getTag() != JCTree.NEWCLASS) {
730 // In this case, `v' is final. Ensure that it's initializer is
731 // evaluated.
732 v.getConstValue(); // ensure initializer is evaluated
733 } else {
734 // Attribute initializer in a new environment
735 // with the declared variable as owner.
736 // Check that initializer conforms to variable's declared type.
737 Env<AttrContext> initEnv = memberEnter.initEnv(tree, env);
738 initEnv.info.lint = lint;
739 // In order to catch self-references, we set the variable's
740 // declaration position to maximal possible value, effectively
741 // marking the variable as undefined.
742 initEnv.info.enclVar = v;
743 attribExpr(tree.init, initEnv, v.type);
744 }
745 }
746 result = tree.type = v.type;
747 chk.validateAnnotations(tree.mods.annotations, v);
748 }
749 finally {
750 chk.setLint(prevLint);
751 }
752 }
753
754 public void visitSkip(JCSkip tree) {
755 result = null;
756 }
757
758 public void visitBlock(JCBlock tree) {
759 if (env.info.scope.owner.kind == TYP) {
760 // Block is a static or instance initializer;
761 // let the owner of the environment be a freshly
762 // created BLOCK-method.
763 Env<AttrContext> localEnv =
764 env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));
765 localEnv.info.scope.owner =
766 new MethodSymbol(tree.flags | BLOCK, names.empty, null,
767 env.info.scope.owner);
768 if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
769 attribStats(tree.stats, localEnv);
770 } else {
771 // Create a new local environment with a local scope.
772 Env<AttrContext> localEnv =
773 env.dup(tree, env.info.dup(env.info.scope.dup()));
774 attribStats(tree.stats, localEnv);
775 localEnv.info.scope.leave();
776 }
777 result = null;
778 }
779
780 // mgr: staging additions
781
782 public void visitBracketExpr(JCBracketExpr tree) {
783 if (options.get("-verbose") != null) { System.out.println("Working on bracket: "+tree); }
784 tree.setSafe(true); // assumed safe until proven guilty
785 Env<AttrContext> localEnv = enter.bracketEnv(tree, env);
786
787 attribExpr(tree.body, localEnv);
788
789 if (options.get("-verbose") != null) { System.out.println("Bracket: "+tree+" is ====="+(tree.isSafe()?"":"UN")+"SAFE====="); }
790 // if the type of the body is a primitive type, we want the boxed
791 // type instead
792 Type t = tree.body.type;
793 if (t.isPrimitive()) {
794 t = types.boxedClass(t).type;
795 }
796 if (t.equals(syms.voidType)) {
797 log.error(tree.body.pos(), "bracket.expression.cannot.have.type.void");
798 }
799 // type of brackets is Code<T>, where T is the type of the body
800 // or SafeCode<T> if bracket is safe
801 Type bracketType = tree.isSafe()?syms.safeCodeType:syms.codeType;
802 Type owntype = new ClassType (bracketType.getEnclosingType(),
803 List.of(t), bracketType.tsym);
804 result = check (tree, owntype, pkind, pkind, pt);
805 }
806
807 public void visitBracketStat(JCBracketStat tree) {
808 tree.setSafe(true); // assumed safe until proven guilty
809 // Create a new local environment with a local scope.
810 Env<AttrContext> localEnv = enter.bracketEnv(tree, env);
811 attribStats(tree.body, localEnv);
812 if (options.get("-verbose") != null) { System.out.println("Bracket: "+tree+" is ====="+(tree.isSafe()?"":"UN")+"SAFE====="); }
813 // localEnv.info.scope.leave();
814 // type of brackets is Code<Void> or SafeCode<Void< if bracket is safe
815 Type bracketType = tree.isSafe()?syms.safeCodeType:syms.codeType;
816 Type owntype = new ClassType (bracketType.getEnclosingType(),
817 List.of(syms.javaLangVoidType), bracketType.tsym);
818 result = check (tree, owntype, pkind, pkind, pt);
819 }
820
821 public void visitEscapeExpr(JCEscapeExpr tree) {
822 // check if there are enclosing brackets
823 if (env.enclBrackets.isEmpty ()) {
824 log.error (tree.body.pos(), "escape.outside.brackets");
825 }
826
827 Env<AttrContext> localEnv = enter.escapeEnv(tree, env);
828 Type t = attribExpr(tree.body, localEnv);
829 // System.out.println("visitEscapeExpr: "+tree+", escapeCount: "+env.escapeCount+", inEscape? "+inEscape+", inEscapeSafeMethod? "+inEscapeSafeMethod);
830 // System.out.println("\t"+t);
831
832 if ((t instanceof ClassType) &&
833 ((t.tsym == syms.safeCodeType.tsym) ||
834 ((t.tsym == syms.codeType.tsym) && !env.isEscapeSafe()))) {
835 if (t.isRaw()) {
836 log.error (tree.body.pos(), "code.may.not.be.raw");
837 }
838 else {
839 result = check (tree, t.getTypeArguments().head, pkind, pkind, pt);
840 if (t.tsym == syms.codeType.tsym) setClosestBracketUnsafe(tree);
841 }
842 } else {
843 if (env.isEscapeSafe()) {
844 log.error (tree.body.pos(), "escape.in.escapesafe.needs.safecode.type", t);
845 }
846 else {
847 log.error (tree.body.pos(), "escape.needs.code.type", t);
848 }
849 result = types.createErrorType(t);
850 }
851 }
852
853 public void visitEscapeStat(JCEscapeStat tree) {
854 // check if there are enclosing brackets
855 if (env.enclBrackets.isEmpty ()) {
856 log.error (tree.body.pos(), "escape.outside.brackets");
857 }
858
859 Env<AttrContext> localEnv = enter.escapeEnv(tree, env);
860 Type t = attribExpr(tree.body, localEnv);
861
862 // check for Code<Void> type
863 if ((t instanceof ClassType) &&
864 ((t.tsym == syms.safeCodeType.tsym) ||
865 ((t.tsym == syms.codeType.tsym) && !env.isEscapeSafe())) &&
866 (t.getTypeArguments().nonEmpty()) && (t.getTypeArguments().head == syms.javaLangVoidType)) {
867 if (t.isRaw()) {
868 log.error (tree.body.pos(), "code.may.not.be.raw");
869 if (t.tsym == syms.codeType.tsym) setClosestBracketUnsafe(tree);
870 }
871 else {
872 result = tree.type = t.getParameterTypes().head;
873 }
874 } else {
875 if (env.isEscapeSafe()) {
876 log.error (tree.body.pos(), "escape.stat.in.escapesafe.needs.safecode.void.type", t);
877 }
878 else {
879 log.error (tree.body.pos(), "escape.stat.needs.code.void.type", t);
880 }
881 result = types.createErrorType(t);
882 }
883 }
884
885 public void visitDoLoop(JCDoWhileLoop tree) {
886 attribStat(tree.body, env.dup(tree));
887 attribExpr(tree.cond, env, syms.booleanType);
888 result = null;
889 }
890
891 public void visitWhileLoop(JCWhileLoop tree) {
892 attribExpr(tree.cond, env, syms.booleanType);
893 attribStat(tree.body, env.dup(tree));
894 result = null;
895 }
896
897 public void visitForLoop(JCForLoop tree) {
898 Env<AttrContext> loopEnv =
899 env.dup(env.tree, env.info.dup(env.info.scope.dup()));
900 attribStats(tree.init, loopEnv);
901 if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType);
902 loopEnv.tree = tree; // before, we were not in loop!
903 attribStats(tree.step, loopEnv);
904 attribStat(tree.body, loopEnv);
905 loopEnv.info.scope.leave();
906 result = null;
907 }
908
909 public void visitForeachLoop(JCEnhancedForLoop tree) {
910 Env<AttrContext> loopEnv =
911 env.dup(env.tree, env.info.dup(env.info.scope.dup()));
912 attribStat(tree.var, loopEnv);
913 Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));
914 chk.checkNonVoid(tree.pos(), exprType);
915 Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
916 if (elemtype == null) {
917 // or perhaps expr implements Iterable<T>?
918 Type base = types.asSuper(exprType, syms.iterableType.tsym);
919 if (base == null) {
920 log.error(tree.expr.pos(), "foreach.not.applicable.to.type");
921 elemtype = types.createErrorType(exprType);
922 } else {
923 List<Type> iterableParams = base.allparams();
924 elemtype = iterableParams.isEmpty()
925 ? syms.objectType
926 : types.upperBound(iterableParams.head);
927 }
928 }
929 chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
930 loopEnv.tree = tree; // before, we were not in loop!
931 attribStat(tree.body, loopEnv);
932 loopEnv.info.scope.leave();
933 result = null;
934 }
935
936 public void visitLabelled(JCLabeledStatement tree) {
937 // Check that label is not used in an enclosing statement
938 Env<AttrContext> env1 = env;
939 while (env1 != null && env1.tree.getTag() != JCTree.CLASSDEF) {
940 if (env1.tree.getTag() == JCTree.LABELLED &&
941 ((JCLabeledStatement) env1.tree).label == tree.label) {
942 log.error(tree.pos(), "label.already.in.use",
943 tree.label);
944 break;
945 }
946 env1 = env1.next;
947 }
948
949 attribStat(tree.body, env.dup(tree));
950 result = null;
951 }
952
953 public void visitSwitch(JCSwitch tree) {
954 Type seltype = attribExpr(tree.selector, env);
955
956 Env<AttrContext> switchEnv =
957 env.dup(tree, env.info.dup(env.info.scope.dup()));
958
959 boolean enumSwitch =
960 allowEnums &&
961 (seltype.tsym.flags() & Flags.ENUM) != 0;
962 if (!enumSwitch)
963 seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
964
965 // Attribute all cases and
966 // check that there are no duplicate case labels or default clauses.
967 Set<Object> labels = new HashSet<Object>(); // The set of case labels.
968 boolean hasDefault = false; // Is there a default label?
969 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
970 JCCase c = l.head;
971 Env<AttrContext> caseEnv =
972 switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
973 if (c.pat != null) {
974 if (enumSwitch) {
975 Symbol sym = enumConstant(c.pat, seltype);
976 if (sym == null) {
977 log.error(c.pat.pos(), "enum.const.req");
978 } else if (!labels.add(sym)) {
979 log.error(c.pos(), "duplicate.case.label");
980 }
981 } else {
982 Type pattype = attribExpr(c.pat, switchEnv, seltype);
983 if (pattype.tag != ERROR) {
984 if (pattype.constValue() == null) {
985 log.error(c.pat.pos(), "const.expr.req");
986 } else if (labels.contains(pattype.constValue())) {
987 log.error(c.pos(), "duplicate.case.label");
988 } else {
989 labels.add(pattype.constValue());
990 }
991 }
992 }
993 } else if (hasDefault) {
994 log.error(c.pos(), "duplicate.default.label");
995 } else {
996 hasDefault = true;
997 }
998 attribStats(c.stats, caseEnv);
999 caseEnv.info.scope.leave();
1000 addVars(c.stats, switchEnv.info.scope);
1001 }
1002
1003 switchEnv.info.scope.leave();
1004 result = null;
1005 }
1006 // where
1007 /** Add any variables defined in stats to the switch scope. */
1008 private static void addVars(List<JCStatement> stats, Scope switchScope) {
1009 for (;stats.nonEmpty(); stats = stats.tail) {
1010 JCTree stat = stats.head;
1011 if (stat.getTag() == JCTree.VARDEF)
1012 switchScope.enter(((JCVariableDecl) stat).sym);
1013 }
1014 }
1015 // where
1016 /** Return the selected enumeration constant symbol, or null. */
1017 private Symbol enumConstant(JCTree tree, Type enumType) {
1018 if (tree.getTag() != JCTree.IDENT) {
1019 log.error(tree.pos(), "enum.label.must.be.unqualified.enum");
1020 return syms.errSymbol;
1021 }
1022 JCIdent ident = (JCIdent)tree;
1023 Name name = ident.name;
1024 for (Scope.Entry e = enumType.tsym.members().lookup(name);
1025 e.scope != null; e = e.next()) {
1026 if (e.sym.kind == VAR) {
1027 Symbol s = ident.sym = e.sym;
1028 ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated
1029 ident.type = s.type;
1030 return ((s.flags_field & Flags.ENUM) == 0)
1031 ? null : s;
1032 }
1033 }
1034 return null;
1035 }
1036
1037 public void visitSynchronized(JCSynchronized tree) {
1038 chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));
1039 attribStat(tree.body, env);
1040 result = null;
1041 }
1042
1043 public void visitTry(JCTry tree) {
1044 // Attribute body
1045 attribStat(tree.body, env.dup(tree, env.info.dup()));
1046
1047 // Attribute catch clauses
1048 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1049 JCCatch c = l.head;
1050 Env<AttrContext> catchEnv =
1051 env.dup(c, env.info.dup(env.info.scope.dup()));
1052 Type ctype = attribStat(c.param, catchEnv);
1053 if (c.param.type.tsym.kind == Kinds.VAR) {
1054 c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
1055 }
1056 chk.checkType(c.param.vartype.pos(),
1057 chk.checkClassType(c.param.vartype.pos(), ctype),
1058 syms.throwableType);
1059 attribStat(c.body, catchEnv);
1060 catchEnv.info.scope.leave();
1061 }
1062
1063 // Attribute finalizer
1064 if (tree.finalizer != null) attribStat(tree.finalizer, env);
1065 result = null;
1066 }
1067
1068 public void visitConditional(JCConditional tree) {
1069 attribExpr(tree.cond, env, syms.booleanType);
1070 attribExpr(tree.truepart, env);
1071 attribExpr(tree.falsepart, env);
1072 result = check(tree,
1073 capture(condType(tree.pos(), tree.cond.type,
1074 tree.truepart.type, tree.falsepart.type)),
1075 VAL, pkind, pt);
1076 }
1077 //where
1078 /** Compute the type of a conditional expression, after
1079 * checking that it exists. See Spec 15.25.
1080 *
1081 * @param pos The source position to be used for
1082 * error diagnostics.
1083 * @param condtype The type of the expression's condition.
1084 * @param thentype The type of the expression's then-part.
1085 * @param elsetype The type of the expression's else-part.
1086 */
1087 private Type condType(DiagnosticPosition pos,
1088 Type condtype,
1089 Type thentype,
1090 Type elsetype) {
1091 Type ctype = condType1(pos, condtype, thentype, elsetype);
1092
1093 // If condition and both arms are numeric constants,
1094 // evaluate at compile-time.
1095 return ((condtype.constValue() != null) &&
1096 (thentype.constValue() != null) &&
1097 (elsetype.constValue() != null))
1098 ? cfolder.coerce(condtype.isTrue()?thentype:elsetype, ctype)
1099 : ctype;
1100 }
1101 /** Compute the type of a conditional expression, after
1102 * checking that it exists. Does not take into
1103 * account the special case where condition and both arms
1104 * are constants.
1105 *
1106 * @param pos The source position to be used for error
1107 * diagnostics.
1108 * @param condtype The type of the expression's condition.
1109 * @param thentype The type of the expression's then-part.
1110 * @param elsetype The type of the expression's else-part.
1111 */
1112 private Type condType1(DiagnosticPosition pos, Type condtype,
1113 Type thentype, Type elsetype) {
1114 // If same type, that is the result
1115 if (types.isSameType(thentype, elsetype))
1116 return thentype.baseType();
1117
1118 Type thenUnboxed = (!allowBoxing || thentype.isPrimitive())
1119 ? thentype : types.unboxedType(thentype);
1120 Type elseUnboxed = (!allowBoxing || elsetype.isPrimitive())
1121 ? elsetype : types.unboxedType(elsetype);
1122
1123 // Otherwise, if both arms can be converted to a numeric
1124 // type, return the least numeric type that fits both arms
1125 // (i.e. return larger of the two, or return int if one
1126 // arm is short, the other is char).
1127 if (thenUnboxed.isPrimitive() && elseUnboxed.isPrimitive()) {
1128 // If one arm has an integer subrange type (i.e., byte,
1129 // short, or char), and the other is an integer constant
1130 // that fits into the subrange, return the subrange type.
1131 if (thenUnboxed.tag < INT && elseUnboxed.tag == INT &&
1132 types.isAssignable(elseUnboxed, thenUnboxed))
1133 return thenUnboxed.baseType();
1134 if (elseUnboxed.tag < INT && thenUnboxed.tag == INT &&
1135 types.isAssignable(thenUnboxed, elseUnboxed))
1136 return elseUnboxed.baseType();
1137
1138 for (int i = BYTE; i < VOID; i++) {
1139 Type candidate = syms.typeOfTag[i];
1140 if (types.isSubtype(thenUnboxed, candidate) &&
1141 types.isSubtype(elseUnboxed, candidate))
1142 return candidate;
1143 }
1144 }
1145
1146 // Those were all the cases that could result in a primitive
1147 if (allowBoxing) {
1148 if (thentype.isPrimitive())
1149 thentype = types.boxedClass(thentype).type;
1150 if (elsetype.isPrimitive())
1151 elsetype = types.boxedClass(elsetype).type;
1152 }
1153
1154 if (types.isSubtype(thentype, elsetype))
1155 return elsetype.baseType();
1156 if (types.isSubtype(elsetype, thentype))
1157 return thentype.baseType();
1158
1159 if (!allowBoxing || thentype.tag == VOID || elsetype.tag == VOID) {
1160 log.error(pos, "neither.conditional.subtype",
1161 thentype, elsetype);
1162 return thentype.baseType();
1163 }
1164
1165 // both are known to be reference types. The result is
1166 // lub(thentype,elsetype). This cannot fail, as it will
1167 // always be possible to infer "Object" if nothing better.
1168 return types.lub(thentype.baseType(), elsetype.baseType());
1169 }
1170
1171 public void visitIf(JCIf tree) {
1172 attribExpr(tree.cond, env, syms.booleanType);
1173 attribStat(tree.thenpart, env);
1174 if (tree.elsepart != null)
1175 attribStat(tree.elsepart, env);
1176 chk.checkEmptyIf(tree);
1177 result = null;
1178 }
1179
1180 public void visitExec(JCExpressionStatement tree) {
1181 attribExpr(tree.expr, env);
1182 result = null;
1183 }
1184
1185 public void visitBreak(JCBreak tree) {
1186 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1187 result = null;
1188 }
1189
1190 public void visitContinue(JCContinue tree) {
1191 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
1192 result = null;
1193 }
1194 //where
1195 /** Return the target of a break or continue statement, if it exists,
1196 * report an error if not.
1197 * Note: The target of a labelled break or continue is the
1198 * (non-labelled) statement tree referred to by the label,
1199 * not the tree representing the labelled statement itself.
1200 *
1201 * @param pos The position to be used for error diagnostics
1202 * @param tag The tag of the jump statement. This is either
1203 * Tree.BREAK or Tree.CONTINUE.
1204 * @param label The label of the jump statement, or null if no
1205 * label is given.
1206 * @param env The environment current at the jump statement.
1207 */
1208 private JCTree findJumpTarget(DiagnosticPosition pos,
1209 int tag,
1210 Name label,
1211 Env<AttrContext> env) {
1212 // Search environments outwards from the point of jump.
1213 Env<AttrContext> env1 = env;
1214 LOOP:
1215 while (env1 != null) {
1216 switch (env1.tree.getTag()) {
1217 case JCTree.LABELLED:
1218 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
1219 if (label == labelled.label) {
1220 // If jump is a continue, check that target is a loop.
1221 if (tag == JCTree.CONTINUE) {
1222 if (labelled.body.getTag() != JCTree.DOLOOP &&
1223 labelled.body.getTag() != JCTree.WHILELOOP &&
1224 labelled.body.getTag() != JCTree.FORLOOP &&
1225 labelled.body.getTag() != JCTree.FOREACHLOOP)
1226 log.error(pos, "not.loop.label", label);
1227 // Found labelled statement target, now go inwards
1228 // to next non-labelled tree.
1229 return TreeInfo.referencedStatement(labelled);
1230 } else {
1231 return labelled;
1232 }
1233 }
1234 break;
1235 case JCTree.DOLOOP:
1236 case JCTree.WHILELOOP:
1237 case JCTree.FORLOOP:
1238 case JCTree.FOREACHLOOP:
1239 if (label == null) return env1.tree;
1240 break;
1241 case JCTree.SWITCH:
1242 if (label == null && tag == JCTree.BREAK) return env1.tree;
1243 break;
1244 case JCTree.METHODDEF:
1245 case JCTree.CLASSDEF:
1246 break LOOP;
1247 default:
1248 }
1249 env1 = env1.next;
1250 }
1251 if (label != null)
1252 log.error(pos, "undef.label", label);
1253 else if (tag == JCTree.CONTINUE)
1254 log.error(pos, "cont.outside.loop");
1255 else
1256 log.error(pos, "break.outside.switch.loop");
1257 return null;
1258 }
1259
1260 public void visitReturn(JCReturn tree) {
1261 // Check that there is an enclosing method which is
1262 // nested within than the enclosing class.
1263 if (env.enclMethod == null ||
1264 env.enclMethod.sym.owner != env.enclClass.sym) {
1265 log.error(tree.pos(), "ret.outside.meth");
1266
1267 } else {
1268 // Attribute return expression, if it exists, and check that
1269 // it conforms to result type of enclosing method.
1270 Symbol m = env.enclMethod.sym;
1271 if (m.type.getReturnType().tag == VOID) {
1272 if (tree.expr != null)
1273 log.error(tree.expr.pos(),
1274 "cant.ret.val.from.meth.decl.void");
1275 } else if (tree.expr == null) {
1276 log.error(tree.pos(), "missing.ret.val");
1277 } else {
1278 attribExpr(tree.expr, env, m.type.getReturnType());
1279 }
1280 }
1281
1282 if (!isClassCloserThanBrackets()) {
1283 log.error(tree.pos(), "no.return.in.brackets");
1284 }
1285 result = null;
1286 }
1287
1288 protected boolean checkRuntimeExceptionEscapeSafe(ClassSymbol clazz) {
1289 Type stype = clazz.type;
1290 while(stype!=Type.noType) {
1291 if (options.get("-verbose") != null) System.out.println("\ttype: "+stype);
1292 if (stype==syms.runtimeExceptionType) return true; // we have made it all the way to RuntimeException, this is separable
1293 Scope s = stype.tsym.members();
1294 for(Symbol member: s.getElements()) {
1295 if (member.kind==VAR) {
1296 VarSymbol v = (VarSymbol)member;
1297 if (v.getKind()==ElementKind.FIELD) {
1298 if (options.get("-verbose") != null) System.out.println("\tfield "+v+", type "+v.type);
1299 if (!isPrimitiveOrBoxedOrArrayThereof(v.type)) return false;
1300 }
1301 }
1302 else if (member.kind==MTH) {
1303 MethodSymbol m = (MethodSymbol)member;
1304 if (options.get("-verbose") != null) System.out.println("\tmethod "+m+", return type "+m.getReturnType());
1305 if ((m.getReturnType()!=syms.voidType) &&
1306 (m.getReturnType()!=syms.javaLangVoidType) &&
1307 (!isPrimitiveOrBoxedOrArrayThereof(m.getReturnType()))) return false;
1308 }
1309 }
1310 stype = clazz.getSuperclass();
1311 clazz = (ClassSymbol)stype.tsym;
1312 }
1313 // we didn't end up at RuntimeException, this is unsafe
1314 return false;
1315 }
1316
1317 public void visitThrow(JCThrow tree) {
1318 attribExpr(tree.expr, env, syms.throwableType);
1319 result = null;
1320 // mgr: escape safety
1321 // in an escape, you can only throw exceptions
1322 // - whose class is RuntimeException or a subclass
1323 // - that only have fields that are a) primitive, b) boxed, c) strings, or d) arrays thereof
1324 // - that only have methods that return a) primitive, b) boxed, c) strings, or d) arrays thereof
1325 if (tree.expr.type.tag==TypeTags.BOT) { return; } // throw null is allowed
1326 if (!checkRuntimeExceptionEscapeSafe((ClassSymbol)((ClassType)tree.expr.type).tsym)) {
1327 if (env.enclMethod==null) {
1328 // throw in an initializer
1329 // this is an an error if we have any separable contructors
1330 env.enclClass.containsNonEscapeSafeInitializers = true;
1331 }
1332 else {
1333 if (env.isEscapeSafe()) {
1334 // error: throw in an separable method or in an escape
1335 log.error(tree.pos(), "no.unsafe.throw.in.escapesafe");
1336 }
1337 }
1338 }
1339 }
1340
1341 public void visitAssert(JCAssert tree) {
1342 attribExpr(tree.cond, env, syms.booleanType);
1343 if (tree.detail != null) {
1344 chk.checkNonVoid(tree.detail.pos(), attribExpr(tree.detail, env));
1345 }
1346 result = null;
1347 }
1348
1349 /** Return true if we are inside brackets, but there is an anonymous inner class even closer:
1350 * <| ... new Foo() { HERE } ... |>
1351 * Also returns true if we aren't inside brackets at all.
1352 */
1353 protected boolean isClassCloserThanBrackets() {
1354 if (env.enclBrackets.size()==0) return true;
1355 JCExpression head = env.enclBrackets.head;
1356
1357 // find the environment where the bracket was created
1358 Env<AttrContext> bracketEnclEnv = null;
1359 Env<AttrContext> e = env;
1360 while(e!=null) {
1361 if (e.tree==head) {
1362 bracketEnclEnv = e;
1363 break;
1364 }
1365 e = e.next;
1366 }
1367 // see if we get to env.enclClass before we get to bracketEnclEnv
1368 boolean found = false;
1369 e = env;
1370 while(e!=null) {
1371 if (e==bracketEnclEnv) {
1372 break;
1373 }
1374 if ((e.info.scope.owner instanceof ClassSymbol) &&
1375 (((ClassSymbol)e.info.scope.owner)==env.enclClass.sym)) {
1376 found = true;
1377 break;
1378 }
1379 e = e.next;
1380 }
1381 return found; // method closer
1382 }
1383
1384 protected void setClosestBracketUnsafe(JCTree tree) {
1385 if (env.enclBrackets.size()>0) {
1386 if (isClassCloserThanBrackets()) return; // inner class, this is safe
1387
1388 if (options.get("-verbose") != null) { System.out.println("Unsafe: "+tree); }
1389
1390 JCExpression head = env.enclBrackets.head;
1391 if (head instanceof JCBracketExpr) {
1392 ((JCBracketExpr)head).safe = false;
1393 }
1394 else if (head instanceof JCBracketStat) {
1395 ((JCBracketStat)head).safe = false;
1396 }
1397 else {
1398 throw new AssertionError("Expected JCBracketExpr or JCBracketStat in enclBrackets, was "+head.getClass().getSimpleName());
1399 }
1400 }
1401 }
1402
1403 /** Visitor method for method invocations.
1404 * NOTE: The method part of an application will have in its type field
1405 * the return type of the method, not the method's type itself!
1406 */
1407 public void visitApply(JCMethodInvocation tree) {
1408 // The local environment of a method application is
1409 // a new environment nested in the current one.
1410 Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
1411
1412 // The types of the actual method arguments.
1413 List<Type> argtypes = null;
1414
1415 // The types of the actual method type arguments.
1416 List<Type> typeargtypes = null;
1417
1418 Name methName = TreeInfo.name(tree.meth);
1419 Type site = null; // non-null only iff isConstructorCall==true
1420
1421 boolean isConstructorCall =
1422 methName == names._this || methName == names._super;
1423
1424 if (isConstructorCall) {
1425 // We are seeing a ...this(...) or ...super(...) call.
1426 // Check that this is the first statement in a constructor.
1427 if (checkFirstConstructorStat(tree, env)) {
1428 // Record the fact
1429 // that this is a constructor call (using isSelfCall).
1430 localEnv.info.isSelfCall = true;
1431
1432 // Attribute arguments, yielding list of argument types.
1433 argtypes = attribArgs(tree.args, localEnv);
1434 typeargtypes = attribTypes(tree.typeargs, localEnv);
1435
1436 // Variable `site' points to the class in which the called
1437 // constructor is defined.
1438 site = env.enclClass.sym.type;
1439 if (methName == names._super) {
1440 if (site == syms.objectType) {
1441 log.error(tree.meth.pos(), "no.superclass", site);
1442 site = types.createErrorType(syms.objectType);
1443 } else {
1444 site = types.supertype(site);
1445 }
1446 }
1447
1448 if (site.tag == CLASS) {
1449 if (site.getEnclosingType().tag == CLASS) {
1450 // we are calling a nested class
1451
1452 if (tree.meth.getTag() == JCTree.SELECT) {
1453 JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
1454
1455 // We are seeing a prefixed call, of the form
1456 // <expr>.super(...).
1457 // Check that the prefix expression conforms
1458 // to the outer instance type of the class.
1459 chk.checkRefType(qualifier.pos(),
1460 attribExpr(qualifier, localEnv,
1461 site.getEnclosingType()));
1462 } else if (methName == names._super) {
1463 // qualifier omitted; check for existence
1464 // of an appropriate implicit qualifier.
1465 rs.resolveImplicitThis(tree.meth.pos(),
1466 localEnv, site);
1467 }
1468 } else if (tree.meth.getTag() == JCTree.SELECT) {
1469 log.error(tree.meth.pos(), "illegal.qual.not.icls",
1470 site.tsym);
1471 }
1472
1473 // if we're calling a java.lang.Enum constructor,
1474 // prefix the implicit String and int parameters
1475 if (site.tsym == syms.enumSym && allowEnums)
1476 argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
1477
1478 // Resolve the called constructor under the assumption
1479 // that we are referring to a superclass instance of the
1480 // current instance (JLS ???).
1481 boolean selectSuperPrev = localEnv.info.selectSuper;
1482 localEnv.info.selectSuper = true;
1483 localEnv.info.varArgs = false;
1484 Symbol sym = rs.resolveConstructor(
1485 tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
1486 localEnv.info.selectSuper = selectSuperPrev;
1487
1488 // Set method symbol to resolved constructor...
1489 TreeInfo.setSymbol(tree.meth, sym);
1490
1491 // ...and check that it is legal in the current context.
1492 // (this will also set the tree's type)
1493 Type mpt = newMethTemplate(argtypes, typeargtypes);
1494 checkId(tree.meth, site, sym, localEnv, MTH,
1495 mpt, tree.varargsElement != null);
1496 }
1497 // Otherwise, `site' is an error type and we do nothing
1498 }
1499 result = tree.type = syms.voidType;
1500 } else {
1501 // Otherwise, we are seeing a regular method call.
1502 // Attribute the arguments, yielding list of argument types, ...
1503 argtypes = attribArgs(tree.args, localEnv);
1504 typeargtypes = attribTypes(tree.typeargs, localEnv);
1505
1506 // ... and attribute the method using as a prototype a methodtype
1507 // whose formal argument types is exactly the list of actual
1508 // arguments (this will also set the method symbol).
1509 Type mpt = newMethTemplate(argtypes, typeargtypes);
1510 localEnv.info.varArgs = false;
1511 Type mtype = attribExpr(tree.meth, localEnv, mpt);
1512 if (localEnv.info.varArgs)
1513 assert mtype.isErroneous() || tree.varargsElement != null;
1514
1515 // Compute the result type.
1516 Type restype = mtype.getReturnType();
1517 assert restype.tag != WILDCARD : mtype;
1518
1519 // as a special case, array.clone() has a result that is
1520 // the same as static type of the array being cloned
1521 if (tree.meth.getTag() == JCTree.SELECT &&
1522 allowCovariantReturns &&
1523 methName == names.clone &&
1524 types.isArray(((JCFieldAccess) tree.meth).selected.type))
1525 restype = ((JCFieldAccess) tree.meth).selected.type;
1526
1527 // as a special case, x.getClass() has type Class<? extends |X|>
1528 if (allowGenerics &&
1529 methName == names.getClass && tree.args.isEmpty()) {
1530 Type qualifier = (tree.meth.getTag() == JCTree.SELECT)
1531 ? ((JCFieldAccess) tree.meth).selected.type
1532 : env.enclClass.sym.type;
1533 restype = new
1534 ClassType(restype.getEnclosingType(),
1535 List.<Type>of(new WildcardType(types.erasure(qualifier),
1536 BoundKind.EXTENDS,
1537 syms.boundClass)),
1538 restype.tsym);
1539 }
1540
1541 // Check that value of resulting type is admissible in the
1542 // current context. Also, capture the return type
1543 result = check(tree, capture(restype), VAL, pkind, pt);
1544 }
1545
1546 // mgr: escape safety check
1547 // the meth AST is either a JCIdent (for calls within the same class) or a JCFieldAccess
1548 // System.out.println("visitApply: "+tree+" isCtor? "+isConstructorCall);
1549 boolean calledMethodEscapeSafe = false;
1550 if (tree.meth instanceof JCIdent) {
1551 JCIdent ident = (JCIdent)tree.meth;
1552 if (isConstructorCall && (ident.sym instanceof MethodSymbol) &&
1553 (((((MethodSymbol)ident.sym).owner.toString().equals("java.lang.Object")) &&
1554 (((MethodSymbol)ident.sym).type.toString().equals("()void")) &&
1555 (((MethodSymbol)ident.sym).name.toString().equals("<init>"))) ||
1556 ((((MethodSymbol)ident.sym).owner.toString().equals("java.lang.RuntimeException")) && // allow RuntimeException
1557 (((MethodSymbol)ident.sym).name.toString().equals("<init>"))) ||
1558 ((((MethodSymbol)ident.sym).owner.toString().equals("edu.rice.cs.mint.runtime.ClassCode")) && // allow ClassCode
1559 (((MethodSymbol)ident.sym).name.toString().equals("<init>"))) ||
1560 ((((MethodSymbol)ident.sym).owner.toString().equals("edu.rice.cs.mint.runtime.FieldCode")) && // allow FieldCode
1561 (((MethodSymbol)ident.sym).name.toString().equals("<init>"))))) {
1562 calledMethodEscapeSafe = true;
1563 }
1564 else if (isConstructorCall && (ident.sym instanceof MethodSymbol) &&
1565 ((ident.sym.flags() & GENERATEDCONSTR)!=0)) {
1566 // generated ctor
1567 calledMethodEscapeSafe = checkDefaultCtorsEscapeSafe((MethodSymbol)ident.sym);
1568 }
1569 else {
1570 calledMethodEscapeSafe = ((ident.sym.flags() & SEPARABLE)!=0);
1571 }
1572 // System.out.println("\ttree.meth.sym = "+ident.sym+" separable? "+calledMethodEscapeSafe+" generated? "+((ident.sym.flags() & GENERATEDCONSTR)!=0));
1573 // System.out.println("\t"+((MethodSymbol)ident.sym).owner+" "+((MethodSymbol)ident.sym).type+" "+((MethodSymbol)ident.sym).name);
1574 }
1575 else if (tree.meth instanceof JCFieldAccess) {
1576 JCFieldAccess fa = (JCFieldAccess)tree.meth;
1577 if ((fa.selected instanceof JCIdent) && (((JCIdent)fa.selected).name==names._this)) {
1578 if ((fa.sym.flags() & STATIC)!=0) {
1579 // this.x access to a static x
1580 calledMethodEscapeSafe = ((fa.sym.flags() & SEPARABLE)!=0);
1581 }
1582 }
1583 else if ((fa.sym instanceof MethodSymbol) &&
1584 ((((MethodSymbol)fa.sym).owner.toString().equals("edu.rice.cs.mint.runtime.ClassCode")) ||
1585 (((MethodSymbol)fa.sym).owner.toString().equals("edu.rice.cs.mint.runtime.FieldCode")))) {
1586 calledMethodEscapeSafe = true;
1587 }
1588 else {
1589 // not a this.x access and not a call to our reflection code
1590 calledMethodEscapeSafe = ((fa.sym.flags() & SEPARABLE)!=0);
1591 }
1592 // System.out.println("\ttree.meth.sym = "+fa.sym+" separable? "+calledMethodEscapeSafe+" generated? "+((fa.sym.flags() & GENERATEDCONSTR)!=0));
1593 }
1594 else {
1595 throw new AssertionError("Expected JCIdent or JCFieldAccess in method invocation, was "+tree.meth.getClass().getSimpleName());
1596 }
1597
1598 if (!calledMethodEscapeSafe) setClosestBracketUnsafe(tree);
1599
1600 // only emit "cannot call not separable from escape/separable" errors if we are in a method, not in brackets
1601 // if we are in brackets, this would not be an error, it would just make code be Code<T>, not SafeCode<T>
1602 if (isClassCloserThanBrackets()) {
1603 if (env.enclMethod==null) {
1604 // method call in an initializer block
1605 if (!calledMethodEscapeSafe) {
1606 setClosestBracketUnsafe(tree);
1607 if (env.escape!=null) {
1608 // error: calling a non-separable method from inside an escape in an initializer block
1609 String callee = TreeInfo.name(tree.meth).toString();
1610 if (isConstructorCall) {
1611 callee = site.toString();
1612 }
1613 StringBuilder sb = new StringBuilder(callee);
1614 sb.append('(');
1615 if (argtypes!=null) {
1616 boolean first = true;
1617 for(Type t: argtypes) {
1618 if (first) first = false;
1619 else sb.append(',');
1620 sb.append(t);
1621 }
1622 }
1623 sb.append(')');
1624 callee = sb.toString();
1625 log.error(tree.pos(),"cannot.call.not.escapesafe.in.escape", callee);
1626 }
1627 else {
1628 // maybe error, depending on constructors: calling a non-separable method from an initializer block
1629 env.enclClass.containsNonEscapeSafeInitializers = true;
1630 }
1631 }
1632 }
1633 else {
1634 boolean currentMethodEscapeSafe = ((env.enclMethod.sym.flags() & SEPARABLE)!=0);
1635 if (env.isEscapeSafe ()) {
1636 if (!calledMethodEscapeSafe &&
1637 (site != syms.objectType)) { // allow super call to Object
1638 String callee = TreeInfo.name(tree.meth).toString();
1639 if (isConstructorCall) {
1640 callee = site.toString();
1641 }
1642 StringBuilder sb = new StringBuilder(callee);
1643 sb.append('(');
1644 if (argtypes!=null) {
1645 boolean first = true;
1646 for(Type t: argtypes) {
1647 if (first) first = false;
1648 else sb.append(',');
1649 sb.append(t);
1650 }
1651 }
1652 sb.append(')');
1653 callee = sb.toString();
1654 String caller = env.enclMethod.name.toString();
1655 if (env.enclMethod.name==names.init) {
1656 caller = env.enclClass.sym.toString();
1657 }
1658 if (env.escape==null) {
1659 // within separable method
1660 sb.setLength(0);
1661 sb.append(caller);
1662 sb.append('(');
1663 boolean first = true;
1664 for(JCVariableDecl decl: env.enclMethod.params) {
1665 if (first) first = false;
1666 else sb.append(',');
1667 sb.append(decl.vartype);
1668 }
1669 sb.append(')');
1670 caller = sb.toString();
1671 log.error(tree.pos(),"not.escapesafe.called.from.escapesafe", callee, caller);
1672 }
1673 else {
1674 // within escape
1675 log.error(tree.pos(),"cannot.call.not.escapesafe.in.escape", callee);
1676 }
1677 }
1678 }
1679 }
1680 }
1681 // mgr: csp safety
1682 if (env.enclBrackets.size()>0) {
1683 boolean nonStaticCall = false;
1684 String method = null;
1685 if (tree.meth instanceof JCIdent) {
1686 JCIdent ident = (JCIdent)tree.meth;
1687 if ((ident.name!=names._this) && (ident.name!=names._super)) {
1688 nonStaticCall = ((ident.sym.flags() & STATIC)==0);
1689 method = ident.name.toString();
1690 }
1691 }
1692 else if (tree.meth instanceof JCFieldAccess) {
1693 JCFieldAccess fa = (JCFieldAccess)tree.meth;
1694 Type t = env.enclClass.sym.type;
1695 while(t!=null) {
1696 if (fa.sym.owner.type.toString().equals(t.toString())) {
1697 nonStaticCall = ((fa.sym.flags() & STATIC)==0);
1698 method = fa.sym.name.toString();
1699 break;
1700 }
1701 t = t.getEnclosingType();
1702 }
1703 }
1704 else {
1705 throw new AssertionError("Expected JCIdent or JCFieldAccess in method invocation, was "+tree.meth.getClass().getSimpleName());
1706 }
1707
1708 if (nonStaticCall) {
1709 log.error(tree.pos(), "may.not.directly.access.enclosing", method);
1710 }
1711 }
1712
1713 // System.out.println("\tenv.enclMethod = "+env.enclMethod+" separable? "+currentMethodEscapeSafe);
1714 chk.validate(tree.typeargs, localEnv);
1715 }
1716 //where
1717 /** Check that given application node appears as first statement
1718 * in a constructor call.
1719 * @param tree The application node
1720 * @param env The environment current at the application.
1721 */
1722 boolean checkFirstConstructorStat(JCMethodInvocation tree, Env<AttrContext> env) {
1723 JCMethodDecl enclMethod = env.enclMethod;
1724 if (enclMethod != null && enclMethod.name == names.init) {
1725 JCBlock body = enclMethod.body;
1726 if (body.stats.head.getTag() == JCTree.EXEC &&
1727 ((JCExpressionStatement) body.stats.head).expr == tree)
1728 return true;
1729 }
1730 log.error(tree.pos(),"call.must.be.first.stmt.in.ctor",
1731 TreeInfo.name(tree.meth));
1732 return false;
1733 }
1734
1735 /** Obtain a method type with given argument types.
1736 */
1737 Type newMethTemplate(List<Type> argtypes, List<Type> typeargtypes) {
1738 MethodType mt = new MethodType(argtypes, null, null, syms.methodClass);
1739 return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt);
1740 }
1741
1742 public void visitNewClass(JCNewClass tree) {
1743 Type owntype = types.createErrorType(tree.type);
1744
1745 // The local environment of a class creation is
1746 // a new environment nested in the current one.
1747 Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
1748
1749 // The anonymous inner class definition of the new expression,
1750 // if one is defined by it.
1751 JCClassDecl cdef = tree.def;
1752
1753 // If enclosing class is given, attribute it, and
1754 // complete class name to be fully qualified
1755 JCExpression clazz = tree.clazz; // Class field following new
1756 JCExpression clazzid = // Identifier in class field
1757 (clazz.getTag() == JCTree.TYPEAPPLY)
1758 ? ((JCTypeApply) clazz).clazz
1759 : clazz;
1760
1761 JCExpression clazzid1 = clazzid; // The same in fully qualified form
1762
1763 if (tree.encl != null) {
1764 // We are seeing a qualified new, of the form
1765 // <expr>.new C <...> (...) ...
1766 // In this case, we let clazz stand for the name of the
1767 // allocated class C prefixed with the type of the qualifier
1768 // expression, so that we can
1769 // resolve it with standard techniques later. I.e., if
1770 // <expr> has type T, then <expr>.new C <...> (...)
1771 // yields a clazz T.C.
1772 Type encltype = chk.checkRefType(tree.encl.pos(),
1773 attribExpr(tree.encl, env));
1774 clazzid1 = make.at(clazz.pos).Select(make.Type(encltype),
1775 ((JCIdent) clazzid).name);
1776 if (clazz.getTag() == JCTree.TYPEAPPLY)
1777 clazz = make.at(tree.pos).
1778 TypeApply(clazzid1,
1779 ((JCTypeApply) clazz).arguments);
1780 else
1781 clazz = clazzid1;
1782 // System.out.println(clazz + " generated.");//DEBUG
1783 }
1784
1785 // Attribute clazz expression and store
1786 // symbol + type back into the attributed tree.
1787 Type clazztype = chk.checkClassType(
1788 tree.clazz.pos(), attribType(clazz, env), true);
1789 final Type origClazzType = clazztype;
1790 Symbol origConstructor = null;
1791
1792 chk.validate(clazz, localEnv);
1793 if (tree.encl != null) {
1794 // We have to work in this case to store
1795 // symbol + type back into the attributed tree.
1796 tree.clazz.type = clazztype;
1797 TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1));
1798 clazzid.type = ((JCIdent) clazzid).sym.type;
1799 if (!clazztype.isErroneous()) {
1800 if (cdef != null && clazztype.tsym.isInterface()) {
1801 log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new");
1802 } else if (clazztype.tsym.isStatic()) {
1803 log.error(tree.encl.pos(), "qualified.new.of.static.class", clazztype.tsym);
1804 }
1805 }
1806 } else if (!clazztype.tsym.isInterface() &&
1807 clazztype.getEnclosingType().tag == CLASS) {
1808 // Check for the existence of an apropos outer instance
1809 rs.resolveImplicitThis(tree.pos(), env, clazztype);
1810 }
1811
1812 // Attribute constructor arguments.
1813 List<Type> argtypes = attribArgs(tree.args, localEnv);
1814 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
1815
1816 // If we have made no mistakes in the class type...
1817 if (clazztype.tag == CLASS) {
1818 // Enums may not be instantiated except implicitly
1819 if (allowEnums &&
1820 (clazztype.tsym.flags_field&Flags.ENUM) != 0 &&
1821 (env.tree.getTag() != JCTree.VARDEF ||
1822 (((JCVariableDecl) env.tree).mods.flags&Flags.ENUM) == 0 ||
1823 ((JCVariableDecl) env.tree).init != tree))
1824 log.error(tree.pos(), "enum.cant.be.instantiated");
1825 // Check that class is not abstract
1826 if (cdef == null &&
1827 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
1828 log.error(tree.pos(), "abstract.cant.be.instantiated",
1829 clazztype.tsym);
1830 } else if (cdef != null && clazztype.tsym.isInterface()) {
1831 // Check that no constructor arguments are given to
1832 // anonymous classes implementing an interface
1833 if (!argtypes.isEmpty())
1834 log.error(tree.args.head.pos(), "anon.class.impl.intf.no.args");
1835
1836 if (!typeargtypes.isEmpty())
1837 log.error(tree.typeargs.head.pos(), "anon.class.impl.intf.no.typeargs");
1838
1839 // Error recovery: pretend no arguments were supplied.
1840 argtypes = List.nil();
1841 typeargtypes = List.nil();
1842 }
1843
1844 // Resolve the called constructor under the assumption
1845 // that we are referring to a superclass instance of the
1846 // current instance (JLS ???).
1847 else {
1848 localEnv.info.selectSuper = cdef != null;
1849 localEnv.info.varArgs = false;
1850 tree.constructor = rs.resolveConstructor(
1851 tree.pos(), localEnv, clazztype, argtypes, typeargtypes);
1852 tree.constructorType = checkMethod(clazztype,
1853 tree.constructor,
1854 localEnv,
1855 tree.args,
1856 argtypes,
1857 typeargtypes,
1858 localEnv.info.varArgs);
1859 if (localEnv.info.varArgs)
1860 assert tree.constructorType.isErroneous() || tree.varargsElement != null;
1861 }
1862
1863 origConstructor = tree.constructor;
1864
1865 if (cdef != null) {
1866 // We are seeing an anonymous class instance creation.
1867 // In this case, the class instance creation
1868 // expression
1869 //
1870 // E.new <typeargs1>C<typargs2>(args) { ... }
1871 //
1872 // is represented internally as
1873 //
1874 // E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) .
1875 //
1876 // This expression is then *transformed* as follows:
1877 //
1878 // (1) add a STATIC flag to the class definition
1879 // if the current environment is static
1880 // (2) add an extends or implements clause
1881 // (3) add a constructor.
1882 //
1883 // For instance, if C is a class, and ET is the type of E,
1884 // the expression
1885 //
1886 // E.new <typeargs1>C<typargs2>(args) { ... }
1887 //
1888 // is translated to (where X is a fresh name and typarams is the
1889 // parameter list of the super constructor):
1890 //
1891 // new <typeargs1>X(<*nullchk*>E, args) where
1892 // X extends C<typargs2> {
1893 // <typarams> X(ET e, args) {
1894 // e.<typeargs1>super(args)
1895 // }
1896 // ...
1897 // }
1898 if (Resolve.isStatic(env)) cdef.mods.flags |= STATIC;
1899
1900 if (clazztype.tsym.isInterface()) {
1901 cdef.implementing = List.of(clazz);
1902 } else {
1903 cdef.extending = clazz;
1904 }
1905
1906 attribStat(cdef, localEnv);
1907
1908 // If an outer instance is given,
1909 // prefix it to the constructor arguments
1910 // and delete it from the new expression
1911 if (tree.encl != null && !clazztype.tsym.isInterface()) {
1912 tree.args = tree.args.prepend(makeNullCheck(tree.encl));
1913 argtypes = argtypes.prepend(tree.encl.type);
1914 tree.encl = null;
1915 }
1916
1917 // Reassign clazztype and recompute constructor.
1918 clazztype = cdef.sym.type;
1919 Symbol sym = rs.resolveConstructor(
1920 tree.pos(), localEnv, clazztype, argtypes,
1921 typeargtypes, true, tree.varargsElement != null);
1922 assert sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous();
1923 tree.constructor = sym;
1924 tree.constructorType = checkMethod(clazztype,
1925 tree.constructor,
1926 localEnv,
1927 tree.args,
1928 argtypes,
1929 typeargtypes,
1930 localEnv.info.varArgs);
1931 }
1932
1933 if (tree.constructor != null && tree.constructor.kind == MTH)
1934 owntype = clazztype;
1935 }
1936 result = check(tree, owntype, VAL, pkind, pt);
1937 chk.validate(tree.typeargs, localEnv);
1938
1939 // System.out.println("newClass: owntype = "+owntype+" constructor = "+tree.constructor+
1940 // " separable? "+((tree.constructor.flags() & SEPARABLE)!=0)+
1941 // " generated_ctor? "+((tree.constructor.flags() & GENERATEDCONSTR)!=0));
1942 if (!isClassCloserThanBrackets()) {
1943 if (tree.constructor != null && origConstructor != null && clazztype.tag == CLASS && tree.constructor.kind == MTH &&
1944 (!((cdef!=null) && (origClazzType.tsym.isInterface()))) && // and not an anonymous inner class of an interface
1945 (!((cdef!=null) && ((origConstructor.flags() & SEPARABLE)!=0))) && // and not an anonymous inner class of a class with an separable constructor
1946 (!(((tree.constructor.flags() & GENERATEDCONSTR)!=0) &&
1947 (checkDefaultCtorsEscapeSafe((MethodSymbol)tree.constructor)))) && // and not a generated constructor that is separable
1948 (!((cdef==null) && (tree.constructor.owner.toString().equals("java.lang.Object")) &&
1949 (tree.constructor.type.toString().equals("()void")) &&
1950 (tree.constructor.name.toString().equals("<init>")))) && // and not Object()
1951 (!((cdef==null) && (tree.constructor.owner.toString().equals("java.lang.RuntimeException")) &&
1952 (tree.constructor.name.toString().equals("<init>"))))) { // and not RuntimeException(...)
1953 // mgr: escape safety check
1954 boolean calledMethodEscapeSafe = ((tree.constructor.flags() & SEPARABLE)!=0);
1955 if (!calledMethodEscapeSafe) setClosestBracketUnsafe(tree);
1956 if (env.enclMethod==null) {
1957 // new in an initializer block
1958 if (!calledMethodEscapeSafe) {
1959 if (env.escape!=null) {
1960 // error: calling a non-separable method from inside an escape in an initializer block
1961 StringBuilder sb = new StringBuilder(owntype.toString());
1962 sb.append('(');
1963 if (argtypes!=null) {
1964 boolean first = true;
1965 for(Type t: argtypes) {
1966 if (first) first = false;
1967 else sb.append(',');
1968 sb.append(t);
1969 }
1970 }
1971 sb.append(')');
1972 String callee = sb.toString();
1973 log.error(tree.pos(),"cannot.call.not.escapesafe.in.escape", callee);
1974 }
1975 else {
1976 // maybe error, depending on constructors: calling a non-separable method from an initializer block
1977 env.enclClass.containsNonEscapeSafeInitializers = true;
1978 }
1979 }
1980 }
1981 else {
1982 if (env.isEscapeSafe ()) {
1983 if (!calledMethodEscapeSafe) {
1984 StringBuilder sb = new StringBuilder(owntype.toString());
1985 sb.append('(');
1986 if (argtypes!=null) {
1987 boolean first = true;
1988 for(Type t: argtypes) {
1989 if (first) first = false;
1990 else sb.append(',');
1991 sb.append(t);
1992 }
1993 }
1994 sb.append(')');
1995 String callee = sb.toString();
1996 if (env.escape==null) {
1997 // within separable method
1998 String caller = env.enclMethod.name.toString();
1999 if (env.enclMethod.name==names.init) {
2000 sb.setLength(0);
2001 sb.append(env.enclClass.sym.toString());
2002 sb.append('(');
2003 boolean first = true;
2004 for(JCVariableDecl decl: env.enclMethod.params) {
2005 if (first) first = false;
2006 else sb.append(',');
2007 sb.append(decl.vartype);
2008 }
2009 sb.append(')');
2010 caller = sb.toString();
2011 }
2012 log.error(tree.pos(),"not.escapesafe.called.from.escapesafe", callee, caller);
2013 }
2014 else {
2015 // within escape
2016 log.error(tree.pos(),"cannot.call.not.escapesafe.in.escape", callee);
2017 }
2018 }
2019 }
2020 }
2021 }
2022 }
2023 }
2024 protected boolean checkDefaultCtorsEscapeSafe(MethodSymbol ctor) {
2025 // this is a generated constructor
2026 // check that all the default constructors in the super classes are separable
2027 // System.out.println("ctor: "+ctor+" owner: "+ctor.owner+" "+ctor.owner.getClass().getSimpleName());
2028 ClassSymbol clazz = (ClassSymbol)ctor.owner;
2029 Type stype = clazz.getSuperclass();
2030 while(stype!=Type.noType) {
2031 // System.out.println("\ttype: "+stype);
2032 if ((stype==syms.objectType) ||
2033 (stype==syms.runtimeExceptionType)) return true; // we have made it all the way to Object or RuntimeException, this is separable
2034 Scope s = stype.tsym.members();
2035 boolean found = false;
2036 for(Symbol member: s.getElements()) {
2037 // System.out.println("\t\t"+member);
2038 if (member.isConstructor()) {
2039 MethodSymbol sctor = (MethodSymbol)member;
2040 // System.out.println("\t\t\tctor: "+sctor+" params: "+sctor.params+" names: "+sctor.savedParameterNames+" type: "+sctor.type);
2041 if (sctor.type.asMethodType().argtypes.isEmpty()) {
2042 // this is the default constructor
2043 // make sure it is either generated or separable
2044 boolean generated = ((sctor.flags() & GENERATEDCONSTR)!=0);
2045 boolean escapesafe = ((sctor.flags() & SEPARABLE)!=0);
2046 // System.out.println("\t\t\t\tdefault, generated? "+generated+", separable? "+escapesafe);
2047 if (escapesafe) return true; // if this has been declared separable, then we can stop here
2048 if (!generated) return false; // this is not generated, i.e. it is user-written and NOT separable, we can stop here
2049 // otherwise we need to continue with the superclass
2050 clazz = (ClassSymbol)sctor.owner;
2051 stype = clazz.getSuperclass();
2052 if ((stype==syms.objectType) ||
2053 (stype==syms.runtimeExceptionType)) return true; // we have made it all the way to Object or RuntimeException, this is separable
2054 found = true;
2055 break;
2056 }
2057 }
2058 }
2059 if (!found) {
2060 // didn't find a default ctor!
2061 // throw new AssertionError("Could not find default constructor for "+stype);
2062 return false;
2063 }
2064 }
2065 return true;
2066 }
2067
2068 /** Make an attributed null check tree.
2069 */
2070 public JCExpression makeNullCheck(JCExpression arg) {
2071 // optimization: X.this is never null; skip null check
2072 Name name = TreeInfo.name(arg);
2073 if (name == names._this || name == names._super) return arg;
2074
2075 int optag = JCTree.NULLCHK;
2076 JCUnary tree = make.at(arg.pos).Unary(optag, arg);
2077 tree.operator = syms.nullcheck;
2078 tree.type = arg.type;
2079 return tree;
2080 }
2081
2082 public void visitNewArray(JCNewArray tree) {
2083 Type owntype = types.createErrorType(tree.type);
2084 Type elemtype;
2085 if (tree.elemtype != null) {
2086 elemtype = attribType(tree.elemtype, env);
2087 chk.validate(tree.elemtype, env);
2088 owntype = elemtype;
2089 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
2090 attribExpr(l.head, env, syms.intType);
2091 owntype = new ArrayType(owntype, syms.arrayClass);
2092 }
2093 } else {
2094 // we are seeing an untyped aggregate { ... }
2095 // this is allowed only if the prototype is an array
2096 if (pt.tag == ARRAY) {
2097 elemtype = types.elemtype(pt);
2098 } else {
2099 if (pt.tag != ERROR) {
2100 log.error(tree.pos(), "illegal.initializer.for.type",
2101 pt);
2102 }
2103 elemtype = types.createErrorType(pt);
2104 }
2105 }
2106 if (tree.elems != null) {
2107 attribExprs(tree.elems, env, elemtype);
2108 owntype = new ArrayType(elemtype, syms.arrayClass);
2109 }
2110 if (!types.isReifiable(elemtype))
2111 log.error(tree.pos(), "generic.array.creation");
2112 result = check(tree, owntype, VAL, pkind, pt);
2113 }
2114
2115 public void visitParens(JCParens tree) {
2116 Type owntype = attribTree(tree.expr, env, pkind, pt);
2117 result = check(tree, owntype, pkind, pkind, pt);
2118 Symbol sym = TreeInfo.symbol(tree);
2119 if (sym != null && (sym.kind&(TYP|PCK)) != 0)
2120 log.error(tree.pos(), "illegal.start.of.type");
2121 }
2122
2123 public void visitAssign(JCAssign tree) {
2124 Type owntype = attribTree(tree.lhs, env.dup(tree), VAR, Type.noType);
2125 Type capturedType = capture(owntype);
2126 attribExpr(tree.rhs, env, owntype);
2127 result = check(tree, capturedType, VAL, pkind, pt);
2128
2129 // mgr: escape safety check
2130 checkAssignEscapeSafety(tree.lhs);
2131 }
2132
2133 protected void checkAssignEscapeSafety(JCExpression lhs) {
2134 if (lhs instanceof JCParens) {
2135 checkAssignEscapeSafety(((JCParens)lhs).expr);
2136 return;
2137 }
2138 if (env.enclMethod==null) {
2139 if (lhs instanceof JCIdent) {
2140 JCIdent ident = (JCIdent)lhs;
2141 switch (ident.sym.getKind()) {
2142 case FIELD: {
2143 // do not allow fields unless it is to this in the constructor
2144 // (this is always to this, otherwise it would be a JCFieldAccess
2145 // only need to check if we have a constructor [we know that, we're in an initializer]
2146 // and if the field is non-static)
2147 if ((ident.sym.flags() & STATIC)!=0) {
2148 env.enclClass.containsNonEscapeSafeInitializers = true;
2149 }
2150 break;
2151 }
2152 case PARAMETER:
2153 case LOCAL_VARIABLE: {
2154 // allow parameters and local variables
2155 // if bound inside this escape
2156 if (env.escape!=null) {
2157 Env<AttrContext> defineEnv = env;
2158 Scope defineScope = defineEnv.info.scope.lookup(ident.sym.name).scope;
2159 while(defineScope==null && defineEnv.outer!=null) {
2160 defineEnv = defineEnv.next;
2161 defineScope = defineEnv.info.scope.lookup(ident.sym.name).scope;
2162 }
2163 if (defineEnv.escape!=env.escape) {
2164 env.enclClass.containsNonEscapeSafeInitializers = true;
2165 }
2166 }
2167 else {
2168 // must be inside an separable method
2169 // all parameters and local variables are okay
2170 // System.out.println("\tno escape");
2171 }
2172 break;
2173 }
2174 case PACKAGE:
2175 case ENUM:
2176 case CLASS:
2177 case ANNOTATION_TYPE:
2178 case INTERFACE:
2179 case ENUM_CONSTANT:
2180 case EXCEPTION_PARAMETER:
2181 case METHOD:
2182 case CONSTRUCTOR:
2183 case STATIC_INIT:
2184 case INSTANCE_INIT:
2185 case TYPE_PARAMETER:
2186 case OTHER:
2187 default: // unexpected, don't do anything
2188 break;
2189 }
2190 }
2191 else if (lhs instanceof JCFieldAccess) {
2192 JCFieldAccess fa = (JCFieldAccess)lhs;
2193 if ((fa.selected instanceof JCIdent) && (((JCIdent)fa.selected).name==names._this)) {
2194 if ((fa.sym.flags() & STATIC)!=0) {
2195 // this.x access to a static x
2196 env.enclClass.containsNonEscapeSafeInitializers = true;
2197 }
2198 }
2199 else {
2200 // not a this.x access
2201 env.enclClass.containsNonEscapeSafeInitializers = true;
2202 }
2203 }
2204
2205 else if (lhs instanceof JCArrayAccess) {
2206 env.enclClass.containsNonEscapeSafeInitializers = true;
2207 }
2208 else {
2209 throw new AssertionError("Expected a JCIdent, JCFieldAccess, JCArrayAccess, or JCParens as lhs of an assignment, was "+
2210 lhs.getClass().getSimpleName()+" in "+lhs);
2211 }
2212 }
2213 else {
2214 if (env.isEscapeSafe ()) {
2215 if (lhs instanceof JCIdent) {
2216 JCIdent ident = (JCIdent)lhs;
2217 // System.out.println("\tsym = "+ident.sym+" kind = "+ident.sym.getKind());
2218 switch (ident.sym.getKind()) {
2219 case FIELD: {
2220 // do not allow fields unless it is to this in the constructor
2221 // (this is always to this, otherwise it would be a JCFieldAccess
2222 // only need to check if we have a constructor and the field is non-static)
2223 if ((env.enclMethod.name!=names.init) || ((ident.sym.flags() & STATIC)!=0)) {
2224 log.error(lhs.pos(), "no.assignment.to.this.fields.in.escapesafe");
2225 }
2226 break;
2227 }
2228 case PARAMETER:
2229 case LOCAL_VARIABLE: {
2230 // allow parameters and local variables
2231 // if bound inside this escape
2232 if (env.escape!=null) {
2233 Env<AttrContext> defineEnv = env;
2234 Scope defineScope = defineEnv.info.scope.lookup(ident.sym.name).scope;
2235 while(defineScope==null && defineEnv.outer!=null) {
2236 defineEnv = defineEnv.next;
2237 defineScope = defineEnv.info.scope.lookup(ident.sym.name).scope;
2238 }
2239 if (defineEnv.escape!=env.escape) {
2240 log.error(lhs.pos(), "assignment.in.escape.to.local.outside.escape");
2241 }
2242 }
2243 else {
2244 // must be inside an separable method
2245 // all parameters and local variables are okay
2246 // System.out.println("\tno escape");
2247 }
2248 break;
2249 }
2250 case PACKAGE:
2251 case ENUM:
2252 case CLASS:
2253 case ANNOTATION_TYPE:
2254 case INTERFACE:
2255 case ENUM_CONSTANT:
2256 case EXCEPTION_PARAMETER:
2257 case METHOD:
2258 case CONSTRUCTOR:
2259 case STATIC_INIT:
2260 case INSTANCE_INIT:
2261 case TYPE_PARAMETER:
2262 case OTHER:
2263 default: // unexpected, don't do anything
2264 break;
2265 }
2266 }
2267 else if (lhs instanceof JCFieldAccess) {
2268 JCFieldAccess fa = (JCFieldAccess)lhs;
2269 if ((fa.selected instanceof JCIdent) && (((JCIdent)fa.selected).name==names._this)) {
2270 if ((fa.sym.flags() & STATIC)!=0) {
2271 // this.x access to a static x
2272 log.error(lhs.pos(), "no.assignment.to.static.fields.in.escapesafe");
2273 }
2274 }
2275 else {
2276 // not a this.x access
2277 log.error(lhs.pos(), "no.assignment.to.fields.in.escapesafe");
2278 }
2279 }
2280 else if (lhs instanceof JCArrayAccess) {
2281 log.error(lhs.pos(), "no.assignment.to.arrays.in.escapesafe");
2282 }
2283 else {
2284 throw new AssertionError("Expected a JCIdent, JCFieldAccess, JCArrayAccess, or JCParens as lhs of an assignment, was "+
2285 lhs.getClass().getSimpleName()+" in "+lhs);
2286 }
2287 // System.out.println("In separable/escape: "+lhs+" "+lhs.getClass().getSimpleName());
2288 }
2289 }
2290 }
2291
2292 public void visitAssignop(JCAssignOp tree) {
2293 // Attribute arguments.
2294 Type owntype = attribTree(tree.lhs, env, VAR, Type.noType);
2295 Type operand = attribExpr(tree.rhs, env);
2296 // Find operator.
2297 Symbol operator = tree.operator = rs.resolveBinaryOperator(
2298 tree.pos(), tree.getTag() - JCTree.ASGOffset, env,
2299 owntype, operand);
2300
2301 if (operator.kind == MTH) {
2302 chk.checkOperator(tree.pos(),
2303 (OperatorSymbol)operator,
2304 tree.getTag() - JCTree.ASGOffset,
2305 owntype,
2306 operand);
2307 chk.checkDivZero(tree.rhs.pos(), operator, operand);
2308 chk.checkCastable(tree.rhs.pos(),
2309 operator.type.getReturnType(),
2310 owntype);
2311 }
2312 result = check(tree, owntype, VAL, pkind, pt);
2313
2314 // mgr: escape safety check
2315 checkAssignEscapeSafety(tree.lhs);
2316 }
2317
2318 public void visitUnary(JCUnary tree) {
2319 // Attribute arguments.
2320 Type argtype = (JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC)
2321 ? attribTree(tree.arg, env, VAR, Type.noType)
2322 : chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env));
2323
2324 // Find operator.
2325 Symbol operator = tree.operator =
2326 rs.resolveUnaryOperator(tree.pos(), tree.getTag(), env, argtype);
2327
2328 Type owntype = types.createErrorType(tree.type);
2329 if (operator.kind == MTH) {
2330 owntype = (JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC)
2331 ? tree.arg.type
2332 : operator.type.getReturnType();
2333 int opc = ((OperatorSymbol)operator).opcode;
2334
2335 // If the argument is constant, fold it.
2336 if (argtype.constValue() != null) {
2337 Type ctype = cfolder.fold1(opc, argtype);
2338 if (ctype != null) {
2339 owntype = cfolder.coerce(ctype, owntype);
2340
2341 // Remove constant types from arguments to
2342 // conserve space. The parser will fold concatenations
2343 // of string literals; the code here also
2344 // gets rid of intermediate results when some of the
2345 // operands are constant identifiers.
2346 if (tree.arg.type.tsym == syms.stringType.tsym) {
2347 tree.arg.type = syms.stringType;
2348 }
2349 }
2350 }
2351 }
2352 result = check(tree, owntype, VAL, pkind, pt);
2353 }
2354
2355 public void visitBinary(JCBinary tree) {
2356 // Attribute arguments.
2357 Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env));
2358 Type right = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.rhs, env));
2359
2360 // Find operator.
2361 Symbol operator = tree.operator =
2362 rs.resolveBinaryOperator(tree.pos(), tree.getTag(), env, left, right);
2363
2364 Type owntype = types.createErrorType(tree.type);
2365 if (operator.kind == MTH) {
2366 owntype = operator.type.getReturnType();
2367 int opc = chk.checkOperator(tree.lhs.pos(),
2368 (OperatorSymbol)operator,
2369 tree.getTag(),
2370 left,
2371 right);
2372
2373 // If both arguments are constants, fold them.
2374 if (left.constValue() != null && right.constValue() != null) {
2375 Type ctype = cfolder.fold2(opc, left, right);
2376 if (ctype != null) {
2377 owntype = cfolder.coerce(ctype, owntype);
2378
2379 // Remove constant types from arguments to
2380 // conserve space. The parser will fold concatenations
2381 // of string literals; the code here also
2382 // gets rid of intermediate results when some of the
2383 // operands are constant identifiers.
2384 if (tree.lhs.type.tsym == syms.stringType.tsym) {
2385 tree.lhs.type = syms.stringType;
2386 }
2387 if (tree.rhs.type.tsym == syms.stringType.tsym) {
2388 tree.rhs.type = syms.stringType;
2389 }
2390 }
2391 }
2392
2393 // Check that argument types of a reference ==, != are
2394 // castable to each other, (JLS???).
2395 if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) {
2396 if (!types.isCastable(left, right, new Warner(tree.pos()))) {
2397 log.error(tree.pos(), "incomparable.types", left, right);
2398 }
2399 }
2400
2401 chk.checkDivZero(tree.rhs.pos(), operator, right);
2402 }
2403 result = check(tree, owntype, VAL, pkind, pt);
2404 }
2405
2406 public void visitTypeCast(JCTypeCast tree) {
2407 Type clazztype = attribType(tree.clazz, env);
2408 chk.validate(tree.clazz, env);
2409 Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly);
2410 Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
2411 if (exprtype.constValue() != null)
2412 owntype = cfolder.coerce(exprtype, owntype);
2413 result = check(tree, capture(owntype), VAL, pkind, pt);
2414
2415 // mgr: disallow casts to Code
2416 // NOTE: we don't do that anymore
2417 // boolean isCastToCode = false;
2418 // if (tree.clazz instanceof JCIdent) {
2419 // JCIdent clazz = (JCIdent)tree.clazz;
2420 // Type casttype = ((ClassSymbol)clazz.sym).type;
2421 // isCastToCode = types.isSubtypeUnchecked(casttype,syms.codeType);
2422 // }
2423 // else if (tree.clazz instanceof JCTypeApply) {
2424 // JCTypeApply tapp = (JCTypeApply)tree.clazz;
2425 // JCIdent clazz = (JCIdent)tapp.clazz;
2426 // Type casttype = ((ClassSymbol)clazz.sym).type;
2427 // isCastToCode = types.isSubtypeUnchecked(casttype,syms.codeType);
2428 // }
2429 // if (isCastToCode) {
2430 // log.error(tree.pos(), "may.not.cast.to.code");
2431 // }
2432 }
2433
2434 public void visitTypeTest(JCInstanceOf tree) {
2435 Type exprtype = chk.checkNullOrRefType(
2436 tree.expr.pos(), attribExpr(tree.expr, env));
2437 Type clazztype = chk.checkReifiableReferenceType(
2438 tree.clazz.pos(), attribType(tree.clazz, env));
2439 chk.validate(tree.clazz, env);
2440 chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
2441 result = check(tree, syms.booleanType, VAL, pkind, pt);
2442 }
2443
2444 public void visitIndexed(JCArrayAccess tree) {
2445 Type owntype = types.createErrorType(tree.type);
2446 Type atype = attribExpr(tree.indexed, env);
2447 attribExpr(tree.index, env, syms.intType);
2448 if (types.isArray(atype))
2449 owntype = types.elemtype(atype);
2450 else if (atype.tag != ERROR)
2451 log.error(tree.pos(), "array.req.but.found", atype);
2452 if ((pkind & VAR) == 0) owntype = capture(owntype);
2453 result = check(tree, owntype, VAR, pkind, pt);
2454 }
2455
2456 public void visitIdent(JCIdent tree) {
2457 Symbol sym;
2458 boolean varArgs = false;
2459
2460 // Find symbol
2461 if (pt.tag == METHOD || pt.tag == FORALL) {
2462 // If we are looking for a method, the prototype `pt' will be a
2463 // method type with the type of the call's arguments as parameters.
2464 env.info.varArgs = false;
2465 sym = rs.resolveMethod(tree.pos(), env, tree.name, pt.getParameterTypes(), pt.getTypeArguments());
2466 varArgs = env.info.varArgs;
2467 } else if (tree.sym != null && tree.sym.kind != VAR) {
2468 sym = tree.sym;
2469 } else {
2470 sym = rs.resolveIdent(tree.pos(), env, tree.name, pkind);
2471 }
2472 tree.sym = sym;
2473
2474 // (1) Also find the environment current for the class where
2475 // sym is defined (`symEnv').
2476 // Only for pre-tiger versions (1.4 and earlier):
2477 // (2) Also determine whether we access symbol out of an anonymous
2478 // class in a this or super call. This is illegal for instance
2479 // members since such classes don't carry a this$n link.
2480 // (`noOuterThisPath').
2481 Env<AttrContext> symEnv = env;
2482 boolean noOuterThisPath = false;
2483 if (env.enclClass.sym.owner.kind != PCK && // we are in an inner class
2484 (sym.kind & (VAR | MTH | TYP)) != 0 &&
2485 sym.owner.kind == TYP &&
2486 tree.name != names._this && tree.name != names._super) {
2487
2488 // Find environment in which identifier is defined.
2489 while (symEnv.outer != null &&
2490 !sym.isMemberOf(symEnv.enclClass.sym, types)) {
2491 if ((symEnv.enclClass.sym.flags() & NOOUTERTHIS) != 0)
2492 noOuterThisPath = !allowAnonOuterThis;
2493 symEnv = symEnv.outer;
2494 }
2495 }
2496
2497 // If symbol is a variable, ...
2498 if (sym.kind == VAR) {
2499 VarSymbol v = (VarSymbol)sym;
2500
2501 // ..., evaluate its initializer, if it has one, and check for
2502 // illegal forward reference.
2503 checkInit(tree, env, v, false);
2504
2505 // If symbol is a local variable accessed from an embedded
2506 // inner class check that it is final.
2507 if (v.owner.kind == MTH &&
2508 v.owner != env.info.scope.owner &&
2509 (v.flags_field & FINAL) == 0) {
2510 log.error(tree.pos(),
2511 "local.var.accessed.from.icls.needs.final",
2512 v);
2513 }
2514
2515 // If we are expecting a variable (as opposed to a value), check
2516 // that the variable is assignable in the current environment.
2517 if (pkind == VAR)
2518 checkAssignable(tree.pos(), v, null, env);
2519
2520 // mgr: CSP level check
2521 // Find the scope in which the variable was defined
2522 Env<AttrContext> defineEnv = env;
2523 Scope defineScope = defineEnv.info.scope.lookup(sym.name).scope;
2524 while(defineScope==null && defineEnv.outer!=null) {
2525 defineEnv = defineEnv.next;
2526 defineScope = defineEnv.info.scope.lookup(sym.name).scope;
2527 }
2528
2529 // Ensure that the level in which the variable was defined isn't greater than the current level
2530 // System.out.println("sym "+sym+" level="+env.getLevel()+" define level="+defineEnv.getLevel());
2531 // System.out.println("\tis member of "+env.enclClass.sym+"? "+sym.isMemberOf(env.enclClass.sym, types));
2532 if (sym.isMemberOf(env.enclClass.sym, types)) {
2533 // this symbol is a member of this class, don't CSP it
2534 tree.cspCount = 0;
2535 }
2536 else {
2537 tree.cspCount = env.getLevel()-defineEnv.getLevel();
2538 }
2539 if (tree.cspCount<0) {
2540 log.error(tree.pos(), "escape.level", defineEnv.getLevel(), env.getLevel());
2541 return;
2542 }
2543 else if (tree.cspCount>0) {
2544 cspVariableCheck(sym, tree);
2545 }
2546 if (env.enclBrackets.size()>0) {
2547 // find the environment where the bracket was created
2548 Env<AttrContext> bracketEnclEnv = null;
2549 Env<AttrContext> e = env;
2550 while(e!=null) {
2551 if (e.tree==env.enclBrackets.head) {
2552 bracketEnclEnv = e;
2553 break;
2554 }
2555 e = e.next;
2556 }
2557
2558 // local variables and parameters outside the brackets must be final
2559 /* FIXME: isn't this covered in cspVariableCheck?
2560 if (((tree.sym.getKind()==ElementKind.PARAMETER) || (tree.sym.getKind()==ElementKind.LOCAL_VARIABLE)) &&
2561 ((tree.sym.flags() & FINAL)==0)) {
2562 // determine if the binding occurrence was outside the brackets
2563 // by starting outside the bracket's env and searching for defineEnv
2564 e = bracketEnclEnv.next;
2565 while(e!=null) {
2566 if (e==defineEnv) {
2567 log.error(tree.pos(), "local.var.accessed.from.brackets.needs.final", sym);
2568 break;
2569 }
2570 e = e.next;
2571 }
2572 }
2573 */
2574
2575 // local variables and parameters outside the brackets must be static
2576 // FIXME: shouldn't this also go in cspVariableCheck?
2577 if (((tree.sym.getKind()==ElementKind.FIELD) || (tree.sym.getKind()==ElementKind.METHOD)) &&
2578 ((tree.sym.flags() & STATIC)==0)) {
2579 // System.out.println("accessing non-static field or method, "+tree.sym.owner);
2580 // System.out.println(env);
2581 // determine if the binding occurrence was outside the brackets
2582 e = env;
2583 while(e!=null) {
2584 // System.out.println("Checking "+e.info.scope.owner+" "+e.info.scope.owner.getClass().getSimpleName());
2585 if (e==bracketEnclEnv) {
2586 log.error(tree.pos(), "may.not.directly.access.enclosing", tree.sym.name.toString());
2587 break;
2588 }
2589 if ((e.info.scope.owner.kind & TYP) != 0) {
2590 // System.out.println("\tis "+e.info.scope.owner.type+" subtype of "+tree.sym.owner.type+"?");
2591 // this is a class, check if its a subclass of tree.sym.owner
2592 if ((e.info.scope.owner.type.toString().equals(tree.sym.owner.type.toString())) ||
2593 (types.isSubtype(e.info.scope.owner.type,tree.sym.owner.type))) {
2594 // System.out.println("yes");
2595 break;
2596 }
2597 }
2598 e = e.next;
2599 }
2600 }
2601
2602 // prevent use of this inside brackets
2603 if (tree.sym.name==names._this) {
2604 // find out tree.sym.owner is an enclosing class of bracketEnclEnv.enclClass.sym.type
2605 Type t = bracketEnclEnv.enclClass.sym.type;
2606 while(t!=null) {
2607 if (tree.sym.owner.type.toString().equals(t.toString())) {
2608 // tree.sym.owner is an enclosing class of bracketEnclClass
2609 // that means that the this belongs to a class outside the brackets
2610 log.error(tree.pos(), "may.not.access.enclosing.this");
2611 break;
2612 }
2613 t = t.getEnclosingType();
2614 }
2615 }
2616 }
2617 }
2618
2619 // In a constructor body,
2620 // if symbol is a field or instance method, check that it is
2621 // not accessed before the supertype constructor is called.
2622 if ((symEnv.info.isSelfCall || noOuterThisPath) &&
2623 (sym.kind & (VAR | MTH)) != 0 &&
2624 sym.owner.kind == TYP &&
2625 (sym.flags() & STATIC) == 0) {
2626 chk.earlyRefError(tree.pos(), sym.kind == VAR ? sym : thisSym(tree.pos(), env));
2627 }
2628 Env<AttrContext> env1 = env;
2629 if (sym.kind != ERR && sym.kind != TYP && sym.owner != null && sym.owner != env1.enclClass.sym) {
2630 // If the found symbol is inaccessible, then it is
2631 // accessed through an enclosing instance. Locate this
2632 // enclosing instance:
2633 while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym))
2634 env1 = env1.outer;
2635 }
2636 result = checkId(tree, env1.enclClass.sym.type, sym, env, pkind, pt, varArgs);
2637 }
2638
2639 /**
2640 * Cache for queries to hasCodeFields.
2641 * Key: type, value: true if the key has code fields
2642 */
2643 protected HashMap<String,Boolean> hasCodeFieldsCache = new HashMap<String,Boolean>();
2644
2645 /**
2646 * Return true if the type has code fields. Uses the cache.
2647 *
2648 * @param type type to check
2649 * @return true if the type has code fields
2650 */
2651 protected boolean hasCodeFields(Type type) {
2652 Boolean result = hasCodeFieldsCache.get(type.toString());
2653 if (result==null) {
2654 if (type!=syms.objectType) hasCodeFields(syms.objectType);
2655
2656 result = hasCodeFields(type, new HashSet<String>());
2657 hasCodeFieldsCache.put(type.toString(), result);
2658 // System.out.println("hasCodeFields: "+type.toString()+" "+result);
2659 }
2660 return result;
2661 }
2662
2663 /**
2664 * Return true if the type has code fields. Uses the passed
2665 * hash set to prevent infinite recursion in cycles.
2666 *
2667 * @param type type to check
2668 * @param visited hash set of types already visited
2669 * @return true if the type has code fields
2670 */
2671 protected boolean hasCodeFields(Type type, HashSet<String> visited) {
2672 if (visited.contains(type.toString())) return false; // this type has already been visited, short out
2673
2674 ListBuffer<Type> checked = new ListBuffer<Type>();
2675 Boolean result = false;
2676 try {
2677 if (isPrimitiveOrBoxedOrArrayThereof(type)) return false;
2678 if (type.tag==ARRAY) return hasCodeFields(((ArrayType)type).elemtype, visited);
2679 List<Type> from = List.<Type>nil();
2680 List<Type> to = List.nil();
2681 boolean isRaw;
2682 do {
2683 if (type.tag==CLASS) {
2684 if (type.toString().indexOf('<')==-1) checked.add(type); // if this class does not contain generics
2685 if (visited.contains(type.toString())) { result = false; return result; }
2686 result = hasCodeFieldsCache.get(type.toString());
2687 if (result!=null) { return result; }
2688 visited.add(type.toString()); // now this type has been visited
2689
2690 ClassType t = (ClassType)type;
2691 Scope s = t.tsym.members();
2692 isRaw = t.isRaw();
2693 // System.out.print("\n\n========================================\nCLASS "+t+"\n\tparams = "+t.typarams_field+"\n\tvars =");
2694 ListBuffer<Type> lbVars = new ListBuffer<Type>();
2695 ListBuffer<Type> lbArgs = new ListBuffer<Type>();
2696 List<Type> typarams_field = t.typarams_field;
2697 for(TypeSymbol tv: t.tsym.getTypeParameters()) {
2698 // System.out.print(" "+tv.type);
2699 lbVars.add(tv.type);
2700 if (isRaw) {
2701 lbArgs.add(syms.objectType);
2702 }
2703 else {
2704 Type head = typarams_field.head;
2705 if (head.isSuperBound() && (!head.isUnbound())) head = syms.objectType;
2706 lbArgs.add(head);
2707 typarams_field = typarams_field.tail;
2708 }
2709 }
2710 // System.out.println("\n\traw? "+isRaw);
2711 from = lbVars.toList().appendList(from);
2712 to = lbArgs.toList().appendList(to);
2713 t = (ClassType)substList(t, from, to);
2714 for(Symbol member: s.getElements()) {
2715 if (((member.flags()&PRIVATE)==0)&&(member.getKind()==ElementKind.FIELD)) {
2716 // Type memberType = types.memberType(t, member);
2717 Type memberType = substList(member.type, from, to);
2718 memberType = substList(memberType, from, to);
2719 memberType = types.upperBound(memberType);
2720 // System.out.println(t+" "+member+" ----> "+memberType);
2721
2722 // System.out.println("\tisObject? "+(memberType==syms.objectType)+" isCode? "+isCodeType(memberType));
2723 // TODO: Do we want to allow Object? This may be good enough if we disallow casts to Code.
2724 // if ((memberType==syms.objectType) || (isCodeType(memberType))) { System.out.println("! Object or Code"); result = true; return result; }
2725 if (isCodeType(memberType)) { result = true; return result; }
2726 if ((memberType.tag==CLASS) && ((memberType.tsym.flags() & FINAL)==0)) { result = true; return result; } // not final class
2727 if (hasCodeFields(memberType, visited)) { result = true; return result; }
2728 }
2729 }
2730 type = ((ClassSymbol)t.tsym).getSuperclass();
2731 // System.out.println("superclass: "+type);
2732 }
2733 else {
2734 type = Type.noType;
2735 }
2736 } while(type!=Type.noType);
2737 // System.out.println("done.");
2738 result = false;
2739 return result;
2740 }
2741 finally {
2742 // if there are no generics involved, then we can already cache the classes
2743 for(Type c: checked.toList()) {
2744 hasCodeFieldsCache.put(c.toString(), result);
2745 // System.out.println("checked: "+c.toString()+" "+result);
2746 }
2747 }
2748 }
2749 protected boolean isCodeType(Type memberType) { return (memberType.tsym!=null) && (memberType.tsym.name==syms.codeType.tsym.name); }
2750 protected Type substList(Type t, List<Type> from, List<Type> to) {
2751 // System.out.println("\torig "+t);
2752 // System.out.print("\tfrom:");
2753 // for(Type f: from) { System.out.print(" "+f+"("+System.identityHashCode(f)+")"); }
2754 // System.out.print("\n\tto");
2755 // for(Type f: to) { System.out.print(" "+f+"("+System.identityHashCode(f)+")"); }
2756 for (; from.nonEmpty(); from = from.tail, to = to.tail) {
2757 t = types.subst(t, from, to);
2758 }
2759 // System.out.println("\nSUBST "+t);
2760 return t;
2761 }
2762
2763 protected boolean isPrimitiveOrBoxedOrArrayThereof(Type type) {
2764 if (type.isPrimitive()) return true;
2765 if (type.tag==ARRAY) return (isPrimitiveOrBoxedOrArrayThereof(((ArrayType)type).elemtype));
2766 if (type.tag==CLASS) {
2767 return ((type.tsym.equals(types.boxedClass(syms.byteType))) ||
2768 (type.tsym.equals(types.boxedClass(syms.charType))) ||
2769 (type.tsym.equals(types.boxedClass(syms.shortType))) ||
2770 (type.tsym.equals(types.boxedClass(syms.intType))) ||
2771 (type.tsym.equals(types.boxedClass(syms.longType))) ||
2772 (type.tsym.equals(types.boxedClass(syms.floatType))) ||
2773 (type.tsym.equals(types.boxedClass(syms.doubleType))) ||
2774 (type.tsym.equals(types.boxedClass(syms.booleanType))) ||
2775 (type.tsym.equals(syms.stringType)));
2776 }
2777 return false;
2778 // TODO: what else can we get here?
2779 // if (type.tag==TYPEVAR) return false;
2780 // throw new AssertionError("Expected either primitive, class or array for variables, was "+type.getClass().getSimpleName());
2781 }
2782
2783 protected void cspVariableCheck(Symbol sym, JCTree tree) {
2784 // CSP variables must:
2785 // 1. be final if they are local variables or parameters
2786 // 2. be primitive or their corresponding boxed types, or an array thereof
2787
2788 // check 1: local variables and parameters must be final
2789 if (((sym.getKind()==ElementKind.PARAMETER) || (sym.getKind()==ElementKind.LOCAL_VARIABLE)) &&
2790 (sym.flags() & FINAL)==0) {
2791 log.error(tree.pos(), "local.var.accessed.from.brackets.needs.final", sym);
2792 }
2793
2794 // check 2: must be primitive or ...
2795 if (isPrimitiveOrBoxedOrArrayThereof(sym.type)) { return; }
2796
2797 // FIXME: revisit final classes without code fields
2798 // ...be final without code fields
2799 if (sym.type.tag==CLASS) {
2800 ClassSymbol c = (ClassSymbol)sym.type.tsym;
2801 if ((c.flags() & FINAL)!=0) {
2802 // is final
2803 if (!hasCodeFields(sym.type)) { return; }
2804 }
2805 }
2806
2807 log.error(tree.pos(), "csp.var.must.be.primitive.or.boxed.or.final.no.code.or.array", sym);
2808 }
2809
2810 public void visitSelect(JCFieldAccess tree) {
2811 // Determine the expected kind of the qualifier expression.
2812 int skind = 0;
2813 if (tree.name == names._this || tree.name == names._super ||
2814 tree.name == names._class)
2815 {
2816 skind = TYP;
2817 } else {
2818 if ((pkind & PCK) != 0) skind = skind | PCK;
2819 if ((pkind & TYP) != 0) skind = skind | TYP | PCK;
2820 if ((pkind & (VAL | MTH)) != 0) skind = skind | VAL | TYP;
2821 }
2822
2823 // Attribute the qualifier expression, and determine its symbol (if any).
2824 Type site = attribTree(tree.selected, env, skind, Infer.anyPoly);
2825 if ((pkind & (PCK | TYP)) == 0)
2826 site = capture(site); // Capture field access
2827
2828 // don't allow T.class T[].class, etc
2829 if (skind == TYP) {
2830 Type elt = site;
2831 while (elt.tag == ARRAY)
2832 elt = ((ArrayType)elt).elemtype;
2833 if (elt.tag == TYPEVAR) {
2834 log.error(tree.pos(), "type.var.cant.be.deref");
2835 result = types.createErrorType(tree.type);
2836 return;
2837 }
2838 }
2839
2840 // If qualifier symbol is a type or `super', assert `selectSuper'
2841 // for the selection. This is relevant for determining whether
2842 // protected symbols are accessible.
2843 Symbol sitesym = TreeInfo.symbol(tree.selected);
2844 boolean selectSuperPrev = env.info.selectSuper;
2845 env.info.selectSuper =
2846 sitesym != null &&
2847 sitesym.name == names._super;
2848
2849 // If selected expression is polymorphic, strip
2850 // type parameters and remember in env.info.tvars, so that
2851 // they can be added later (in Attr.checkId and Infer.instantiateMethod).
2852 if (tree.selected.type.tag == FORALL) {
2853 ForAll pstype = (ForAll)tree.selected.type;
2854 env.info.tvars = pstype.tvars;
2855 site = tree.selected.type = pstype.qtype;
2856 }
2857
2858 // Determine the symbol represented by the selection.
2859 env.info.varArgs = false;
2860 Symbol sym = selectSym(tree, site, env, pt, pkind);
2861 if (sym.exists() && !isType(sym) && (pkind & (PCK | TYP)) != 0) {
2862 site = capture(site);
2863 sym = selectSym(tree, site, env, pt, pkind);
2864 }
2865 boolean varArgs = env.info.varArgs;
2866 tree.sym = sym;
2867
2868 if (site.tag == TYPEVAR && !isType(sym) && sym.kind != ERR) {
2869 while (site.tag == TYPEVAR) site = site.getUpperBound();
2870 site = capture(site);
2871 }
2872
2873 // If that symbol is a variable, ...
2874 if (sym.kind == VAR) {
2875 VarSymbol v = (VarSymbol)sym;
2876
2877 // ..., evaluate its initializer, if it has one, and check for
2878 // illegal forward reference.
2879 checkInit(tree, env, v, true);
2880
2881 // If we are expecting a variable (as opposed to a value), check
2882 // that the variable is assignable in the current environment.
2883 if (pkind == VAR)
2884 checkAssignable(tree.pos(), v, tree.selected, env);
2885
2886 // mgr: csp safety
2887 // Prevent use of this inside brackets
2888 if (env.enclBrackets.size()>0) {
2889 if (tree.sym.name==names._this) {
2890 // find the environment where the bracket was created
2891 ClassSymbol bracketEnclClass = null;
2892 Env<AttrContext> e = env;
2893 while(e!=null) {
2894 if (e.tree==env.enclBrackets.head) {
2895 bracketEnclClass = e.enclClass.sym;
2896 break;
2897 }
2898 e = e.next;
2899 }
2900 // find out tree.sym.owner is an enclosing class of bracketEnclClass
2901 Type t = bracketEnclClass.type;
2902 while(t!=null) {
2903 if (tree.sym.owner.type.toString().equals(t.toString())) {
2904 // tree.sym.owner is an enclosing class of bracketEnclClass
2905 // that means that the this belongs to a class outside the brackets
2906 log.error(tree.pos(), "may.not.access.enclosing.this");
2907 break;
2908 }
2909 t = t.getEnclosingType();
2910 }
2911 }
2912 }
2913 }
2914
2915 // Disallow selecting a type from an expression
2916 if (isType(sym) && (sitesym==null || (sitesym.kind&(TYP|PCK)) == 0)) {
2917 tree.type = check(tree.selected, pt,
2918 sitesym == null ? VAL : sitesym.kind, TYP|PCK, pt);
2919 }
2920
2921 if (isType(sitesym)) {
2922 if (sym.name == names._this) {
2923 // If `C' is the currently compiled class, check that
2924 // C.this' does not appear in a call to a super(...)
2925 if (env.info.isSelfCall &&
2926 site.tsym == env.enclClass.sym) {
2927 chk.earlyRefError(tree.pos(), sym);
2928 }
2929 } else {
2930 // Check if type-qualified fields or methods are static (JLS)
2931 if ((sym.flags() & STATIC) == 0 &&
2932 sym.name != names._super &&
2933 (sym.kind == VAR || sym.kind == MTH)) {
2934 rs.access(rs.new StaticError(sym),
2935 tree.pos(), site, sym.name, true);
2936 }
2937 }
2938 }
2939
2940 // If we are selecting an instance member via a `super', ...
2941 if (env.info.selectSuper && (sym.flags() & STATIC) == 0) {
2942
2943 // Check that super-qualified symbols are not abstract (JLS)
2944 rs.checkNonAbstract(tree.pos(), sym);
2945
2946 if (site.isRaw()) {
2947 // Determine argument types for site.
2948 Type site1 = types.asSuper(env.enclClass.sym.type, site.tsym);
2949 if (site1 != null) site = site1;
2950 }
2951 }
2952
2953 env.info.selectSuper = selectSuperPrev;
2954 result = checkId(tree, site, sym, env, pkind, pt, varArgs);
2955 env.info.tvars = List.nil();
2956 }
2957 //where
2958 /** Determine symbol referenced by a Select expression,
2959 *
2960 * @param tree The select tree.
2961 * @param site The type of the selected expression,
2962 * @param env The current environment.
2963 * @param pt The current prototype.
2964 * @param pkind The expected kind(s) of the Select expression.
2965 */
2966 private Symbol selectSym(JCFieldAccess tree,
2967 Type site,
2968 Env<AttrContext> env,
2969 Type pt,
2970 int pkind) {
2971 DiagnosticPosition pos = tree.pos();
2972 Name name = tree.name;
2973
2974 switch (site.tag) {
2975 case PACKAGE:
2976 return rs.access(
2977 rs.findIdentInPackage(env, site.tsym, name, pkind),
2978 pos, site, name, true);
2979 case ARRAY:
2980 case CLASS:
2981 if (pt.tag == METHOD || pt.tag == FORALL) {
2982 return rs.resolveQualifiedMethod(
2983 pos, env, site, name, pt.getParameterTypes(), pt.getTypeArguments());
2984 } else if (name == names._this || name == names._super) {
2985 return rs.resolveSelf(pos, env, site.tsym, name);
2986 } else if (name == names._class) {
2987 // In this case, we have already made sure in
2988 // visitSelect that qualifier expression is a type.
2989 Type t = syms.classType;
2990 List<Type> typeargs = allowGenerics
2991 ? List.of(types.erasure(site))
2992 : List.<Type>nil();
2993 t = new ClassType(t.getEnclosingType(), typeargs, t.tsym);
2994 return new VarSymbol(
2995 STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
2996 } else {
2997 // We are seeing a plain identifier as selector.
2998 Symbol sym = rs.findIdentInType(env, site, name, pkind);
2999 if ((pkind & ERRONEOUS) == 0)
3000 sym = rs.access(sym, pos, site, name, true);
3001 return sym;
3002 }
3003 case WILDCARD:
3004 throw new AssertionError(tree);
3005 case TYPEVAR:
3006 // Normally, site.getUpperBound() shouldn't be null.
3007 // It should only happen during memberEnter/attribBase
3008 // when determining the super type which *must* be
3009 // done before attributing the type variables. In
3010 // other words, we are seeing this illegal program:
3011 // class B<T> extends A<T.foo> {}
3012 Symbol sym = (site.getUpperBound() != null)
3013 ? selectSym(tree, capture(site.getUpperBound()), env, pt, pkind)
3014 : null;
3015 if (sym == null || isType(sym)) {
3016 log.error(pos, "type.var.cant.be.deref");
3017 return syms.errSymbol;
3018 } else {
3019 Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ?
3020 rs.new AccessError(env, site, sym) :
3021 sym;
3022 rs.access(sym2, pos, site, name, true);
3023 return sym;
3024 }
3025 case ERROR:
3026 // preserve identifier names through errors
3027 return types.createErrorType(name, site.tsym, site).tsym;
3028 default:
3029 // The qualifier expression is of a primitive type -- only
3030 // .class is allowed for these.
3031 if (name == names._class) {
3032 // In this case, we have already made sure in Select that
3033 // qualifier expression is a type.
3034 Type t = syms.classType;
3035 Type arg = types.boxedClass(site).type;
3036 t = new ClassType(t.getEnclosingType(), List.of(arg), t.tsym);
3037 return new VarSymbol(
3038 STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
3039 } else {
3040 log.error(pos, "cant.deref", site);
3041 return syms.errSymbol;
3042 }
3043 }
3044 }
3045
3046 /** Determine type of identifier or select expression and check that
3047 * (1) the referenced symbol is not deprecated
3048 * (2) the symbol's type is safe (@see checkSafe)
3049 * (3) if symbol is a variable, check that its type and kind are
3050 * compatible with the prototype and protokind.
3051 * (4) if symbol is an instance field of a raw type,
3052 * which is being assigned to, issue an unchecked warning if its
3053 * type changes under erasure.
3054 * (5) if symbol is an instance method of a raw type, issue an
3055 * unchecked warning if its argument types change under erasure.
3056 * If checks succeed:
3057 * If symbol is a constant, return its constant type
3058 * else if symbol is a method, return its result type
3059 * otherwise return its type.
3060 * Otherwise return errType.
3061 *
3062 * @param tree The syntax tree representing the identifier
3063 * @param site If this is a select, the type of the selected
3064 * expression, otherwise the type of the current class.
3065 * @param sym The symbol representing the identifier.
3066 * @param env The current environment.
3067 * @param pkind The set of expected kinds.
3068 * @param pt The expected type.
3069 */
3070 Type checkId(JCTree tree,
3071 Type site,
3072 Symbol sym,
3073 Env<AttrContext> env,
3074 int pkind,
3075 Type pt,
3076 boolean useVarargs) {
3077 if (pt.isErroneous()) return types.createErrorType(site);
3078 Type owntype; // The computed type of this identifier occurrence.
3079 switch (sym.kind) {
3080 case TYP:
3081 // For types, the computed type equals the symbol's type,
3082 // except for two situations:
3083 owntype = sym.type;
3084 if (owntype.tag == CLASS) {
3085 Type ownOuter = owntype.getEnclosingType();
3086
3087 // (a) If the symbol's type is parameterized, erase it
3088 // because no type parameters were given.
3089 // We recover generic outer type later in visitTypeApply.
3090 if (owntype.tsym.type.getTypeArguments().nonEmpty()) {
3091 owntype = types.erasure(owntype);
3092 }
3093
3094 // (b) If the symbol's type is an inner class, then
3095 // we have to interpret its outer type as a superclass
3096 // of the site type. Example:
3097 //
3098 // class Tree<A> { class Visitor { ... } }
3099 // class PointTree extends Tree<Point> { ... }
3100 // ...PointTree.Visitor...
3101 //
3102 // Then the type of the last expression above is
3103 // Tree<Point>.Visitor.
3104 else if (ownOuter.tag == CLASS && site != ownOuter) {
3105 Type normOuter = site;
3106 if (normOuter.tag == CLASS)
3107 normOuter = types.asEnclosingSuper(site, ownOuter.tsym);
3108 if (normOuter == null) // perhaps from an import
3109 normOuter = types.erasure(ownOuter);
3110 if (normOuter != ownOuter)
3111 owntype = new ClassType(
3112 normOuter, List.<Type>nil(), owntype.tsym);
3113 }
3114 }
3115 break;
3116 case VAR:
3117 VarSymbol v = (VarSymbol)sym;
3118 // Test (4): if symbol is an instance field of a raw type,
3119 // which is being assigned to, issue an unchecked warning if
3120 // its type changes under erasure.
3121 if (allowGenerics &&
3122 pkind == VAR &&
3123 v.owner.kind == TYP &&
3124 (v.flags() & STATIC) == 0 &&
3125 (site.tag == CLASS || site.tag == TYPEVAR)) {
3126 Type s = types.asOuterSuper(site, v.owner);
3127 if (s != null &&
3128 s.isRaw() &&
3129 !types.isSameType(v.type, v.erasure(types))) {
3130 chk.warnUnchecked(tree.pos(),
3131 "unchecked.assign.to.var",
3132 v, s);
3133 }
3134 }
3135 // The computed type of a variable is the type of the
3136 // variable symbol, taken as a member of the site type.
3137 owntype = (sym.owner.kind == TYP &&
3138 sym.name != names._this && sym.name != names._super)
3139 ? types.memberType(site, sym)
3140 : sym.type;
3141
3142 if (env.info.tvars.nonEmpty()) {
3143 Type owntype1 = new ForAll(env.info.tvars, owntype);
3144 for (List<Type> l = env.info.tvars; l.nonEmpty(); l = l.tail)
3145 if (!owntype.contains(l.head)) {
3146 log.error(tree.pos(), "undetermined.type", owntype1);
3147 owntype1 = types.createErrorType(owntype1);
3148 }
3149 owntype = owntype1;
3150 }
3151
3152 // If the variable is a constant, record constant value in
3153 // computed type.
3154 if (v.getConstValue() != null && isStaticReference(tree))
3155 owntype = owntype.constType(v.getConstValue());
3156
3157 if (pkind == VAL) {
3158 owntype = capture(owntype); // capture "names as expressions"
3159 }
3160 break;
3161 case MTH: {
3162 JCMethodInvocation app = (JCMethodInvocation)env.tree;
3163 owntype = checkMethod(site, sym, env, app.args,
3164 pt.getParameterTypes(), pt.getTypeArguments(),
3165 env.info.varArgs);
3166 break;
3167 }
3168 case PCK: case ERR:
3169 owntype = sym.type;
3170 break;
3171 default:
3172 throw new AssertionError("unexpected kind: " + sym.kind +
3173 " in tree " + tree);
3174 }
3175
3176 // Test (1): emit a `deprecation' warning if symbol is deprecated.
3177 // (for constructors, the error was given when the constructor was
3178 // resolved)
3179 if (sym.name != names.init &&
3180 (sym.flags() & DEPRECATED) != 0 &&
3181 (env.info.scope.owner.flags() & DEPRECATED) == 0 &&
3182 sym.outermostClass() != env.info.scope.owner.outermostClass())
3183 chk.warnDeprecated(tree.pos(), sym);
3184
3185 if ((sym.flags() & PROPRIETARY) != 0)
3186 log.strictWarning(tree.pos(), "sun.proprietary", sym);
3187
3188 // Test (3): if symbol is a variable, check that its type and
3189 // kind are compatible with the prototype and protokind.
3190 return check(tree, owntype, sym.kind, pkind, pt);
3191 }
3192
3193 /** Check that variable is initialized and evaluate the variable's
3194 * initializer, if not yet done. Also check that variable is not
3195 * referenced before it is defined.
3196 * @param tree The tree making up the variable reference.
3197 * @param env The current environment.
3198 * @param v The variable's symbol.
3199 */
3200 private void checkInit(JCTree tree,
3201 Env<AttrContext> env,
3202 VarSymbol v,
3203 boolean onlyWarning) {
3204 // System.err.println(v + " " + ((v.flags() & STATIC) != 0) + " " +
3205 // tree.pos + " " + v.pos + " " +
3206 // Resolve.isStatic(env));//DEBUG
3207
3208 // A forward reference is diagnosed if the declaration position
3209 // of the variable is greater than the current tree position
3210 // and the tree and variable definition occur in the same class
3211 // definition. Note that writes don't count as references.
3212 // This check applies only to class and instance
3213 // variables. Local variables follow different scope rules,
3214 // and are subject to definite assignment checking.
3215 if ((env.info.enclVar == v || v.pos > tree.pos) &&
3216 v.owner.kind == TYP &&
3217 canOwnInitializer(env.info.scope.owner) &&
3218 v.owner == env.info.scope.owner.enclClass() &&
3219 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) &&
3220 (env.tree.getTag() != JCTree.ASSIGN ||
3221 TreeInfo.skipParens(((JCAssign) env.tree).lhs) != tree)) {
3222 String suffix = (env.info.enclVar == v) ?
3223 "self.ref" : "forward.ref";
3224 if (!onlyWarning || isStaticEnumField(v)) {
3225 log.error(tree.pos(), "illegal." + suffix);
3226 } else if (useBeforeDeclarationWarning) {
3227 log.warning(tree.pos(), suffix, v);
3228 }
3229 }
3230
3231 v.getConstValue(); // ensure initializer is evaluated
3232
3233 checkEnumInitializer(tree, env, v);
3234 }
3235
3236 /**
3237 * Check for illegal references to static members of enum. In
3238 * an enum type, constructors and initializers may not
3239 * reference its static members unless they are constant.
3240 *
3241 * @param tree The tree making up the variable reference.
3242 * @param env The current environment.
3243 * @param v The variable's symbol.
3244 * @see JLS 3rd Ed. (8.9 Enums)
3245 */
3246 private void checkEnumInitializer(JCTree tree, Env<AttrContext> env, VarSymbol v) {
3247 // JLS 3rd Ed.:
3248 //
3249 // "It is a compile-time error to reference a static field
3250 // of an enum type that is not a compile-time constant
3251 // (15.28) from constructors, instance initializer blocks,
3252 // or instance variable initializer expressions of that
3253 // type. It is a compile-time error for the constructors,
3254 // instance initializer blocks, or instance variable
3255 // initializer expressions of an enum constant e to refer
3256 // to itself or to an enum constant of the same type that
3257 // is declared to the right of e."
3258 if (isStaticEnumField(v)) {
3259 ClassSymbol enclClass = env.info.scope.owner.enclClass();
3260
3261 if (enclClass == null || enclClass.owner == null)
3262 return;
3263
3264 // See if the enclosing class is the enum (or a
3265 // subclass thereof) declaring v. If not, this
3266 // reference is OK.
3267 if (v.owner != enclClass && !types.isSubtype(enclClass.type, v.owner.type))
3268 return;
3269
3270 // If the reference isn't from an initializer, then
3271 // the reference is OK.
3272 if (!Resolve.isInitializer(env))
3273 return;
3274
3275 log.error(tree.pos(), "illegal.enum.static.ref");
3276 }
3277 }
3278
3279 /** Is the given symbol a static, non-constant field of an Enum?
3280 * Note: enum literals should not be regarded as such
3281 */
3282 private boolean isStaticEnumField(VarSymbol v) {
3283 return Flags.isEnum(v.owner) &&
3284 Flags.isStatic(v) &&
3285 !Flags.isConstant(v) &&
3286 v.name != names._class;
3287 }
3288
3289 /** Can the given symbol be the owner of code which forms part
3290 * if class initialization? This is the case if the symbol is
3291 * a type or field, or if the symbol is the synthetic method.
3292 * owning a block.
3293 */
3294 private boolean canOwnInitializer(Symbol sym) {
3295 return
3296 (sym.kind & (VAR | TYP)) != 0 ||
3297 (sym.kind == MTH && (sym.flags() & BLOCK) != 0);
3298 }
3299
3300 Warner noteWarner = new Warner();
3301
3302 /**
3303 * Check that method arguments conform to its instantation.
3304 **/
3305 public Type checkMethod(Type site,
3306 Symbol sym,
3307 Env<AttrContext> env,
3308 final List<JCExpression> argtrees,
3309 List<Type> argtypes,
3310 List<Type> typeargtypes,
3311 boolean useVarargs) {
3312 // Test (5): if symbol is an instance method of a raw type, issue
3313 // an unchecked warning if its argument types change under erasure.
3314 if (allowGenerics &&
3315 (sym.flags() & STATIC) == 0 &&
3316 (site.tag == CLASS || site.tag == TYPEVAR)) {
3317 Type s = types.asOuterSuper(site, sym.owner);
3318 if (s != null && s.isRaw() &&
3319 !types.isSameTypes(sym.type.getParameterTypes(),
3320 sym.erasure(types).getParameterTypes())) {
3321 chk.warnUnchecked(env.tree.pos(),
3322 "unchecked.call.mbr.of.raw.type",
3323 sym, s);
3324 }
3325 }
3326
3327 // Compute the identifier's instantiated type.
3328 // For methods, we need to compute the instance type by
3329 // Resolve.instantiate from the symbol's type as well as
3330 // any type arguments and value arguments.
3331 noteWarner.warned = false;
3332 Type owntype = rs.instantiate(env,
3333 site,
3334 sym,
3335 argtypes,
3336 typeargtypes,
3337 true,
3338 useVarargs,
3339 noteWarner);
3340 boolean warned = noteWarner.warned;
3341
3342 // If this fails, something went wrong; we should not have
3343 // found the identifier in the first place.
3344 if (owntype == null) {
3345 if (!pt.isErroneous())
3346 log.error(env.tree.pos(),
3347 "internal.error.cant.instantiate",
3348 sym, site,
3349 Type.toString(pt.getParameterTypes()));
3350 owntype = types.createErrorType(site);
3351 } else {
3352 // System.out.println("call : " + env.tree);
3353 // System.out.println("method : " + owntype);
3354 // System.out.println("actuals: " + argtypes);
3355 List<Type> formals = owntype.getParameterTypes();
3356 Type last = useVarargs ? formals.last() : null;
3357 if (sym.name==names.init &&
3358 sym.owner == syms.enumSym)
3359 formals = formals.tail.tail;
3360 List<JCExpression> args = argtrees;
3361 while (formals.head != last) {
3362 JCTree arg = args.head;
3363 Warner warn = chk.convertWarner(arg.pos(), arg.type, formals.head);
3364 assertConvertible(arg, arg.type, formals.head, warn);
3365 warned |= warn.warned;
3366 args = args.tail;
3367 formals = formals.tail;
3368 }
3369 if (useVarargs) {
3370 Type varArg = types.elemtype(last);
3371 while (args.tail != null) {
3372 JCTree arg = args.head;
3373 Warner warn = chk.convertWarner(arg.pos(), arg.type, varArg);
3374 assertConvertible(arg, arg.type, varArg, warn);
3375 warned |= warn.warned;
3376 args = args.tail;
3377 }
3378 } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
3379 // non-varargs call to varargs method
3380 Type varParam = owntype.getParameterTypes().last();
3381 Type lastArg = argtypes.last();
3382 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
3383 !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
3384 log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
3385 types.elemtype(varParam),
3386 varParam);
3387 }
3388
3389 if (warned && sym.type.tag == FORALL) {
3390 chk.warnUnchecked(env.tree.pos(),
3391 "unchecked.meth.invocation.applied",
3392 kindName(sym),
3393 sym.name,
3394 rs.methodArguments(sym.type.getParameterTypes()),
3395 rs.methodArguments(argtypes),
3396 kindName(sym.location()),
3397 sym.location());
3398 owntype = new MethodType(owntype.getParameterTypes(),
3399 types.erasure(owntype.getReturnType()),
3400 owntype.getThrownTypes(),
3401 syms.methodClass);
3402 }
3403 if (useVarargs) {
3404 JCTree tree = env.tree;
3405 Type argtype = owntype.getParameterTypes().last();
3406 if (!types.isReifiable(argtype))
3407 chk.warnUnchecked(env.tree.pos(),
3408 "unchecked.generic.array.creation",
3409 argtype);
3410 Type elemtype = types.elemtype(argtype);
3411 switch (tree.getTag()) {
3412 case JCTree.APPLY:
3413 ((JCMethodInvocation) tree).varargsElement = elemtype;
3414 break;
3415 case JCTree.NEWCLASS:
3416 ((JCNewClass) tree).varargsElement = elemtype;
3417 break;
3418 default:
3419 throw new AssertionError(""+tree);
3420 }
3421 }
3422 }
3423 return owntype;
3424 }
3425
3426 private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
3427 if (types.isConvertible(actual, formal, warn))
3428 return;
3429
3430 if (formal.isCompound()
3431 && types.isSubtype(actual, types.supertype(formal))
3432 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
3433 return;
3434
3435 if (false) {
3436 // TODO: make assertConvertible work
3437 chk.typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
3438 throw new AssertionError("Tree: " + tree
3439 + " actual:" + actual
3440 + " formal: " + formal);
3441 }
3442 }
3443
3444 public void visitLiteral(JCLiteral tree) {
3445 result = check(
3446 tree, litType(tree.typetag).constType(tree.value), VAL, pkind, pt);
3447 }
3448 //where
3449 /** Return the type of a literal with given type tag.
3450 */
3451 Type litType(int tag) {
3452 return (tag == TypeTags.CLASS) ? syms.stringType : syms.typeOfTag[tag];
3453 }
3454
3455 public void visitTypeIdent(JCPrimitiveTypeTree tree) {
3456 result = check(tree, syms.typeOfTag[tree.typetag], TYP, pkind, pt);
3457 }
3458
3459 public void visitTypeArray(JCArrayTypeTree tree) {
3460 Type etype = attribType(tree.elemtype, env);
3461 Type type = new ArrayType(etype, syms.arrayClass);
3462 result = check(tree, type, TYP, pkind, pt);
3463 }
3464
3465 /** Visitor method for parameterized types.
3466 * Bound checking is left until later, since types are attributed
3467 * before supertype structure is completely known
3468 */
3469 public void visitTypeApply(JCTypeApply tree) {
3470 Type owntype = types.createErrorType(tree.type);
3471
3472 // Attribute functor part of application and make sure it's a class.
3473 Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env));
3474
3475 // Attribute type parameters
3476 List<Type> actuals = attribTypes(tree.arguments, env);
3477
3478 if (clazztype.tag == CLASS) {
3479 List<Type> formals = clazztype.tsym.type.getTypeArguments();
3480
3481 if (actuals.length() == formals.length()) {
3482 List<Type> a = actuals;
3483 List<Type> f = formals;
3484 while (a.nonEmpty()) {
3485 a.head = a.head.withTypeVar(f.head);
3486 a = a.tail;
3487 f = f.tail;
3488 }
3489 // Compute the proper generic outer
3490 Type clazzOuter = clazztype.getEnclosingType();
3491 if (clazzOuter.tag == CLASS) {
3492 Type site;
3493 if (tree.clazz.getTag() == JCTree.IDENT) {
3494 site = env.enclClass.sym.type;
3495 } else if (tree.clazz.getTag() == JCTree.SELECT) {
3496 site = ((JCFieldAccess) tree.clazz).selected.type;
3497 } else throw new AssertionError(""+tree);
3498 if (clazzOuter.tag == CLASS && site != clazzOuter) {
3499 if (site.tag == CLASS)
3500 site = types.asOuterSuper(site, clazzOuter.tsym);
3501 if (site == null)
3502 site = types.erasure(clazzOuter);
3503 clazzOuter = site;
3504 }
3505 }
3506 owntype = new ClassType(clazzOuter, actuals, clazztype.tsym);
3507 } else {
3508 if (formals.length() != 0) {
3509 log.error(tree.pos(), "wrong.number.type.args",
3510 Integer.toString(formals.length()));
3511 } else {
3512 log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym);
3513 }
3514 owntype = types.createErrorType(tree.type);
3515 }
3516
3517 // mgr: prevent instantiation of type parameters to Code, except when in Code
3518 // List<Code> or List<Code<Integer>> illegal
3519 // Code<Code<Integer>> legal
3520 // Code<List<Code>> illegal
3521 // NOTE: We don't do that anymore
3522 // if (!types.isSubtypeUnchecked(clazztype,syms.codeType)) {
3523 // // A<T> is not Code<T> -- T may not be Code
3524 // boolean hasCodeArg = false;
3525 // for(JCExpression arg: tree.arguments) {
3526 // if (arg instanceof JCIdent) {
3527 // JCIdent t = (JCIdent)arg;
3528 // Type ttype = null;
3529 // if (t.sym instanceof ClassSymbol) {
3530 // ttype = ((ClassSymbol)t.sym).type;
3531 // }
3532 // else if (t.sym instanceof TypeSymbol) {
3533 // TypeSymbol tsym = (TypeSymbol)t.sym;
3534 // ttype = tsym.type;
3535 // }
3536 // else throw new AssertionError("Expected ClassSymbol or TypeSymbol as type argument");
3537 // if (types.isSubtypeUnchecked(ttype,syms.codeType)) {
3538 // hasCodeArg = true;
3539 // break;
3540 // }
3541 // }
3542 // else if (arg instanceof JCTypeApply) {
3543 // JCTypeApply tapp = (JCTypeApply)arg;
3544 // JCIdent t = (JCIdent)tapp.clazz;
3545 // Type ttype = ((ClassSymbol)t.sym).type;
3546 // if (types.isSubtypeUnchecked(ttype,syms.codeType)) {
3547 // hasCodeArg = true;
3548 // break;
3549 // }
3550 // }
3551 // }
3552 // if (hasCodeArg) {
3553 // log.error(tree.pos(), "may.not.instantiate.to.code");
3554 // }
3555 // }
3556 }
3557 result = check(tree, owntype, TYP, pkind, pt);
3558 }
3559
3560 public void visitTypeParameter(JCTypeParameter tree) {
3561 TypeVar a = (TypeVar)tree.type;
3562 Set<Type> boundSet = new HashSet<Type>();
3563 if (a.bound.isErroneous())
3564 return;
3565 List<Type> bs = types.getBounds(a);
3566 if (tree.bounds.nonEmpty()) {
3567 // accept class or interface or typevar as first bound.
3568 Type b = checkBase(bs.head, tree.bounds.head, env, false, false, false);
3569 boundSet.add(types.erasure(b));
3570 if (b.isErroneous()) {
3571 a.bound = b;
3572 }
3573 else if (b.tag == TYPEVAR) {
3574 // if first bound was a typevar, do not accept further bounds.
3575 if (tree.bounds.tail.nonEmpty()) {
3576 log.error(tree.bounds.tail.head.pos(),
3577 "type.var.may.not.be.followed.by.other.bounds");
3578 tree.bounds = List.of(tree.bounds.head);
3579 a.bound = bs.head;
3580 }
3581 } else {
3582 // if first bound was a class or interface, accept only interfaces
3583 // as further bounds.
3584 for (JCExpression bound : tree.bounds.tail) {
3585 bs = bs.tail;
3586 Type i = checkBase(bs.head, bound, env, false, true, false);
3587 if (i.isErroneous())
3588 a.bound = i;
3589 else if (i.tag == CLASS)
3590 chk.checkNotRepeated(bound.pos(), types.erasure(i), boundSet);
3591 }
3592 }
3593 }
3594 bs = types.getBounds(a);
3595
3596 // in case of multiple bounds ...
3597 if (bs.length() > 1) {
3598 // ... the variable's bound is a class type flagged COMPOUND
3599 // (see comment for TypeVar.bound).
3600 // In this case, generate a class tree that represents the
3601 // bound class, ...
3602 JCTree extending;
3603 List<JCExpression> implementing;
3604 if ((bs.head.tsym.flags() & INTERFACE) == 0) {
3605 extending = tree.bounds.head;
3606 implementing = tree.bounds.tail;
3607 } else {
3608 extending = null;
3609 implementing = tree.bounds;
3610 }
3611 JCClassDecl cd = make.at(tree.pos).ClassDef(
3612 make.Modifiers(PUBLIC | ABSTRACT),
3613 tree.name, List.<JCTypeParameter>nil(),
3614 extending, implementing, List.<JCTree>nil());
3615
3616 ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym;
3617 assert (c.flags() & COMPOUND) != 0;
3618 cd.sym = c;
3619 c.sourcefile = env.toplevel.sourcefile;
3620
3621 // ... and attribute the bound class
3622 c.flags_field |= UNATTRIBUTED;
3623 Env<AttrContext> cenv = enter.classEnv(cd, env);
3624 enter.typeEnvs.put(c, cenv);
3625 }
3626 }
3627
3628
3629 public void visitWildcard(JCWildcard tree) {
3630 //- System.err.println("visitWildcard("+tree+");");//DEBUG
3631 Type type = (tree.kind.kind == BoundKind.UNBOUND)
3632 ? syms.objectType
3633 : attribType(tree.inner, env);
3634 result = check(tree, new WildcardType(chk.checkRefType(tree.pos(), type),
3635 tree.kind.kind,
3636 syms.boundClass),
3637 TYP, pkind, pt);
3638 }
3639
3640 public void visitAnnotation(JCAnnotation tree) {
3641 log.error(tree.pos(), "annotation.not.valid.for.type", pt);
3642 result = tree.type = syms.errType;
3643 }
3644
3645 public void visitErroneous(JCErroneous tree) {
3646 if (tree.errs != null)
3647 for (JCTree err : tree.errs)
3648 attribTree(err, env, ERR, pt);
3649 result = tree.type = syms.errType;
3650 }
3651
3652 /** Default visitor method for all other trees.
3653 */
3654 public void visitTree(JCTree tree) {
3655 throw new AssertionError();
3656 }
3657
3658 /** Main method: attribute class definition associated with given class symbol.
3659 * reporting completion failures at the given position.
3660 * @param pos The source position at which completion errors are to be
3661 * reported.
3662 * @param c The class symbol whose definition will be attributed.
3663 */
3664 public void attribClass(DiagnosticPosition pos, ClassSymbol c) {
3665 try {
3666 annotate.flush();
3667 attribClass(c);
3668 } catch (CompletionFailure ex) {
3669 chk.completionError(pos, ex);
3670 }
3671 }
3672
3673 /** Attribute class definition associated with given class symbol.
3674 * @param c The class symbol whose definition will be attributed.
3675 */
3676 void attribClass(ClassSymbol c) throws CompletionFailure {
3677 if (c.type.tag == ERROR) return;
3678
3679 // Check for cycles in the inheritance graph, which can arise from
3680 // ill-formed class files.
3681 chk.checkNonCyclic(null, c.type);
3682
3683 Type st = types.supertype(c.type);
3684 if ((c.flags_field & Flags.COMPOUND) == 0) {
3685 // First, attribute superclass.
3686 if (st.tag == CLASS)
3687 attribClass((ClassSymbol)st.tsym);
3688
3689 // Next attribute owner, if it is a class.
3690 if (c.owner.kind == TYP && c.owner.type.tag == CLASS)
3691 attribClass((ClassSymbol)c.owner);
3692 }
3693
3694 // The previous operations might have attributed the current class
3695 // if there was a cycle. So we test first whether the class is still
3696 // UNATTRIBUTED.
3697 if ((c.flags_field & UNATTRIBUTED) != 0) {
3698 c.flags_field &= ~UNATTRIBUTED;
3699
3700 // Get environment current at the point of class definition.
3701 Env<AttrContext> env = enter.typeEnvs.get(c);
3702
3703 // The info.lint field in the envs stored in enter.typeEnvs is deliberately uninitialized,
3704 // because the annotations were not available at the time the env was created. Therefore,
3705 // we look up the environment chain for the first enclosing environment for which the
3706 // lint value is set. Typically, this is the parent env, but might be further if there
3707 // are any envs created as a result of TypeParameter nodes.
3708 Env<AttrContext> lintEnv = env;
3709 while (lintEnv.info.lint == null)
3710 lintEnv = lintEnv.next;
3711
3712 // Having found the enclosing lint value, we can initialize the lint value for this class
3713 env.info.lint = lintEnv.info.lint.augment(c.attributes_field, c.flags());
3714
3715 Lint prevLint = chk.setLint(env.info.lint);
3716 JavaFileObject prev = log.useSource(c.sourcefile);
3717
3718 try {
3719 // java.lang.Enum may not be subclassed by a non-enum
3720 if (st.tsym == syms.enumSym &&
3721 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0))
3722 log.error(env.tree.pos(), "enum.no.subclassing");
3723
3724 // Enums may not be extended by source-level classes
3725 if (st.tsym != null &&
3726 ((st.tsym.flags_field & Flags.ENUM) != 0) &&
3727 ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0) &&
3728 !target.compilerBootstrap(c)) {
3729 log.error(env.tree.pos(), "enum.types.not.extensible");
3730 }
3731 attribClassBody(env, c);
3732
3733 chk.checkDeprecatedAnnotation(env.tree.pos(), c);
3734 } finally {
3735 log.useSource(prev);
3736 chk.setLint(prevLint);
3737 }
3738
3739 }
3740 }
3741
3742 public void visitImport(JCImport tree) {
3743 // nothing to do
3744 }
3745
3746 // mgr: added let expressions
3747 public void visitLetExpr(LetExpr tree) {
3748 attribStats(tree.defs, env);
3749 Type t = attribExpr(tree.expr, env);
3750 result = check(tree, t, pkind, pkind, pt);
3751 }
3752
3753 /** Finish the attribution of a class. */
3754 private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
3755 JCClassDecl tree = (JCClassDecl)env.tree;
3756 assert c == tree.sym;
3757
3758 // Validate annotations
3759 chk.validateAnnotations(tree.mods.annotations, c);
3760
3761 // Validate type parameters, supertype and interfaces.
3762 attribBounds(tree.typarams);
3763 chk.validate(tree.typarams, env);
3764 chk.validate(tree.extending, env);
3765 chk.validate(tree.implementing, env);
3766
3767 // If this is a non-abstract class, check that it has no abstract
3768 // methods or unimplemented methods of an implemented interface.
3769 if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) {
3770 if (!relax)
3771 chk.checkAllDefined(tree.pos(), c);
3772 }
3773
3774 if ((c.flags() & ANNOTATION) != 0) {
3775 if (tree.implementing.nonEmpty())
3776 log.error(tree.implementing.head.pos(),
3777 "cant.extend.intf.annotation");
3778 if (tree.typarams.nonEmpty())
3779 log.error(tree.typarams.head.pos(),
3780 "intf.annotation.cant.have.type.params");
3781 } else {
3782 // Check that all extended classes and interfaces
3783 // are compatible (i.e. no two define methods with same arguments
3784 // yet different return types). (JLS 8.4.6.3)
3785 chk.checkCompatibleSupertypes(tree.pos(), c.type);
3786 }
3787
3788 // Check that class does not import the same parameterized interface
3789 // with two different argument lists.
3790 chk.checkClassBounds(tree.pos(), c.type);
3791
3792 tree.type = c.type;
3793
3794 boolean assertsEnabled = false;
3795 assert assertsEnabled = true;
3796 if (assertsEnabled) {
3797 for (List<JCTypeParameter> l = tree.typarams;
3798 l.nonEmpty(); l = l.tail)
3799 assert env.info.scope.lookup(l.head.name).scope != null;
3800 }
3801
3802 // Check that a generic class doesn't extend Throwable
3803 if (!c.type.allparams().isEmpty() && types.isSubtype(c.type, syms.throwableType))
3804 log.error(tree.extending.pos(), "generic.throwable");
3805
3806 // Check that all methods which implement some
3807 // method conform to the method they implement.
3808 chk.checkImplementations(tree);
3809
3810 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
3811 // Attribute declaration
3812 attribStat(l.head, env);
3813 // Check that declarations in inner classes are not static (JLS 8.1.2)
3814 // Make an exception for static constants.
3815 if (c.owner.kind != PCK &&
3816 ((c.flags() & STATIC) == 0 || c.name == names.empty) &&
3817 (TreeInfo.flags(l.head) & (STATIC | INTERFACE)) != 0) {
3818 Symbol sym = null;
3819 if (l.head.getTag() == JCTree.VARDEF) sym = ((JCVariableDecl) l.head).sym;
3820 if (sym == null ||
3821 sym.kind != VAR ||
3822 ((VarSymbol) sym).getConstValue() == null)
3823 log.error(l.head.pos(), "icls.cant.have.static.decl");
3824 }
3825 }
3826
3827 // Check for cycles among non-initial constructors.
3828 chk.checkCyclicConstructors(tree);
3829
3830 // Check for cycles among annotation elements.
3831 chk.checkNonCyclicElements(tree);
3832
3833 // Check for proper use of serialVersionUID
3834 if (env.info.lint.isEnabled(Lint.LintCategory.SERIAL) &&
3835 isSerializable(c) &&
3836 (c.flags() & Flags.ENUM) == 0 &&
3837 (c.flags() & ABSTRACT) == 0) {
3838 checkSerialVersionUID(tree, c);
3839 }
3840
3841 // mgr: escape safety
3842 // If the class has at least one separable ctor, then calling
3843 // non-separable methods or ctors from (static) initializers is illegal
3844 if (tree.containsEscapeSafeCtors && tree.containsNonEscapeSafeInitializers) {
3845 // error: calling non-separable methods or ctors even though class contains at least one separable ctor
3846 for(JCTree d: tree.defs) {
3847 if (d instanceof JCMethodDecl) {
3848 JCMethodDecl m = (JCMethodDecl)d;
3849 if (m.name == names.init) {
3850 boolean isCtorEscapeSafe = ((m.sym.flags() & SEPARABLE)!=0);
3851 if (isCtorEscapeSafe) {
3852 log.error(m.pos(), "escapesafe.ctor.but.non.escapesafe.initializer");
3853 }
3854 }
3855 }
3856 }
3857 }
3858 }
3859 // where
3860 /** check if a class is a subtype of Serializable, if that is available. */
3861 private boolean isSerializable(ClassSymbol c) {
3862 try {
3863 syms.serializableType.complete();
3864 }
3865 catch (CompletionFailure e) {
3866 return false;
3867 }
3868 return types.isSubtype(c.type, syms.serializableType);
3869 }
3870
3871 /** Check that an appropriate serialVersionUID member is defined. */
3872 private void checkSerialVersionUID(JCClassDecl tree, ClassSymbol c) {
3873
3874 // check for presence of serialVersionUID
3875 Scope.Entry e = c.members().lookup(names.serialVersionUID);
3876 while (e.scope != null && e.sym.kind != VAR) e = e.next();
3877 if (e.scope == null) {
3878 log.warning(tree.pos(), "missing.SVUID", c);
3879 return;
3880 }
3881
3882 // check that it is static final
3883 VarSymbol svuid = (VarSymbol)e.sym;
3884 if ((svuid.flags() & (STATIC | FINAL)) !=
3885 (STATIC | FINAL))
3886 log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "improper.SVUID", c);
3887
3888 // check that it is long
3889 else if (svuid.type.tag != TypeTags.LONG)
3890 log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "long.SVUID", c);
3891
3892 // check constant
3893 else if (svuid.getConstValue() == null)
3894 log.warning(TreeInfo.diagnosticPositionFor(svuid, tree), "constant.SVUID", c);
3895 }
3896
3897 private Type capture(Type type) {
3898 return types.capture(type);
3899 }
3900 }