MemberEnter.java revision 4195:cfc4a56c86f9
1/* 2 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.comp; 27 28import java.util.EnumSet; 29import java.util.Set; 30 31import com.sun.tools.javac.code.*; 32import com.sun.tools.javac.code.Scope.WriteableScope; 33import com.sun.tools.javac.tree.*; 34import com.sun.tools.javac.util.*; 35import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 36 37import com.sun.tools.javac.code.Symbol.*; 38import com.sun.tools.javac.code.Type.*; 39import com.sun.tools.javac.tree.JCTree.*; 40 41import static com.sun.tools.javac.code.Flags.*; 42import static com.sun.tools.javac.code.Kinds.*; 43import static com.sun.tools.javac.code.Kinds.Kind.*; 44import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 45 46/** Resolves field, method and constructor header, and constructs corresponding Symbols. 47 * 48 * <p><b>This is NOT part of any supported API. 49 * If you write code that depends on this, you do so at your own risk. 50 * This code and its internal interfaces are subject to change or 51 * deletion without notice.</b> 52 */ 53public class MemberEnter extends JCTree.Visitor { 54 protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>(); 55 56 private final Enter enter; 57 private final Log log; 58 private final Check chk; 59 private final Attr attr; 60 private final Symtab syms; 61 private final Annotate annotate; 62 private final Types types; 63 private final DeferredLintHandler deferredLintHandler; 64 65 public static MemberEnter instance(Context context) { 66 MemberEnter instance = context.get(memberEnterKey); 67 if (instance == null) 68 instance = new MemberEnter(context); 69 return instance; 70 } 71 72 protected MemberEnter(Context context) { 73 context.put(memberEnterKey, this); 74 enter = Enter.instance(context); 75 log = Log.instance(context); 76 chk = Check.instance(context); 77 attr = Attr.instance(context); 78 syms = Symtab.instance(context); 79 annotate = Annotate.instance(context); 80 types = Types.instance(context); 81 deferredLintHandler = DeferredLintHandler.instance(context); 82 } 83 84 /** Construct method type from method signature. 85 * @param typarams The method's type parameters. 86 * @param params The method's value parameters. 87 * @param res The method's result type, 88 * null if it is a constructor. 89 * @param recvparam The method's receiver parameter, 90 * null if none given; TODO: or already set here? 91 * @param thrown The method's thrown exceptions. 92 * @param env The method's (local) environment. 93 */ 94 Type signature(MethodSymbol msym, 95 List<JCTypeParameter> typarams, 96 List<JCVariableDecl> params, 97 JCTree res, 98 JCVariableDecl recvparam, 99 List<JCExpression> thrown, 100 Env<AttrContext> env) { 101 102 // Enter and attribute type parameters. 103 List<Type> tvars = enter.classEnter(typarams, env); 104 attr.attribTypeVariables(typarams, env); 105 106 // Enter and attribute value parameters. 107 ListBuffer<Type> argbuf = new ListBuffer<>(); 108 for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) { 109 memberEnter(l.head, env); 110 argbuf.append(l.head.vartype.type); 111 } 112 113 // Attribute result type, if one is given. 114 Type restype = res == null ? syms.voidType : attr.attribType(res, env); 115 116 // Attribute receiver type, if one is given. 117 Type recvtype; 118 if (recvparam!=null) { 119 memberEnter(recvparam, env); 120 recvtype = recvparam.vartype.type; 121 } else { 122 recvtype = null; 123 } 124 125 // Attribute thrown exceptions. 126 ListBuffer<Type> thrownbuf = new ListBuffer<>(); 127 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) { 128 Type exc = attr.attribType(l.head, env); 129 if (!exc.hasTag(TYPEVAR)) { 130 exc = chk.checkClassType(l.head.pos(), exc); 131 } else if (exc.tsym.owner == msym) { 132 //mark inference variables in 'throws' clause 133 exc.tsym.flags_field |= THROWS; 134 } 135 thrownbuf.append(exc); 136 } 137 MethodType mtype = new MethodType(argbuf.toList(), 138 restype, 139 thrownbuf.toList(), 140 syms.methodClass); 141 mtype.recvtype = recvtype; 142 143 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); 144 } 145 146/* ******************************************************************** 147 * Visitor methods for member enter 148 *********************************************************************/ 149 150 /** Visitor argument: the current environment 151 */ 152 protected Env<AttrContext> env; 153 154 /** Enter field and method definitions and process import 155 * clauses, catching any completion failure exceptions. 156 */ 157 protected void memberEnter(JCTree tree, Env<AttrContext> env) { 158 Env<AttrContext> prevEnv = this.env; 159 try { 160 this.env = env; 161 tree.accept(this); 162 } catch (CompletionFailure ex) { 163 chk.completionError(tree.pos(), ex); 164 } finally { 165 this.env = prevEnv; 166 } 167 } 168 169 /** Enter members from a list of trees. 170 */ 171 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) { 172 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 173 memberEnter(l.head, env); 174 } 175 176 public void visitMethodDef(JCMethodDecl tree) { 177 WriteableScope enclScope = enter.enterScope(env); 178 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); 179 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); 180 tree.sym = m; 181 182 //if this is a default method, add the DEFAULT flag to the enclosing interface 183 if ((tree.mods.flags & DEFAULT) != 0) { 184 m.enclClass().flags_field |= DEFAULT; 185 } 186 187 Env<AttrContext> localEnv = methodEnv(tree, env); 188 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 189 try { 190 // Compute the method type 191 m.type = signature(m, tree.typarams, tree.params, 192 tree.restype, tree.recvparam, 193 tree.thrown, 194 localEnv); 195 } finally { 196 deferredLintHandler.setPos(prevLintPos); 197 } 198 199 if (types.isSignaturePolymorphic(m)) { 200 m.flags_field |= SIGNATURE_POLYMORPHIC; 201 } 202 203 // Set m.params 204 ListBuffer<VarSymbol> params = new ListBuffer<>(); 205 JCVariableDecl lastParam = null; 206 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 207 JCVariableDecl param = lastParam = l.head; 208 params.append(Assert.checkNonNull(param.sym)); 209 } 210 m.params = params.toList(); 211 212 // mark the method varargs, if necessary 213 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0) 214 m.flags_field |= Flags.VARARGS; 215 216 localEnv.info.scope.leave(); 217 if (chk.checkUnique(tree.pos(), m, enclScope)) { 218 enclScope.enter(m); 219 } 220 221 annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); 222 // Visit the signature of the method. Note that 223 // TypeAnnotate doesn't descend into the body. 224 annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, m, tree.pos()); 225 226 if (tree.defaultValue != null) { 227 m.defaultValue = annotate.unfinishedDefaultValue(); // set it to temporary sentinel for now 228 annotate.annotateDefaultValueLater(tree.defaultValue, localEnv, m, tree.pos()); 229 } 230 } 231 232 /** Create a fresh environment for method bodies. 233 * @param tree The method definition. 234 * @param env The environment current outside of the method definition. 235 */ 236 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) { 237 Env<AttrContext> localEnv = 238 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(tree.sym))); 239 localEnv.enclMethod = tree; 240 if (tree.sym.type != null) { 241 //when this is called in the enter stage, there's no type to be set 242 localEnv.info.returnResult = attr.new ResultInfo(KindSelector.VAL, 243 tree.sym.type.getReturnType()); 244 } 245 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 246 return localEnv; 247 } 248 249 public void visitVarDef(JCVariableDecl tree) { 250 Env<AttrContext> localEnv = env; 251 if ((tree.mods.flags & STATIC) != 0 || 252 (env.info.scope.owner.flags() & INTERFACE) != 0) { 253 localEnv = env.dup(tree, env.info.dup()); 254 localEnv.info.staticLevel++; 255 } 256 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 257 258 try { 259 if (TreeInfo.isEnumInit(tree)) { 260 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 261 } else { 262 attr.attribType(tree.vartype, localEnv); 263 if (TreeInfo.isReceiverParam(tree)) 264 checkReceiver(tree, localEnv); 265 } 266 } finally { 267 deferredLintHandler.setPos(prevLintPos); 268 } 269 270 if ((tree.mods.flags & VARARGS) != 0) { 271 //if we are entering a varargs parameter, we need to 272 //replace its type (a plain array type) with the more 273 //precise VarargsType --- we need to do it this way 274 //because varargs is represented in the tree as a 275 //modifier on the parameter declaration, and not as a 276 //distinct type of array node. 277 ArrayType atype = (ArrayType)tree.vartype.type; 278 tree.vartype.type = atype.makeVarargs(); 279 } 280 WriteableScope enclScope = enter.enterScope(env); 281 VarSymbol v = 282 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner); 283 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 284 tree.sym = v; 285 if (tree.init != null) { 286 v.flags_field |= HASINIT; 287 if ((v.flags_field & FINAL) != 0 && 288 needsLazyConstValue(tree.init)) { 289 Env<AttrContext> initEnv = getInitEnv(tree, env); 290 initEnv.info.enclVar = v; 291 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); 292 } 293 } 294 if (chk.checkUnique(tree.pos(), v, enclScope)) { 295 chk.checkTransparentVar(tree.pos(), v, enclScope); 296 enclScope.enter(v); 297 } 298 299 annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); 300 annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v, tree.pos()); 301 302 v.pos = tree.pos; 303 } 304 // where 305 void checkType(JCTree tree, Type type, String diag) { 306 if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) { 307 log.error(tree, diag, type, tree.type); 308 } 309 } 310 void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { 311 attr.attribExpr(tree.nameexpr, localEnv); 312 MethodSymbol m = localEnv.enclMethod.sym; 313 if (m.isConstructor()) { 314 Type outertype = m.owner.owner.type; 315 if (outertype.hasTag(TypeTag.METHOD)) { 316 // we have a local inner class 317 outertype = m.owner.owner.owner.type; 318 } 319 if (outertype.hasTag(TypeTag.CLASS)) { 320 checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); 321 checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); 322 } else { 323 log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); 324 } 325 } else { 326 checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); 327 checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); 328 } 329 } 330 331 public boolean needsLazyConstValue(JCTree tree) { 332 InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 333 tree.accept(initTreeVisitor); 334 return initTreeVisitor.result; 335 } 336 337 /** Visitor class for expressions which might be constant expressions, 338 * as per JLS 15.28 (Constant Expressions). 339 */ 340 static class InitTreeVisitor extends JCTree.Visitor { 341 342 private static final Set<Tag> ALLOWED_OPERATORS = 343 EnumSet.of(Tag.POS, Tag.NEG, Tag.NOT, Tag.COMPL, Tag.PLUS, Tag.MINUS, 344 Tag.MUL, Tag.DIV, Tag.MOD, Tag.SL, Tag.SR, Tag.USR, 345 Tag.LT, Tag.LE, Tag.GT, Tag.GE, Tag.EQ, Tag.NE, 346 Tag.BITAND, Tag.BITXOR, Tag.BITOR, Tag.AND, Tag.OR); 347 348 boolean result = true; 349 350 @Override 351 public void visitTree(JCTree tree) { 352 result = false; 353 } 354 355 @Override 356 public void visitLiteral(JCLiteral that) {} 357 358 @Override 359 public void visitTypeCast(JCTypeCast tree) { 360 tree.expr.accept(this); 361 } 362 363 @Override 364 public void visitUnary(JCUnary that) { 365 if (!ALLOWED_OPERATORS.contains(that.getTag())) { 366 result = false; 367 return ; 368 } 369 that.arg.accept(this); 370 } 371 372 @Override 373 public void visitBinary(JCBinary that) { 374 if (!ALLOWED_OPERATORS.contains(that.getTag())) { 375 result = false; 376 return ; 377 } 378 that.lhs.accept(this); 379 that.rhs.accept(this); 380 } 381 382 @Override 383 public void visitConditional(JCConditional tree) { 384 tree.cond.accept(this); 385 tree.truepart.accept(this); 386 tree.falsepart.accept(this); 387 } 388 389 @Override 390 public void visitParens(JCParens tree) { 391 tree.expr.accept(this); 392 } 393 394 @Override 395 public void visitIdent(JCIdent that) {} 396 397 @Override 398 public void visitSelect(JCFieldAccess tree) { 399 tree.selected.accept(this); 400 } 401 } 402 403 /** Create a fresh environment for a variable's initializer. 404 * If the variable is a field, the owner of the environment's scope 405 * is be the variable itself, otherwise the owner is the method 406 * enclosing the variable definition. 407 * 408 * @param tree The variable definition. 409 * @param env The environment current outside of the variable definition. 410 */ 411 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 412 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 413 if (tree.sym.owner.kind == TYP) { 414 localEnv.info.scope = env.info.scope.dupUnshared(tree.sym); 415 } 416 if ((tree.mods.flags & STATIC) != 0 || 417 ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null)) 418 localEnv.info.staticLevel++; 419 return localEnv; 420 } 421 422 /** Default member enter visitor method: do nothing 423 */ 424 public void visitTree(JCTree tree) { 425 } 426 427 public void visitErroneous(JCErroneous tree) { 428 if (tree.errs != null) 429 memberEnter(tree.errs, env); 430 } 431 432 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 433 Env<AttrContext> mEnv = methodEnv(tree, env); 434 mEnv.info.lint = mEnv.info.lint.augment(tree.sym); 435 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 436 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 437 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 438 mEnv.info.scope.enterIfAbsent(l.head.sym); 439 return mEnv; 440 } 441 442 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 443 Env<AttrContext> iEnv = initEnv(tree, env); 444 return iEnv; 445 } 446} 447