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