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