src/share/classes/com/sun/tools/javac/comp/Attr.java
Print this page
@@ -195,11 +195,11 @@
* @param pt The expected type (or: prototype) of the tree
*/
Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) {
if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) {
if ((ownkind & ~pkind) == 0) {
- owntype = chk.checkType(tree.pos(), owntype, pt);
+ owntype = chk.checkType(tree.pos(), owntype, pt, errKey);
} else {
log.error(tree.pos(), "unexpected.type",
kindNames(pkind),
kindName(ownkind));
owntype = types.createErrorType(owntype);
@@ -242,13 +242,17 @@
((v.flags() & HASINIT) != 0
||
!((base == null ||
(base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) &&
isAssignableAsBlankFinal(v, env)))) {
+ if (v.isResourceVariable()) { //ARM resource
+ log.error(pos, "arm.resource.may.not.be.assigned", v);
+ } else {
log.error(pos, "cant.assign.val.to.final.var", v);
}
}
+ }
/** Does tree represent a static reference to an identifier?
* It is assumed that tree is either a SELECT or an IDENT.
* We have to weed out selects from non-type names here.
* @param tree The candidate tree.
@@ -375,10 +379,14 @@
/** Visitor argument: the currently expected proto-type.
*/
Type pt;
+ /** Visitor argument: the error key to be generated when a type error occurs
+ */
+ String errKey;
+
/** Visitor result: the computed type.
*/
Type result;
/** Visitor method: attribute a tree, catching any completion failure
@@ -388,17 +396,23 @@
* @param env The environment visitor argument.
* @param pkind The protokind visitor argument.
* @param pt The prototype visitor argument.
*/
Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt) {
+ return attribTree(tree, env, pkind, pt, "incompatible.types");
+ }
+
+ Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt, String errKey) {
Env<AttrContext> prevEnv = this.env;
int prevPkind = this.pkind;
Type prevPt = this.pt;
+ String prevErrKey = this.errKey;
try {
this.env = env;
this.pkind = pkind;
this.pt = pt;
+ this.errKey = errKey;
tree.accept(this);
if (tree == breakTree)
throw new BreakAttr(env);
return result;
} catch (CompletionFailure ex) {
@@ -406,19 +420,24 @@
return chk.completionError(tree.pos(), ex);
} finally {
this.env = prevEnv;
this.pkind = prevPkind;
this.pt = prevPt;
+ this.errKey = prevErrKey;
}
}
/** Derived visitor method: attribute an expression tree.
*/
public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType);
}
+ public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt, String key) {
+ return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType, key);
+ }
+
/** Derived visitor method: attribute an expression tree with
* no constraints on the computed type.
*/
Type attribExpr(JCTree tree, Env<AttrContext> env) {
return attribTree(tree, env, VAL, Type.noType);
@@ -979,18 +998,39 @@
attribStat(tree.body, env);
result = null;
}
public void visitTry(JCTry tree) {
+ // Create a new local environment with a local scope.
+ Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
+ // Attribute resource declarations
+ ListBuffer<VarSymbol> resourceVars = ListBuffer.lb();
+ for (JCTree resource : tree.resources) {
+ if (resource.getTag() == JCTree.VARDEF) {
+ attribStat(resource, localEnv);
+ chk.checkType(resource, resource.type, syms.autoCloseableType, "arm.not.applicable.to.type");
+ VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource);
+ var.setData(ElementKind.RESOURCE_VARIABLE);
+ resourceVars.append(var);
+ } else {
+ attribExpr(resource, localEnv, syms.autoCloseableType, "arm.not.applicable.to.type");
+ }
+ }
// Attribute body
- attribStat(tree.body, env.dup(tree, env.info.dup()));
+ attribStat(tree.body, localEnv.dup(tree, localEnv.info.dup()));
+
+ //remove arm resource vars from local scope - such variables cannot be
+ //accessed from catch/finally clauses
+ for (VarSymbol resourceVar : resourceVars) {
+ localEnv.info.scope.remove(resourceVar);
+ }
// Attribute catch clauses
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
JCCatch c = l.head;
Env<AttrContext> catchEnv =
- env.dup(c, env.info.dup(env.info.scope.dup()));
+ localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup()));
Type ctype = attribStat(c.param, catchEnv);
if (TreeInfo.isMultiCatch(c)) {
//check that multi-catch parameter is marked as final
if ((c.param.sym.flags() & FINAL) == 0) {
log.error(c.param.pos(), "multicatch.param.must.be.final", c.param.sym);
@@ -1006,11 +1046,13 @@
attribStat(c.body, catchEnv);
catchEnv.info.scope.leave();
}
// Attribute finalizer
- if (tree.finalizer != null) attribStat(tree.finalizer, env);
+ if (tree.finalizer != null) attribStat(tree.finalizer, localEnv);
+
+ localEnv.info.scope.leave();
result = null;
}
public void visitConditional(JCConditional tree) {
attribExpr(tree.cond, env, syms.booleanType);
@@ -2136,10 +2178,19 @@
// that the variable is assignable in the current environment.
if (pkind == VAR)
checkAssignable(tree.pos(), v, tree.selected, env);
}
+ if (sitesym != null &&
+ sitesym.kind == VAR &&
+ ((VarSymbol)sitesym).isResourceVariable() &&
+ sym.kind == MTH &&
+ sym.name == names.close &&
+ env.info.lint.isEnabled(Lint.LintCategory.ARM)) {
+ log.warning(tree, "arm.explicit.close.call");
+ }
+
// Disallow selecting a type from an expression
if (isType(sym) && (sitesym==null || (sitesym.kind&(TYP|PCK)) == 0)) {
tree.type = check(tree.selected, pt,
sitesym == null ? VAL : sitesym.kind, TYP|PCK, pt);
}