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);
         }