1 /* 2 * Copyright (c) 2003, 2019, 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 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 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 */ 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, true); 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 */ 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 */ 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 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 if (m.isConstructor() && m.type.getParameterTypes().size() == 0) { 234 int statsSize = tree.body.stats.size(); 235 if (statsSize == 0) { 236 m.flags_field |= EMPTYNOARGCONSTR; 237 } else if (statsSize == 1 && TreeInfo.isSuperCall(tree.body.stats.head)) { 238 JCExpressionStatement exec = (JCExpressionStatement) tree.body.stats.head; 239 JCMethodInvocation meth = (JCMethodInvocation)exec.expr; 240 if (meth.args.size() == 0) { 241 // Deem a constructor "empty" even if it contains a 'super' call, 242 // as long as it has no argument expressions (to respect common coding style). 243 m.flags_field |= EMPTYNOARGCONSTR; 244 } 245 } 246 } 247 } 248 249 /** Create a fresh environment for method bodies. 250 * @param tree The method definition. 251 * @param env The environment current outside of the method definition. 252 */ 253 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) { 254 Env<AttrContext> localEnv = 255 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(tree.sym))); 256 localEnv.enclMethod = tree; 257 if (tree.sym.type != null) { 258 //when this is called in the enter stage, there's no type to be set 259 localEnv.info.returnResult = attr.new ResultInfo(KindSelector.VAL, 260 tree.sym.type.getReturnType()); 261 } 262 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 263 localEnv.info.yieldResult = null; 264 return localEnv; 265 } 266 267 @Override 268 public void visitBlock(JCBlock tree) { 269 if ((tree.flags & STATIC) == 0 && tree.stats.size() > 0) 270 env.info.scope.owner.flags_field |= HASINITBLOCK; 271 } 272 273 public void visitVarDef(JCVariableDecl tree) { 274 Env<AttrContext> localEnv = env; 275 if ((tree.mods.flags & STATIC) != 0 || 276 (env.info.scope.owner.flags() & INTERFACE) != 0) { 277 localEnv = env.dup(tree, env.info.dup()); 278 localEnv.info.staticLevel++; 279 } 280 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 281 282 try { 283 if (TreeInfo.isEnumInit(tree)) { 284 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 285 } else if (!tree.isImplicitlyTyped()) { 286 attr.attribType(tree.vartype, localEnv); 287 if (TreeInfo.isReceiverParam(tree)) 288 checkReceiver(tree, localEnv); 289 } 290 } finally { 291 deferredLintHandler.setPos(prevLintPos); 292 } 293 294 if ((tree.mods.flags & VARARGS) != 0) { 295 //if we are entering a varargs parameter, we need to 296 //replace its type (a plain array type) with the more 297 //precise VarargsType --- we need to do it this way 298 //because varargs is represented in the tree as a 299 //modifier on the parameter declaration, and not as a 300 //distinct type of array node. 301 ArrayType atype = (ArrayType)tree.vartype.type; 302 tree.vartype.type = atype.makeVarargs(); 303 } 304 WriteableScope enclScope = enter.enterScope(env); 305 Type vartype = tree.isImplicitlyTyped() 306 ? env.info.scope.owner.kind == MTH ? Type.noType : syms.errType 307 : tree.vartype.type; 308 VarSymbol v = new VarSymbol(0, tree.name, vartype, enclScope.owner); 309 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 310 tree.sym = v; 311 /* Don't want constant propagation/folding for instance fields of primitive classes, 312 as these can undergo updates via copy on write. 313 */ 314 if (tree.init != null) { 315 v.flags_field |= HASINIT; 316 if ((v.flags_field & FINAL) != 0 && ((v.flags_field & STATIC) != 0 || !v.owner.isValueClass()) && 317 needsLazyConstValue(tree.init)) { 318 Env<AttrContext> initEnv = getInitEnv(tree, env); 319 initEnv.info.enclVar = v; 320 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); 321 } 322 } 323 if (chk.checkUnique(tree.pos(), v, enclScope)) { 324 chk.checkTransparentVar(tree.pos(), v, enclScope); 325 enclScope.enter(v); 326 } else if (v.owner.kind == MTH || (v.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0) { 327 // if this is a parameter or a field obtained from a record component, enter it 328 enclScope.enter(v); 329 } 330 331 annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); 332 if (!tree.isImplicitlyTyped()) { 333 annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v, tree.pos()); 334 } 335 336 v.pos = tree.pos; 337 } 338 // where 339 void checkType(JCTree tree, Type type, Error errorKey) { 340 if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) { 341 log.error(tree, errorKey); 342 } 343 } 344 void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { 345 attr.attribExpr(tree.nameexpr, localEnv); 346 MethodSymbol m = localEnv.enclMethod.sym; 347 if (m.isConstructor()) { 348 Type outertype = m.owner.owner.type; 349 if (outertype.hasTag(TypeTag.METHOD)) { 350 // we have a local inner class 351 outertype = m.owner.owner.owner.type; 352 } 353 if (outertype.hasTag(TypeTag.CLASS)) { 354 checkType(tree.vartype, outertype, Errors.IncorrectConstructorReceiverType(outertype, tree.vartype.type)); 355 checkType(tree.nameexpr, outertype, Errors.IncorrectConstructorReceiverName(outertype, tree.nameexpr.type)); 356 } else { 357 log.error(tree, Errors.ReceiverParameterNotApplicableConstructorToplevelClass); 358 } 359 } else { 360 checkType(tree.vartype, m.owner.type, Errors.IncorrectReceiverType(m.owner.type, tree.vartype.type)); 361 checkType(tree.nameexpr, m.owner.type, Errors.IncorrectReceiverName(m.owner.type, tree.nameexpr.type)); 362 } 363 } 364 365 public boolean needsLazyConstValue(JCTree tree) { 366 InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 367 tree.accept(initTreeVisitor); 368 return initTreeVisitor.result; 369 } 370 371 /** Visitor class for expressions which might be constant expressions, 372 * as per JLS 15.28 (Constant Expressions). 373 */ 374 static class InitTreeVisitor extends JCTree.Visitor { 375 376 private static final Set<Tag> ALLOWED_OPERATORS = 377 EnumSet.of(Tag.POS, Tag.NEG, Tag.NOT, Tag.COMPL, Tag.PLUS, Tag.MINUS, 378 Tag.MUL, Tag.DIV, Tag.MOD, Tag.SL, Tag.SR, Tag.USR, 379 Tag.LT, Tag.LE, Tag.GT, Tag.GE, Tag.EQ, Tag.NE, 380 Tag.BITAND, Tag.BITXOR, Tag.BITOR, Tag.AND, Tag.OR); 381 382 boolean result = true; 383 384 @Override 385 public void visitTree(JCTree tree) { 386 result = false; 387 } 388 389 @Override 390 public void visitLiteral(JCLiteral that) {} 391 392 @Override 393 public void visitTypeCast(JCTypeCast tree) { 394 tree.expr.accept(this); 395 } 396 397 @Override 398 public void visitUnary(JCUnary that) { 399 if (!ALLOWED_OPERATORS.contains(that.getTag())) { 400 result = false; 401 return ; 402 } 403 that.arg.accept(this); 404 } 405 406 @Override 407 public void visitBinary(JCBinary that) { 408 if (!ALLOWED_OPERATORS.contains(that.getTag())) { 409 result = false; 410 return ; 411 } 412 that.lhs.accept(this); 413 that.rhs.accept(this); 414 } 415 416 @Override 417 public void visitConditional(JCConditional tree) { 418 tree.cond.accept(this); 419 tree.truepart.accept(this); 420 tree.falsepart.accept(this); 421 } 422 423 @Override 424 public void visitParens(JCParens tree) { 425 tree.expr.accept(this); 426 } 427 428 @Override 429 public void visitIdent(JCIdent that) {} 430 431 @Override 432 public void visitSelect(JCFieldAccess tree) { 433 tree.selected.accept(this); 434 } 435 } 436 437 /** Create a fresh environment for a variable's initializer. 438 * If the variable is a field, the owner of the environment's scope 439 * is be the variable itself, otherwise the owner is the method 440 * enclosing the variable definition. 441 * 442 * @param tree The variable definition. 443 * @param env The environment current outside of the variable definition. 444 */ 445 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 446 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 447 if (tree.sym.owner.kind == TYP) { 448 localEnv.info.scope = env.info.scope.dupUnshared(tree.sym); 449 } 450 if ((tree.mods.flags & STATIC) != 0 || 451 ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null)) 452 localEnv.info.staticLevel++; 453 return localEnv; 454 } 455 456 /** Default member enter visitor method: do nothing 457 */ 458 public void visitTree(JCTree tree) { 459 } 460 461 public void visitErroneous(JCErroneous tree) { 462 if (tree.errs != null) 463 memberEnter(tree.errs, env); 464 } 465 466 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 467 Env<AttrContext> mEnv = methodEnv(tree, env); 468 mEnv.info.lint = mEnv.info.lint.augment(tree.sym); 469 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 470 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 471 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 472 mEnv.info.scope.enterIfAbsent(l.head.sym); 473 return mEnv; 474 } 475 476 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 477 Env<AttrContext> iEnv = initEnv(tree, env); 478 return iEnv; 479 } 480 }