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