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