107 final Analyzer analyzer;
108 final DeferredAttr deferredAttr;
109 final Check chk;
110 final Flow flow;
111 final MemberEnter memberEnter;
112 final TypeEnter typeEnter;
113 final TreeMaker make;
114 final ConstFold cfolder;
115 final Enter enter;
116 final Target target;
117 final Types types;
118 final Preview preview;
119 final JCDiagnostic.Factory diags;
120 final TypeAnnotations typeAnnotations;
121 final TypeEnvs typeEnvs;
122 final Dependencies dependencies;
123 final Annotate annotate;
124 final ArgumentAttr argumentAttr;
125 final MatchBindingsComputer matchBindingsComputer;
126 final AttrRecover attrRecover;
127
128 public static Attr instance(Context context) {
129 Attr instance = context.get(attrKey);
130 if (instance == null)
131 instance = new Attr(context);
132 return instance;
133 }
134
135 @SuppressWarnings("this-escape")
136 protected Attr(Context context) {
137 context.put(attrKey, this);
138
139 names = Names.instance(context);
140 log = Log.instance(context);
141 lintMapper = LintMapper.instance(context);
142 syms = Symtab.instance(context);
143 rs = Resolve.instance(context);
144 operators = Operators.instance(context);
145 chk = Check.instance(context);
146 flow = Flow.instance(context);
147 memberEnter = MemberEnter.instance(context);
148 typeEnter = TypeEnter.instance(context);
149 make = TreeMaker.instance(context);
150 enter = Enter.instance(context);
151 infer = Infer.instance(context);
152 analyzer = Analyzer.instance(context);
153 deferredAttr = DeferredAttr.instance(context);
154 cfolder = ConstFold.instance(context);
155 target = Target.instance(context);
156 types = Types.instance(context);
157 preview = Preview.instance(context);
158 diags = JCDiagnostic.Factory.instance(context);
159 annotate = Annotate.instance(context);
160 typeAnnotations = TypeAnnotations.instance(context);
161 typeEnvs = TypeEnvs.instance(context);
162 dependencies = Dependencies.instance(context);
163 argumentAttr = ArgumentAttr.instance(context);
164 matchBindingsComputer = MatchBindingsComputer.instance(context);
165 attrRecover = AttrRecover.instance(context);
166
167 Options options = Options.instance(context);
168
169 Source source = Source.instance(context);
170 allowReifiableTypesInInstanceof = Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source);
171 allowRecords = Feature.RECORDS.allowedInSource(source);
172 allowPatternSwitch = (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH)) &&
173 Feature.PATTERN_SWITCH.allowedInSource(source);
174 allowUnconditionalPatternsInstanceOf =
175 Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.allowedInSource(source);
176 sourceName = source.name;
177 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
178
179 statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
180 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
181 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
182 methodAttrInfo = new MethodAttrInfo();
183 unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
184 unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType);
185 recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
186 initBlockType = new MethodType(List.nil(), syms.voidType, List.nil(), syms.methodClass);
187 }
188
189 /** Switch: reifiable types in instanceof enabled?
190 */
191 boolean allowReifiableTypesInInstanceof;
192
193 /** Are records allowed
194 */
195 private final boolean allowRecords;
196
197 /** Are patterns in switch allowed
198 */
199 private final boolean allowPatternSwitch;
200
201 /** Are unconditional patterns in instanceof allowed
202 */
203 private final boolean allowUnconditionalPatternsInstanceOf;
204
205 /**
206 * Switch: warn about use of variable before declaration?
207 * RFE: 6425594
208 */
209 boolean useBeforeDeclarationWarning;
210
211 /**
212 * Switch: name of source level; used for error reporting.
213 */
214 String sourceName;
215
216 /** Check kind and type of given tree against protokind and prototype.
217 * If check succeeds, store type in tree and return it.
218 * If check fails, store errType in tree and return it.
219 * No checks are performed if the prototype is a method type.
220 * It is not necessary in this case since we know that kind and type
221 * are correct.
222 *
223 * @param tree The tree whose kind and type is checked
224 * @param found The computed type of the tree
278 owner.kind == VAR || // i.e. we are in a variable initializer
279 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block
280 &&
281 v.owner == owner.owner
282 &&
283 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
284 boolean insideCompactConstructor = env.enclMethod != null && TreeInfo.isCompactConstructor(env.enclMethod);
285 return isAssignable & !insideCompactConstructor;
286 }
287
288 /** Check that variable can be assigned to.
289 * @param pos The current source code position.
290 * @param v The assigned variable
291 * @param base If the variable is referred to in a Select, the part
292 * to the left of the `.', null otherwise.
293 * @param env The current environment.
294 */
295 void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
296 if (v.name == names._this) {
297 log.error(pos, Errors.CantAssignValToThis);
298 return;
299 }
300 if ((v.flags() & FINAL) != 0 &&
301 ((v.flags() & HASINIT) != 0
302 ||
303 !((base == null ||
304 TreeInfo.isThisQualifier(base)) &&
305 isAssignableAsBlankFinal(v, env)))) {
306 if (v.isResourceVariable()) { //TWR resource
307 log.error(pos, Errors.TryResourceMayNotBeAssigned(v));
308 } else {
309 log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v));
310 }
311 return;
312 }
313
314 // Check instance field assignments that appear in constructor prologues
315 if (rs.isEarlyReference(env, base, v)) {
316
317 // Field may not be inherited from a superclass
318 if (v.owner != env.enclClass.sym) {
319 log.error(pos, Errors.CantRefBeforeCtorCalled(v));
320 return;
321 }
322
323 // Field may not have an initializer
324 if ((v.flags() & HASINIT) != 0) {
325 log.error(pos, Errors.CantAssignInitializedBeforeCtorCalled(v));
326 return;
327 }
328 }
329 }
330
331 /** Does tree represent a static reference to an identifier?
332 * It is assumed that tree is either a SELECT or an IDENT.
333 * We have to weed out selects from non-type names here.
334 * @param tree The candidate tree.
335 */
336 boolean isStaticReference(JCTree tree) {
337 if (tree.hasTag(SELECT)) {
338 Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected);
339 if (lsym == null || lsym.kind != TYP) {
340 return false;
341 }
342 }
343 return true;
344 }
345
346 /** Is this symbol a type?
347 */
1102 * - have an accessibility stricter than that of the record type
1103 * - explicitly invoke any other constructor
1104 */
1105 if ((tree.sym.flags_field & GENERATEDCONSTR) == 0) {
1106 if (Check.protection(m.flags()) > Check.protection(env.enclClass.sym.flags())) {
1107 log.error(tree,
1108 (env.enclClass.sym.flags() & AccessFlags) == 0 ?
1109 Errors.InvalidCanonicalConstructorInRecord(
1110 Fragments.Canonical,
1111 env.enclClass.sym.name,
1112 Fragments.CanonicalMustNotHaveStrongerAccess("package")
1113 ) :
1114 Errors.InvalidCanonicalConstructorInRecord(
1115 Fragments.Canonical,
1116 env.enclClass.sym.name,
1117 Fragments.CanonicalMustNotHaveStrongerAccess(asFlagSet(env.enclClass.sym.flags() & AccessFlags))
1118 )
1119 );
1120 }
1121
1122 if (TreeInfo.hasAnyConstructorCall(tree)) {
1123 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1124 Fragments.Canonical, env.enclClass.sym.name,
1125 Fragments.CanonicalMustNotContainExplicitConstructorInvocation));
1126 }
1127 }
1128
1129 // also we want to check that no type variables have been defined
1130 if (!tree.typarams.isEmpty()) {
1131 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1132 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalMustNotDeclareTypeVariables));
1133 }
1134
1135 /* and now we need to check that the constructor's arguments are exactly the same as those of the
1136 * record components
1137 */
1138 List<? extends RecordComponent> recordComponents = env.enclClass.sym.getRecordComponents();
1139 List<Type> recordFieldTypes = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.type);
1140 for (JCVariableDecl param: tree.params) {
1141 boolean paramIsVarArgs = (param.sym.flags_field & VARARGS) != 0;
1142 if (!types.isSameType(param.type, recordFieldTypes.head) ||
1180 if (tree.defaultValue != null) {
1181 if ((owner.flags() & ANNOTATION) == 0)
1182 log.error(tree.pos(),
1183 Errors.DefaultAllowedInIntfAnnotationMember);
1184 }
1185 if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0)
1186 log.error(tree.pos(), Errors.MissingMethBodyOrDeclAbstract(tree.sym, owner));
1187 } else {
1188 if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) {
1189 if ((owner.flags() & INTERFACE) != 0) {
1190 log.error(tree.body.pos(), Errors.IntfMethCantHaveBody);
1191 } else {
1192 log.error(tree.pos(), Errors.AbstractMethCantHaveBody);
1193 }
1194 } else if ((tree.mods.flags & NATIVE) != 0) {
1195 log.error(tree.pos(), Errors.NativeMethCantHaveBody);
1196 }
1197 // Add an implicit super() call unless an explicit call to
1198 // super(...) or this(...) is given
1199 // or we are compiling class java.lang.Object.
1200 if (isConstructor && owner.type != syms.objectType) {
1201 if (!TreeInfo.hasAnyConstructorCall(tree)) {
1202 JCStatement supCall = make.at(tree.body.pos).Exec(make.Apply(List.nil(),
1203 make.Ident(names._super), make.Idents(List.nil())));
1204 tree.body.stats = tree.body.stats.prepend(supCall);
1205 } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&
1206 (tree.mods.flags & GENERATEDCONSTR) == 0 &&
1207 TreeInfo.hasConstructorCall(tree, names._super)) {
1208 // enum constructors are not allowed to call super
1209 // directly, so make sure there aren't any super calls
1210 // in enum constructors, except in the compiler
1211 // generated one.
1212 log.error(tree.body.stats.head.pos(),
1213 Errors.CallToSuperNotAllowedInEnumCtor(env.enclClass.sym));
1214 }
1215 if (env.enclClass.sym.isRecord() && (tree.sym.flags_field & RECORD) != 0) { // we are seeing the canonical constructor
1216 List<Name> recordComponentNames = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.name);
1217 List<Name> initParamNames = tree.sym.params.map(p -> p.name);
1218 if (!initParamNames.equals(recordComponentNames)) {
1219 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1220 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalWithNameMismatch));
1221 }
1222 if (tree.sym.type.asMethodType().thrown != null && !tree.sym.type.asMethodType().thrown.isEmpty()) {
1223 log.error(tree,
1224 Errors.InvalidCanonicalConstructorInRecord(
1225 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical,
1226 env.enclClass.sym.name,
1227 Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(
1228 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical)));
1229 }
1230 }
1231 }
1232
1233 // Attribute all type annotations in the body
1234 annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m);
1235 annotate.flush();
1236
1237 // Start of constructor prologue (if not in java.lang.Object constructor)
1238 localEnv.info.ctorPrologue = isConstructor && owner.type != syms.objectType;
1239
1240 // Attribute method body.
1241 attribStat(tree.body, localEnv);
1242 }
1243
1244 localEnv.info.scope.leave();
1245 result = tree.type = m.type;
1246 } finally {
1247 chk.setLint(prevLint);
1248 chk.setMethod(prevMethod);
1249 env.info.ctorPrologue = ctorProloguePrev;
1250 }
1251 }
1252
1253 public void visitVarDef(JCVariableDecl tree) {
1254 // Local variables have not been entered yet, so we need to do it now:
1255 if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
1256 if (tree.sym != null) {
1257 // parameters have already been entered
1258 env.info.scope.enter(tree.sym);
1259 } else {
1260 if (tree.isImplicitlyTyped() && (tree.getModifiers().flags & PARAMETER) == 0) {
1261 if (tree.init == null) {
1262 //cannot use 'var' without initializer
1263 log.error(tree, Errors.CantInferLocalVarType(tree.name, Fragments.LocalMissingInit));
1264 tree.vartype = make.at(tree.pos()).Erroneous();
1265 } else {
1266 Fragment msg = canInferLocalVarType(tree);
1267 if (msg != null) {
1268 //cannot use 'var' with initializer which require an explicit target
1269 //(e.g. lambda, method reference, array initializer).
1270 log.error(tree, Errors.CantInferLocalVarType(tree.name, msg));
1271 tree.vartype = make.at(tree.pos()).Erroneous();
1272 }
1281 }
1282 } else {
1283 doQueueScanTreeAndTypeAnnotateForVarInit(tree, env);
1284 }
1285
1286 VarSymbol v = tree.sym;
1287 Lint lint = env.info.lint.augment(v);
1288 Lint prevLint = chk.setLint(lint);
1289
1290 // Check that the variable's declared type is well-formed.
1291 boolean isImplicitLambdaParameter = env.tree.hasTag(LAMBDA) &&
1292 ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT &&
1293 (tree.sym.flags() & PARAMETER) != 0;
1294 chk.validate(tree.vartype, env, !isImplicitLambdaParameter && !tree.isImplicitlyTyped());
1295
1296 try {
1297 v.getConstValue(); // ensure compile-time constant initializer is evaluated
1298 chk.checkDeprecatedAnnotation(tree.pos(), v);
1299
1300 if (tree.init != null) {
1301 if ((v.flags_field & FINAL) == 0 ||
1302 !memberEnter.needsLazyConstValue(tree.init)) {
1303 // Not a compile-time constant
1304 // Attribute initializer in a new environment
1305 // with the declared variable as owner.
1306 // Check that initializer conforms to variable's declared type.
1307 Env<AttrContext> initEnv = memberEnter.initEnv(tree, env);
1308 initEnv.info.lint = lint;
1309 // In order to catch self-references, we set the variable's
1310 // declaration position to maximal possible value, effectively
1311 // marking the variable as undefined.
1312 initEnv.info.enclVar = v;
1313 attribExpr(tree.init, initEnv, v.type);
1314 if (tree.isImplicitlyTyped()) {
1315 //fixup local variable type
1316 v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name);
1317 }
1318 }
1319 if (tree.isImplicitlyTyped()) {
1320 setSyntheticVariableType(tree, v.type);
1321 }
1322 }
1323 result = tree.type = v.type;
1324 if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP && !v.isStatic()) {
1325 if (isNonArgsMethodInObject(v.name)) {
1326 log.error(tree, Errors.IllegalRecordComponentName(v));
1327 }
1328 }
1329 chk.checkRequiresIdentity(tree, env.info.lint);
1330 }
1331 finally {
1332 chk.setLint(prevLint);
1333 }
1334 }
1335
1336 private void doQueueScanTreeAndTypeAnnotateForVarInit(JCVariableDecl tree, Env<AttrContext> env) {
1337 if (tree.init != null &&
1338 (tree.mods.flags & Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED) == 0 &&
1417 }
1418 }
1419 }
1420
1421 public void visitSkip(JCSkip tree) {
1422 result = null;
1423 }
1424
1425 public void visitBlock(JCBlock tree) {
1426 if (env.info.scope.owner.kind == TYP || env.info.scope.owner.kind == ERR) {
1427 // Block is a static or instance initializer;
1428 // let the owner of the environment be a freshly
1429 // created BLOCK-method.
1430 Symbol fakeOwner =
1431 new MethodSymbol(tree.flags | BLOCK |
1432 env.info.scope.owner.flags() & STRICTFP, names.empty, initBlockType,
1433 env.info.scope.owner);
1434 final Env<AttrContext> localEnv =
1435 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner)));
1436
1437 if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
1438 // Attribute all type annotations in the block
1439 annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner);
1440 annotate.flush();
1441 attribStats(tree.stats, localEnv);
1442
1443 {
1444 // Store init and clinit type annotations with the ClassSymbol
1445 // to allow output in Gen.normalizeDefs.
1446 ClassSymbol cs = (ClassSymbol)env.info.scope.owner;
1447 List<Attribute.TypeCompound> tas = localEnv.info.scope.owner.getRawTypeAttributes();
1448 if ((tree.flags & STATIC) != 0) {
1449 cs.appendClassInitTypeAttributes(tas);
1450 } else {
1451 cs.appendInitTypeAttributes(tas);
1452 }
1453 }
1454 } else {
1455 // Create a new local environment with a local scope.
1456 Env<AttrContext> localEnv =
1457 env.dup(tree, env.info.dup(env.info.scope.dup()));
1930 // where
1931 /** Return the selected enumeration constant symbol, or null. */
1932 private Symbol enumConstant(JCTree tree, Type enumType) {
1933 if (tree.hasTag(IDENT)) {
1934 JCIdent ident = (JCIdent)tree;
1935 Name name = ident.name;
1936 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) {
1937 if (sym.kind == VAR) {
1938 Symbol s = ident.sym = sym;
1939 ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated
1940 ident.type = s.type;
1941 return ((s.flags_field & Flags.ENUM) == 0)
1942 ? null : s;
1943 }
1944 }
1945 }
1946 return null;
1947 }
1948
1949 public void visitSynchronized(JCSynchronized tree) {
1950 chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));
1951 if (tree.lock.type != null && tree.lock.type.isValueBased()) {
1952 log.warning(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
1953 }
1954 attribStat(tree.body, env);
1955 result = null;
1956 }
1957
1958 public void visitTry(JCTry tree) {
1959 // Create a new local environment with a local
1960 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
1961 try {
1962 boolean isTryWithResource = tree.resources.nonEmpty();
1963 // Create a nested environment for attributing the try block if needed
1964 Env<AttrContext> tryEnv = isTryWithResource ?
1965 env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) :
1966 localEnv;
1967 try {
1968 // Attribute resource declarations
1969 for (JCTree resource : tree.resources) {
1970 CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) {
1971 @Override
4376 }
4377
4378 public void visitSelect(JCFieldAccess tree) {
4379 // Determine the expected kind of the qualifier expression.
4380 KindSelector skind = KindSelector.NIL;
4381 if (tree.name == names._this || tree.name == names._super ||
4382 tree.name == names._class)
4383 {
4384 skind = KindSelector.TYP;
4385 } else {
4386 if (pkind().contains(KindSelector.PCK))
4387 skind = KindSelector.of(skind, KindSelector.PCK);
4388 if (pkind().contains(KindSelector.TYP))
4389 skind = KindSelector.of(skind, KindSelector.TYP, KindSelector.PCK);
4390 if (pkind().contains(KindSelector.VAL_MTH))
4391 skind = KindSelector.of(skind, KindSelector.VAL, KindSelector.TYP);
4392 }
4393
4394 // Attribute the qualifier expression, and determine its symbol (if any).
4395 Type site = attribTree(tree.selected, env, new ResultInfo(skind, Type.noType));
4396 if (!pkind().contains(KindSelector.TYP_PCK))
4397 site = capture(site); // Capture field access
4398
4399 // don't allow T.class T[].class, etc
4400 if (skind == KindSelector.TYP) {
4401 Type elt = site;
4402 while (elt.hasTag(ARRAY))
4403 elt = ((ArrayType)elt).elemtype;
4404 if (elt.hasTag(TYPEVAR)) {
4405 log.error(tree.pos(), Errors.TypeVarCantBeDeref);
4406 result = tree.type = types.createErrorType(tree.name, site.tsym, site);
4407 tree.sym = tree.type.tsym;
4408 return ;
4409 }
4410 }
4411
4412 // If qualifier symbol is a type or `super', assert `selectSuper'
4413 // for the selection. This is relevant for determining whether
4414 // protected symbols are accessible.
4415 Symbol sitesym = TreeInfo.symbol(tree.selected);
5487 .filter(s -> s.tsym.isSealed())
5488 .map(s -> (ClassSymbol) s.tsym)
5489 .collect(List.collector());
5490
5491 if (sealedSupers.isEmpty()) {
5492 if ((c.flags_field & Flags.NON_SEALED) != 0) {
5493 boolean hasErrorSuper = false;
5494
5495 hasErrorSuper |= types.directSupertypes(c.type)
5496 .stream()
5497 .anyMatch(s -> s.tsym.kind == Kind.ERR);
5498
5499 ClassType ct = (ClassType) c.type;
5500
5501 hasErrorSuper |= !ct.isCompound() && ct.interfaces_field != ct.all_interfaces_field;
5502
5503 if (!hasErrorSuper) {
5504 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
5505 }
5506 }
5507 } else {
5508 if (c.isDirectlyOrIndirectlyLocal() && !c.isEnum()) {
5509 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local));
5510 }
5511
5512 if (!c.type.isCompound()) {
5513 for (ClassSymbol supertypeSym : sealedSupers) {
5514 if (!supertypeSym.isPermittedSubclass(c.type.tsym)) {
5515 log.error(TreeInfo.diagnosticPositionFor(c.type.tsym, env.tree), Errors.CantInheritFromSealed(supertypeSym));
5516 }
5517 }
5518 if (!c.isNonSealed() && !c.isFinal() && !c.isSealed()) {
5519 log.error(TreeInfo.diagnosticPositionFor(c, env.tree),
5520 c.isInterface() ?
5521 Errors.NonSealedOrSealedExpected :
5522 Errors.NonSealedSealedOrFinalExpected);
5523 }
5524 }
5525 }
5526
5527 env.info.returnResult = null;
5528 // java.lang.Enum may not be subclassed by a non-enum
5529 if (st.tsym == syms.enumSym &&
5530 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0))
5531 log.error(env.tree.pos(), Errors.EnumNoSubclassing);
5532
5533 // Enums may not be extended by source-level classes
5534 if (st.tsym != null &&
5535 ((st.tsym.flags_field & Flags.ENUM) != 0) &&
5536 ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0)) {
5537 log.error(env.tree.pos(), Errors.EnumTypesNotExtensible);
5538 }
5539
5540 if (rs.isSerializable(c.type)) {
5541 env.info.isSerializable = true;
5542 }
5543
5544 attribClassBody(env, c);
5545
5546 chk.checkDeprecatedAnnotation(env.tree.pos(), c);
5547 chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c);
5548 chk.checkFunctionalInterface((JCClassDecl) env.tree, c);
5549 chk.checkLeaksNotAccessible(env, (JCClassDecl) env.tree);
5550
5551 if (c.isImplicit()) {
5552 chk.checkHasMain(env.tree.pos(), c);
5553 }
5554 } finally {
5555 env.info.returnResult = prevReturnRes;
5556 log.useSource(prev);
5557 chk.setLint(prevLint);
5558 }
5559
5560 }
5561 }
5562
5563 public void visitImport(JCImport tree) {
5666 sym.kind != VAR ||
5667 sym.getConstValue() == null)
5668 log.error(l.head.pos(), Errors.IclsCantHaveStaticDecl(c));
5669 }
5670 }
5671
5672 // Check for proper placement of super()/this() calls.
5673 chk.checkSuperInitCalls(tree);
5674
5675 // Check for cycles among non-initial constructors.
5676 chk.checkCyclicConstructors(tree);
5677
5678 // Check for cycles among annotation elements.
5679 chk.checkNonCyclicElements(tree);
5680
5681 // Check for proper use of serialVersionUID and other
5682 // serialization-related fields and methods
5683 if (env.info.lint.isEnabled(LintCategory.SERIAL)
5684 && rs.isSerializable(c.type)
5685 && !c.isAnonymous()) {
5686 chk.checkSerialStructure(tree, c);
5687 }
5688 // Correctly organize the positions of the type annotations
5689 typeAnnotations.organizeTypeAnnotationsBodies(tree);
5690
5691 // Check type annotations applicability rules
5692 validateTypeAnnotations(tree, false);
5693 }
5694 // where
5695 /** get a diagnostic position for an attribute of Type t, or null if attribute missing */
5696 private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) {
5697 for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) {
5698 if (types.isSameType(al.head.annotationType.type, t))
5699 return al.head.pos();
5700 }
5701
5702 return null;
5703 }
5704
5705 private Type capture(Type type) {
5706 return types.capture(type);
|
107 final Analyzer analyzer;
108 final DeferredAttr deferredAttr;
109 final Check chk;
110 final Flow flow;
111 final MemberEnter memberEnter;
112 final TypeEnter typeEnter;
113 final TreeMaker make;
114 final ConstFold cfolder;
115 final Enter enter;
116 final Target target;
117 final Types types;
118 final Preview preview;
119 final JCDiagnostic.Factory diags;
120 final TypeAnnotations typeAnnotations;
121 final TypeEnvs typeEnvs;
122 final Dependencies dependencies;
123 final Annotate annotate;
124 final ArgumentAttr argumentAttr;
125 final MatchBindingsComputer matchBindingsComputer;
126 final AttrRecover attrRecover;
127 final LocalProxyVarsGen localProxyVarsGen;
128
129 public static Attr instance(Context context) {
130 Attr instance = context.get(attrKey);
131 if (instance == null)
132 instance = new Attr(context);
133 return instance;
134 }
135
136 @SuppressWarnings("this-escape")
137 protected Attr(Context context) {
138 context.put(attrKey, this);
139
140 names = Names.instance(context);
141 log = Log.instance(context);
142 lintMapper = LintMapper.instance(context);
143 syms = Symtab.instance(context);
144 rs = Resolve.instance(context);
145 operators = Operators.instance(context);
146 chk = Check.instance(context);
147 flow = Flow.instance(context);
148 memberEnter = MemberEnter.instance(context);
149 typeEnter = TypeEnter.instance(context);
150 make = TreeMaker.instance(context);
151 enter = Enter.instance(context);
152 infer = Infer.instance(context);
153 analyzer = Analyzer.instance(context);
154 deferredAttr = DeferredAttr.instance(context);
155 cfolder = ConstFold.instance(context);
156 target = Target.instance(context);
157 types = Types.instance(context);
158 preview = Preview.instance(context);
159 diags = JCDiagnostic.Factory.instance(context);
160 annotate = Annotate.instance(context);
161 typeAnnotations = TypeAnnotations.instance(context);
162 typeEnvs = TypeEnvs.instance(context);
163 dependencies = Dependencies.instance(context);
164 argumentAttr = ArgumentAttr.instance(context);
165 matchBindingsComputer = MatchBindingsComputer.instance(context);
166 attrRecover = AttrRecover.instance(context);
167 localProxyVarsGen = LocalProxyVarsGen.instance(context);
168
169 Options options = Options.instance(context);
170
171 Source source = Source.instance(context);
172 allowReifiableTypesInInstanceof = Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source);
173 allowRecords = Feature.RECORDS.allowedInSource(source);
174 allowPatternSwitch = (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH)) &&
175 Feature.PATTERN_SWITCH.allowedInSource(source);
176 allowUnconditionalPatternsInstanceOf =
177 Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.allowedInSource(source);
178 sourceName = source.name;
179 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
180
181 statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
182 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
183 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
184 methodAttrInfo = new MethodAttrInfo();
185 unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
186 unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType);
187 recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
188 initBlockType = new MethodType(List.nil(), syms.voidType, List.nil(), syms.methodClass);
189 allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
190 Feature.VALUE_CLASSES.allowedInSource(source);
191 }
192
193 /** Switch: reifiable types in instanceof enabled?
194 */
195 boolean allowReifiableTypesInInstanceof;
196
197 /** Are records allowed
198 */
199 private final boolean allowRecords;
200
201 /** Are patterns in switch allowed
202 */
203 private final boolean allowPatternSwitch;
204
205 /** Are unconditional patterns in instanceof allowed
206 */
207 private final boolean allowUnconditionalPatternsInstanceOf;
208
209 /** Are value classes allowed
210 */
211 private final boolean allowValueClasses;
212
213 /**
214 * Switch: warn about use of variable before declaration?
215 * RFE: 6425594
216 */
217 boolean useBeforeDeclarationWarning;
218
219 /**
220 * Switch: name of source level; used for error reporting.
221 */
222 String sourceName;
223
224 /** Check kind and type of given tree against protokind and prototype.
225 * If check succeeds, store type in tree and return it.
226 * If check fails, store errType in tree and return it.
227 * No checks are performed if the prototype is a method type.
228 * It is not necessary in this case since we know that kind and type
229 * are correct.
230 *
231 * @param tree The tree whose kind and type is checked
232 * @param found The computed type of the tree
286 owner.kind == VAR || // i.e. we are in a variable initializer
287 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block
288 &&
289 v.owner == owner.owner
290 &&
291 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
292 boolean insideCompactConstructor = env.enclMethod != null && TreeInfo.isCompactConstructor(env.enclMethod);
293 return isAssignable & !insideCompactConstructor;
294 }
295
296 /** Check that variable can be assigned to.
297 * @param pos The current source code position.
298 * @param v The assigned variable
299 * @param base If the variable is referred to in a Select, the part
300 * to the left of the `.', null otherwise.
301 * @param env The current environment.
302 */
303 void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
304 if (v.name == names._this) {
305 log.error(pos, Errors.CantAssignValToThis);
306 } else if ((v.flags() & FINAL) != 0 &&
307 ((v.flags() & HASINIT) != 0
308 ||
309 !((base == null ||
310 TreeInfo.isThisQualifier(base)) &&
311 isAssignableAsBlankFinal(v, env)))) {
312 if (v.isResourceVariable()) { //TWR resource
313 log.error(pos, Errors.TryResourceMayNotBeAssigned(v));
314 } else {
315 log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v));
316 }
317 }
318 }
319
320 /** Does tree represent a static reference to an identifier?
321 * It is assumed that tree is either a SELECT or an IDENT.
322 * We have to weed out selects from non-type names here.
323 * @param tree The candidate tree.
324 */
325 boolean isStaticReference(JCTree tree) {
326 if (tree.hasTag(SELECT)) {
327 Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected);
328 if (lsym == null || lsym.kind != TYP) {
329 return false;
330 }
331 }
332 return true;
333 }
334
335 /** Is this symbol a type?
336 */
1091 * - have an accessibility stricter than that of the record type
1092 * - explicitly invoke any other constructor
1093 */
1094 if ((tree.sym.flags_field & GENERATEDCONSTR) == 0) {
1095 if (Check.protection(m.flags()) > Check.protection(env.enclClass.sym.flags())) {
1096 log.error(tree,
1097 (env.enclClass.sym.flags() & AccessFlags) == 0 ?
1098 Errors.InvalidCanonicalConstructorInRecord(
1099 Fragments.Canonical,
1100 env.enclClass.sym.name,
1101 Fragments.CanonicalMustNotHaveStrongerAccess("package")
1102 ) :
1103 Errors.InvalidCanonicalConstructorInRecord(
1104 Fragments.Canonical,
1105 env.enclClass.sym.name,
1106 Fragments.CanonicalMustNotHaveStrongerAccess(asFlagSet(env.enclClass.sym.flags() & AccessFlags))
1107 )
1108 );
1109 }
1110
1111 if (!allowValueClasses && TreeInfo.hasAnyConstructorCall(tree)) {
1112 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1113 Fragments.Canonical, env.enclClass.sym.name,
1114 Fragments.CanonicalMustNotContainExplicitConstructorInvocation));
1115 }
1116 }
1117
1118 // also we want to check that no type variables have been defined
1119 if (!tree.typarams.isEmpty()) {
1120 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1121 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalMustNotDeclareTypeVariables));
1122 }
1123
1124 /* and now we need to check that the constructor's arguments are exactly the same as those of the
1125 * record components
1126 */
1127 List<? extends RecordComponent> recordComponents = env.enclClass.sym.getRecordComponents();
1128 List<Type> recordFieldTypes = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.type);
1129 for (JCVariableDecl param: tree.params) {
1130 boolean paramIsVarArgs = (param.sym.flags_field & VARARGS) != 0;
1131 if (!types.isSameType(param.type, recordFieldTypes.head) ||
1169 if (tree.defaultValue != null) {
1170 if ((owner.flags() & ANNOTATION) == 0)
1171 log.error(tree.pos(),
1172 Errors.DefaultAllowedInIntfAnnotationMember);
1173 }
1174 if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0)
1175 log.error(tree.pos(), Errors.MissingMethBodyOrDeclAbstract(tree.sym, owner));
1176 } else {
1177 if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) {
1178 if ((owner.flags() & INTERFACE) != 0) {
1179 log.error(tree.body.pos(), Errors.IntfMethCantHaveBody);
1180 } else {
1181 log.error(tree.pos(), Errors.AbstractMethCantHaveBody);
1182 }
1183 } else if ((tree.mods.flags & NATIVE) != 0) {
1184 log.error(tree.pos(), Errors.NativeMethCantHaveBody);
1185 }
1186 // Add an implicit super() call unless an explicit call to
1187 // super(...) or this(...) is given
1188 // or we are compiling class java.lang.Object.
1189 boolean addedSuperInIdentityClass = false;
1190 if (isConstructor && owner.type != syms.objectType) {
1191 if (!TreeInfo.hasAnyConstructorCall(tree)) {
1192 JCStatement supCall = make.at(tree.body.pos).Exec(make.Apply(List.nil(),
1193 make.Ident(names._super), make.Idents(List.nil())));
1194 if (allowValueClasses && (owner.isValueClass() || owner.hasStrict() || ((owner.flags_field & RECORD) != 0))) {
1195 tree.body.stats = tree.body.stats.append(supCall);
1196 } else {
1197 tree.body.stats = tree.body.stats.prepend(supCall);
1198 addedSuperInIdentityClass = true;
1199 }
1200 } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&
1201 (tree.mods.flags & GENERATEDCONSTR) == 0 &&
1202 TreeInfo.hasConstructorCall(tree, names._super)) {
1203 // enum constructors are not allowed to call super
1204 // directly, so make sure there aren't any super calls
1205 // in enum constructors, except in the compiler
1206 // generated one.
1207 log.error(tree.body.stats.head.pos(),
1208 Errors.CallToSuperNotAllowedInEnumCtor(env.enclClass.sym));
1209 }
1210 if (env.enclClass.sym.isRecord() && (tree.sym.flags_field & RECORD) != 0) { // we are seeing the canonical constructor
1211 List<Name> recordComponentNames = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.name);
1212 List<Name> initParamNames = tree.sym.params.map(p -> p.name);
1213 if (!initParamNames.equals(recordComponentNames)) {
1214 log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
1215 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalWithNameMismatch));
1216 }
1217 if (tree.sym.type.asMethodType().thrown != null && !tree.sym.type.asMethodType().thrown.isEmpty()) {
1218 log.error(tree,
1219 Errors.InvalidCanonicalConstructorInRecord(
1220 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical,
1221 env.enclClass.sym.name,
1222 Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(
1223 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical)));
1224 }
1225 }
1226 }
1227
1228 // Attribute all type annotations in the body
1229 annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m);
1230 annotate.flush();
1231
1232 // Start of constructor prologue (if not in java.lang.Object constructor)
1233 localEnv.info.ctorPrologue = isConstructor && owner.type != syms.objectType;
1234
1235 // Attribute method body.
1236 attribStat(tree.body, localEnv);
1237 if (localEnv.info.ctorPrologue) {
1238 boolean thisInvocation = false;
1239 ListBuffer<JCTree> prologueCode = new ListBuffer<>();
1240 for (JCTree stat : tree.body.stats) {
1241 prologueCode.add(stat);
1242 /* gather all the stats in the body until a `super` or `this` constructor invocation is found,
1243 * including the constructor invocation, that way we don't need to worry in the visitor below if
1244 * if we are dealing or not with prologue code
1245 */
1246 if (stat instanceof JCExpressionStatement expStmt &&
1247 expStmt.expr instanceof JCMethodInvocation mi &&
1248 TreeInfo.isConstructorCall(mi)) {
1249 thisInvocation = TreeInfo.name(mi.meth) == names._this;
1250 if (!addedSuperInIdentityClass || !allowValueClasses) {
1251 break;
1252 }
1253 }
1254 }
1255 if (!prologueCode.isEmpty()) {
1256 CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(localEnv,
1257 addedSuperInIdentityClass && allowValueClasses ?
1258 PrologueVisitorMode.WARNINGS_ONLY :
1259 thisInvocation ?
1260 PrologueVisitorMode.THIS_CONSTRUCTOR :
1261 PrologueVisitorMode.SUPER_CONSTRUCTOR,
1262 false);
1263 ctorPrologueVisitor.scan(prologueCode.toList());
1264 }
1265 }
1266 }
1267
1268 localEnv.info.scope.leave();
1269 result = tree.type = m.type;
1270 } finally {
1271 chk.setLint(prevLint);
1272 chk.setMethod(prevMethod);
1273 env.info.ctorPrologue = ctorProloguePrev;
1274 }
1275 }
1276
1277 enum PrologueVisitorMode {
1278 WARNINGS_ONLY,
1279 SUPER_CONSTRUCTOR,
1280 THIS_CONSTRUCTOR
1281 }
1282
1283 class CtorPrologueVisitor extends TreeScanner {
1284 Env<AttrContext> localEnv;
1285 PrologueVisitorMode mode;
1286 boolean isInitializer;
1287
1288 CtorPrologueVisitor(Env<AttrContext> localEnv, PrologueVisitorMode mode, boolean isInitializer) {
1289 this.localEnv = localEnv;
1290 currentClassSym = localEnv.enclClass.sym;
1291 this.mode = mode;
1292 this.isInitializer = isInitializer;
1293 }
1294
1295 boolean insideLambdaOrClassDef = false;
1296
1297 @Override
1298 public void visitLambda(JCLambda lambda) {
1299 boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef;
1300 try {
1301 insideLambdaOrClassDef = true;
1302 super.visitLambda(lambda);
1303 } finally {
1304 insideLambdaOrClassDef = previousInsideLambdaOrClassDef;
1305 }
1306 }
1307
1308 ClassSymbol currentClassSym;
1309
1310 @Override
1311 public void visitClassDef(JCClassDecl classDecl) {
1312 boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef;
1313 ClassSymbol previousClassSym = currentClassSym;
1314 try {
1315 insideLambdaOrClassDef = true;
1316 currentClassSym = classDecl.sym;
1317 super.visitClassDef(classDecl);
1318 } finally {
1319 insideLambdaOrClassDef = previousInsideLambdaOrClassDef;
1320 currentClassSym = previousClassSym;
1321 }
1322 }
1323
1324 private void reportPrologueError(JCTree tree, Symbol sym) {
1325 reportPrologueError(tree, sym, false);
1326 }
1327
1328 private void reportPrologueError(JCTree tree, Symbol sym, boolean hasInit) {
1329 preview.checkSourceLevel(tree, Feature.FLEXIBLE_CONSTRUCTORS);
1330 if (mode != PrologueVisitorMode.WARNINGS_ONLY) {
1331 if (hasInit) {
1332 log.error(tree, Errors.CantAssignInitializedBeforeCtorCalled(sym));
1333 } else {
1334 log.error(tree, Errors.CantRefBeforeCtorCalled(sym));
1335 }
1336 } else if (allowValueClasses) {
1337 // issue lint warning
1338 log.warning(tree, LintWarnings.WouldNotBeAllowedInPrologue(sym));
1339 }
1340 }
1341
1342 @Override
1343 public void visitApply(JCMethodInvocation tree) {
1344 super.visitApply(tree);
1345 Name name = TreeInfo.name(tree.meth);
1346 boolean isConstructorCall = name == names._this || name == names._super;
1347 Symbol msym = TreeInfo.symbolFor(tree.meth);
1348 // is this an instance method call or an illegal constructor invocation like: `this.super()`?
1349 if (msym != null && // for erroneous invocations msym can be null, ignore those
1350 (!isConstructorCall ||
1351 isConstructorCall && tree.meth.hasTag(SELECT))) {
1352 if (isEarlyReference(localEnv, tree.meth, msym))
1353 reportPrologueError(tree.meth, msym);
1354 }
1355 }
1356
1357 @Override
1358 public void visitIdent(JCIdent tree) {
1359 analyzeSymbol(tree);
1360 }
1361
1362 boolean isIndexed = false;
1363
1364 @Override
1365 public void visitIndexed(JCArrayAccess tree) {
1366 boolean previousIsIndexed = isIndexed;
1367 try {
1368 isIndexed = true;
1369 scan(tree.indexed);
1370 } finally {
1371 isIndexed = previousIsIndexed;
1372 }
1373 scan(tree.index);
1374 if (mode == PrologueVisitorMode.SUPER_CONSTRUCTOR && isInstanceField(tree.indexed)) {
1375 localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, TreeInfo.symbolFor(tree.indexed));
1376 }
1377 }
1378
1379 @Override
1380 public void visitSelect(JCFieldAccess tree) {
1381 SelectScanner ss = new SelectScanner();
1382 ss.scan(tree);
1383 if (ss.scanLater == null) {
1384 Symbol sym = TreeInfo.symbolFor(tree);
1385 // if this is a field access
1386 if (sym.kind == VAR && sym.owner.kind == TYP) {
1387 // Type.super.field or super.field expressions are forbidden in early construction contexts
1388 for (JCTree subtree : ss.selectorTrees) {
1389 if (TreeInfo.isSuperOrSelectorDotSuper(subtree)) {
1390 reportPrologueError(tree, sym);
1391 return;
1392 }
1393 }
1394 }
1395 analyzeSymbol(tree);
1396 } else {
1397 boolean prevLhs = isInLHS;
1398 try {
1399 isInLHS = false;
1400 scan(ss.scanLater);
1401 } finally {
1402 isInLHS = prevLhs;
1403 }
1404 }
1405 if (mode == PrologueVisitorMode.SUPER_CONSTRUCTOR) {
1406 for (JCTree subtree : ss.selectorTrees) {
1407 if (isInstanceField(subtree)) {
1408 // we need to add a proxy for this one
1409 localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, TreeInfo.symbolFor(subtree));
1410 }
1411 }
1412 }
1413 }
1414
1415 boolean isInstanceField(JCTree tree) {
1416 Symbol sym = TreeInfo.symbolFor(tree);
1417 return (sym != null &&
1418 !sym.isStatic() &&
1419 sym.kind == VAR &&
1420 sym.owner.kind == TYP &&
1421 sym.name != names._this &&
1422 sym.name != names._super &&
1423 isEarlyReference(localEnv, tree, sym));
1424 }
1425
1426 @Override
1427 public void visitNewClass(JCNewClass tree) {
1428 super.visitNewClass(tree);
1429 checkNewClassAndMethRefs(tree, tree.type);
1430 }
1431
1432 @Override
1433 public void visitReference(JCMemberReference tree) {
1434 super.visitReference(tree);
1435 if (tree.getMode() == JCMemberReference.ReferenceMode.NEW) {
1436 checkNewClassAndMethRefs(tree, tree.expr.type);
1437 }
1438 }
1439
1440 void checkNewClassAndMethRefs(JCTree tree, Type t) {
1441 if (t.tsym.isEnclosedBy(localEnv.enclClass.sym) &&
1442 !t.tsym.isStatic() &&
1443 !t.tsym.isDirectlyOrIndirectlyLocal()) {
1444 reportPrologueError(tree, t.getEnclosingType().tsym);
1445 }
1446 }
1447
1448 /* if a symbol is in the LHS of an assignment expression we won't consider it as a candidate
1449 * for a proxy local variable later on
1450 */
1451 boolean isInLHS = false;
1452
1453 @Override
1454 public void visitAssign(JCAssign tree) {
1455 boolean previousIsInLHS = isInLHS;
1456 try {
1457 isInLHS = true;
1458 scan(tree.lhs);
1459 } finally {
1460 isInLHS = previousIsInLHS;
1461 }
1462 scan(tree.rhs);
1463 }
1464
1465 @Override
1466 public void visitMethodDef(JCMethodDecl tree) {
1467 // ignore any declarative part, mainly to avoid scanning receiver parameters
1468 scan(tree.body);
1469 }
1470
1471 void analyzeSymbol(JCTree tree) {
1472 Symbol sym = TreeInfo.symbolFor(tree);
1473 // make sure that there is a symbol and it is not static
1474 if (sym == null || sym.isStatic()) {
1475 return;
1476 }
1477 if (isInLHS && !insideLambdaOrClassDef) {
1478 // Check instance field assignments that appear in constructor prologues
1479 if (isEarlyReference(localEnv, tree, sym)) {
1480 // Field may not be inherited from a superclass
1481 if (sym.owner != localEnv.enclClass.sym) {
1482 reportPrologueError(tree, sym);
1483 return;
1484 }
1485 // Field may not have an initializer
1486 if ((sym.flags() & HASINIT) != 0) {
1487 if (!localEnv.enclClass.sym.isValueClass() || !sym.type.hasTag(ARRAY) || !isIndexed) {
1488 reportPrologueError(tree, sym, true);
1489 }
1490 return;
1491 }
1492 // cant reference an instance field before a this constructor
1493 if (allowValueClasses && mode == PrologueVisitorMode.THIS_CONSTRUCTOR) {
1494 reportPrologueError(tree, sym);
1495 return;
1496 }
1497 }
1498 return;
1499 }
1500 tree = TreeInfo.skipParens(tree);
1501 if (sym.kind == VAR && sym.owner.kind == TYP) {
1502 if (sym.name == names._this || sym.name == names._super) {
1503 // are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`?
1504 if (TreeInfo.isExplicitThisReference(
1505 types,
1506 (ClassType)localEnv.enclClass.sym.type,
1507 tree)) {
1508 reportPrologueError(tree, sym);
1509 }
1510 } else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only
1511 if (sym.owner != localEnv.enclClass.sym) {
1512 if (localEnv.enclClass.sym.isSubClass(sym.owner, types) &&
1513 sym.isInheritedIn(localEnv.enclClass.sym, types)) {
1514 /* if we are dealing with a field that doesn't belong to the current class, but the
1515 * field is inherited, this is an error. Unless, the super class is also an outer
1516 * class and the field's qualifier refers to the outer class
1517 */
1518 if (tree.hasTag(IDENT) ||
1519 TreeInfo.isExplicitThisReference(
1520 types,
1521 (ClassType)localEnv.enclClass.sym.type,
1522 ((JCFieldAccess)tree).selected)) {
1523 reportPrologueError(tree, sym);
1524 }
1525 }
1526 } else if (isEarlyReference(localEnv, tree, sym)) {
1527 /* now this is a `proper` instance field of the current class
1528 * references to fields of identity classes which happen to have initializers are
1529 * not allowed in the prologue.
1530 * But it is OK for a field with initializer to refer to another field with initializer,
1531 * so no warning or error if we are analyzing a field initializer.
1532 */
1533 if (insideLambdaOrClassDef ||
1534 (!localEnv.enclClass.sym.isValueClass() &&
1535 (sym.flags_field & HASINIT) != 0 &&
1536 !isInitializer))
1537 reportPrologueError(tree, sym);
1538 // we will need to generate a proxy for this field later on
1539 if (!isInLHS) {
1540 if (!allowValueClasses) {
1541 reportPrologueError(tree, sym);
1542 } else {
1543 if (mode == PrologueVisitorMode.THIS_CONSTRUCTOR) {
1544 reportPrologueError(tree, sym);
1545 } else if (mode == PrologueVisitorMode.SUPER_CONSTRUCTOR) {
1546 localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym);
1547 }
1548 /* we do nothing in warnings only mode, as in that mode we are simulating what
1549 * the compiler would do in case the constructor code would be in the prologue
1550 * phase
1551 */
1552 }
1553 }
1554 }
1555 }
1556 }
1557 }
1558
1559 /**
1560 * Determine if the symbol appearance constitutes an early reference to the current class.
1561 *
1562 * <p>
1563 * This means the symbol is an instance field, or method, of the current class and it appears
1564 * in an early initialization context of it (i.e., one of its constructor prologues).
1565 *
1566 * @param env The current environment
1567 * @param tree the AST referencing the variable
1568 * @param sym The symbol
1569 */
1570 private boolean isEarlyReference(Env<AttrContext> env, JCTree tree, Symbol sym) {
1571 if ((sym.flags() & STATIC) == 0 &&
1572 (sym.kind == VAR || sym.kind == MTH) &&
1573 sym.isMemberOf(env.enclClass.sym, types)) {
1574 // Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance
1575 if (tree instanceof JCFieldAccess fa) {
1576 return TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, fa.selected);
1577 } else if (currentClassSym != env.enclClass.sym) {
1578 /* so we are inside a class, CI, in the prologue of an outer class, CO, and the symbol being
1579 * analyzed has no qualifier. So if the symbol is a member of CI the reference is allowed,
1580 * otherwise it is not.
1581 * It could be that the reference to CI's member happens inside CI's own prologue, but that
1582 * will be checked separately, when CI's prologue is analyzed.
1583 */
1584 return !sym.isMemberOf(currentClassSym, types);
1585 }
1586 return true;
1587 }
1588 return false;
1589 }
1590
1591 /* scanner for a select expression, anything that is not a select or identifier
1592 * will be stored for further analysis
1593 */
1594 class SelectScanner extends DeferredAttr.FilterScanner {
1595 JCTree scanLater;
1596 java.util.List<JCTree> selectorTrees = new ArrayList<>();
1597
1598 SelectScanner() {
1599 super(Set.of(IDENT, SELECT, PARENS));
1600 }
1601
1602 @Override
1603 public void visitSelect(JCFieldAccess tree) {
1604 super.visitSelect(tree);
1605 selectorTrees.add(tree.selected);
1606 }
1607
1608 @Override
1609 void skip(JCTree tree) {
1610 scanLater = tree;
1611 }
1612 }
1613 }
1614
1615 public void visitVarDef(JCVariableDecl tree) {
1616 // Local variables have not been entered yet, so we need to do it now:
1617 if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
1618 if (tree.sym != null) {
1619 // parameters have already been entered
1620 env.info.scope.enter(tree.sym);
1621 } else {
1622 if (tree.isImplicitlyTyped() && (tree.getModifiers().flags & PARAMETER) == 0) {
1623 if (tree.init == null) {
1624 //cannot use 'var' without initializer
1625 log.error(tree, Errors.CantInferLocalVarType(tree.name, Fragments.LocalMissingInit));
1626 tree.vartype = make.at(tree.pos()).Erroneous();
1627 } else {
1628 Fragment msg = canInferLocalVarType(tree);
1629 if (msg != null) {
1630 //cannot use 'var' with initializer which require an explicit target
1631 //(e.g. lambda, method reference, array initializer).
1632 log.error(tree, Errors.CantInferLocalVarType(tree.name, msg));
1633 tree.vartype = make.at(tree.pos()).Erroneous();
1634 }
1643 }
1644 } else {
1645 doQueueScanTreeAndTypeAnnotateForVarInit(tree, env);
1646 }
1647
1648 VarSymbol v = tree.sym;
1649 Lint lint = env.info.lint.augment(v);
1650 Lint prevLint = chk.setLint(lint);
1651
1652 // Check that the variable's declared type is well-formed.
1653 boolean isImplicitLambdaParameter = env.tree.hasTag(LAMBDA) &&
1654 ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT &&
1655 (tree.sym.flags() & PARAMETER) != 0;
1656 chk.validate(tree.vartype, env, !isImplicitLambdaParameter && !tree.isImplicitlyTyped());
1657
1658 try {
1659 v.getConstValue(); // ensure compile-time constant initializer is evaluated
1660 chk.checkDeprecatedAnnotation(tree.pos(), v);
1661
1662 if (tree.init != null) {
1663 Env<AttrContext> initEnv = memberEnter.initEnv(tree, env);
1664 if ((v.flags_field & FINAL) == 0 ||
1665 !memberEnter.needsLazyConstValue(tree.init)) {
1666 // Not a compile-time constant
1667 // Attribute initializer in a new environment
1668 // with the declared variable as owner.
1669 // Check that initializer conforms to variable's declared type.
1670 initEnv.info.lint = lint;
1671 // In order to catch self-references, we set the variable's
1672 // declaration position to maximal possible value, effectively
1673 // marking the variable as undefined.
1674 initEnv.info.enclVar = v;
1675 boolean previousCtorPrologue = initEnv.info.ctorPrologue;
1676 try {
1677 if (v.owner.kind == TYP && !v.isStatic() && v.isStrict()) {
1678 // strict instance initializer in a value class
1679 initEnv.info.ctorPrologue = true;
1680 }
1681 attribExpr(tree.init, initEnv, v.type);
1682 if (tree.isImplicitlyTyped()) {
1683 //fixup local variable type
1684 v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name);
1685 }
1686 } finally {
1687 initEnv.info.ctorPrologue = previousCtorPrologue;
1688 }
1689 }
1690 if (allowValueClasses && v.owner.kind == TYP && !v.isStatic()) {
1691 // strict field initializers are inlined in constructor's prologues
1692 CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(initEnv,
1693 !v.isStrict() ? PrologueVisitorMode.WARNINGS_ONLY : PrologueVisitorMode.SUPER_CONSTRUCTOR,
1694 true);
1695 ctorPrologueVisitor.scan(tree.init);
1696 }
1697 if (tree.isImplicitlyTyped()) {
1698 setSyntheticVariableType(tree, v.type);
1699 }
1700 }
1701 result = tree.type = v.type;
1702 if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP && !v.isStatic()) {
1703 if (isNonArgsMethodInObject(v.name)) {
1704 log.error(tree, Errors.IllegalRecordComponentName(v));
1705 }
1706 }
1707 chk.checkRequiresIdentity(tree, env.info.lint);
1708 }
1709 finally {
1710 chk.setLint(prevLint);
1711 }
1712 }
1713
1714 private void doQueueScanTreeAndTypeAnnotateForVarInit(JCVariableDecl tree, Env<AttrContext> env) {
1715 if (tree.init != null &&
1716 (tree.mods.flags & Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED) == 0 &&
1795 }
1796 }
1797 }
1798
1799 public void visitSkip(JCSkip tree) {
1800 result = null;
1801 }
1802
1803 public void visitBlock(JCBlock tree) {
1804 if (env.info.scope.owner.kind == TYP || env.info.scope.owner.kind == ERR) {
1805 // Block is a static or instance initializer;
1806 // let the owner of the environment be a freshly
1807 // created BLOCK-method.
1808 Symbol fakeOwner =
1809 new MethodSymbol(tree.flags | BLOCK |
1810 env.info.scope.owner.flags() & STRICTFP, names.empty, initBlockType,
1811 env.info.scope.owner);
1812 final Env<AttrContext> localEnv =
1813 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner)));
1814
1815 if ((tree.flags & STATIC) != 0) {
1816 localEnv.info.staticLevel++;
1817 } else {
1818 localEnv.info.instanceInitializerBlock = true;
1819 }
1820 // Attribute all type annotations in the block
1821 annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner);
1822 annotate.flush();
1823 attribStats(tree.stats, localEnv);
1824
1825 {
1826 // Store init and clinit type annotations with the ClassSymbol
1827 // to allow output in Gen.normalizeDefs.
1828 ClassSymbol cs = (ClassSymbol)env.info.scope.owner;
1829 List<Attribute.TypeCompound> tas = localEnv.info.scope.owner.getRawTypeAttributes();
1830 if ((tree.flags & STATIC) != 0) {
1831 cs.appendClassInitTypeAttributes(tas);
1832 } else {
1833 cs.appendInitTypeAttributes(tas);
1834 }
1835 }
1836 } else {
1837 // Create a new local environment with a local scope.
1838 Env<AttrContext> localEnv =
1839 env.dup(tree, env.info.dup(env.info.scope.dup()));
2312 // where
2313 /** Return the selected enumeration constant symbol, or null. */
2314 private Symbol enumConstant(JCTree tree, Type enumType) {
2315 if (tree.hasTag(IDENT)) {
2316 JCIdent ident = (JCIdent)tree;
2317 Name name = ident.name;
2318 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) {
2319 if (sym.kind == VAR) {
2320 Symbol s = ident.sym = sym;
2321 ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated
2322 ident.type = s.type;
2323 return ((s.flags_field & Flags.ENUM) == 0)
2324 ? null : s;
2325 }
2326 }
2327 }
2328 return null;
2329 }
2330
2331 public void visitSynchronized(JCSynchronized tree) {
2332 boolean identityType = chk.checkIdentityType(tree.pos(), attribExpr(tree.lock, env));
2333 if (identityType && tree.lock.type != null && tree.lock.type.isValueBased()) {
2334 log.warning(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
2335 }
2336 attribStat(tree.body, env);
2337 result = null;
2338 }
2339
2340 public void visitTry(JCTry tree) {
2341 // Create a new local environment with a local
2342 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
2343 try {
2344 boolean isTryWithResource = tree.resources.nonEmpty();
2345 // Create a nested environment for attributing the try block if needed
2346 Env<AttrContext> tryEnv = isTryWithResource ?
2347 env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) :
2348 localEnv;
2349 try {
2350 // Attribute resource declarations
2351 for (JCTree resource : tree.resources) {
2352 CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) {
2353 @Override
4758 }
4759
4760 public void visitSelect(JCFieldAccess tree) {
4761 // Determine the expected kind of the qualifier expression.
4762 KindSelector skind = KindSelector.NIL;
4763 if (tree.name == names._this || tree.name == names._super ||
4764 tree.name == names._class)
4765 {
4766 skind = KindSelector.TYP;
4767 } else {
4768 if (pkind().contains(KindSelector.PCK))
4769 skind = KindSelector.of(skind, KindSelector.PCK);
4770 if (pkind().contains(KindSelector.TYP))
4771 skind = KindSelector.of(skind, KindSelector.TYP, KindSelector.PCK);
4772 if (pkind().contains(KindSelector.VAL_MTH))
4773 skind = KindSelector.of(skind, KindSelector.VAL, KindSelector.TYP);
4774 }
4775
4776 // Attribute the qualifier expression, and determine its symbol (if any).
4777 Type site = attribTree(tree.selected, env, new ResultInfo(skind, Type.noType));
4778 Assert.check(site == tree.selected.type);
4779 if (!pkind().contains(KindSelector.TYP_PCK))
4780 site = capture(site); // Capture field access
4781
4782 // don't allow T.class T[].class, etc
4783 if (skind == KindSelector.TYP) {
4784 Type elt = site;
4785 while (elt.hasTag(ARRAY))
4786 elt = ((ArrayType)elt).elemtype;
4787 if (elt.hasTag(TYPEVAR)) {
4788 log.error(tree.pos(), Errors.TypeVarCantBeDeref);
4789 result = tree.type = types.createErrorType(tree.name, site.tsym, site);
4790 tree.sym = tree.type.tsym;
4791 return ;
4792 }
4793 }
4794
4795 // If qualifier symbol is a type or `super', assert `selectSuper'
4796 // for the selection. This is relevant for determining whether
4797 // protected symbols are accessible.
4798 Symbol sitesym = TreeInfo.symbol(tree.selected);
5870 .filter(s -> s.tsym.isSealed())
5871 .map(s -> (ClassSymbol) s.tsym)
5872 .collect(List.collector());
5873
5874 if (sealedSupers.isEmpty()) {
5875 if ((c.flags_field & Flags.NON_SEALED) != 0) {
5876 boolean hasErrorSuper = false;
5877
5878 hasErrorSuper |= types.directSupertypes(c.type)
5879 .stream()
5880 .anyMatch(s -> s.tsym.kind == Kind.ERR);
5881
5882 ClassType ct = (ClassType) c.type;
5883
5884 hasErrorSuper |= !ct.isCompound() && ct.interfaces_field != ct.all_interfaces_field;
5885
5886 if (!hasErrorSuper) {
5887 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
5888 }
5889 }
5890 } else if ((c.flags_field & Flags.COMPOUND) == 0) {
5891 if (c.isDirectlyOrIndirectlyLocal() && !c.isEnum()) {
5892 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local));
5893 }
5894
5895 if (!c.type.isCompound()) {
5896 for (ClassSymbol supertypeSym : sealedSupers) {
5897 if (!supertypeSym.isPermittedSubclass(c.type.tsym)) {
5898 log.error(TreeInfo.diagnosticPositionFor(c.type.tsym, env.tree), Errors.CantInheritFromSealed(supertypeSym));
5899 }
5900 }
5901 if (!c.isNonSealed() && !c.isFinal() && !c.isSealed()) {
5902 log.error(TreeInfo.diagnosticPositionFor(c, env.tree),
5903 c.isInterface() ?
5904 Errors.NonSealedOrSealedExpected :
5905 Errors.NonSealedSealedOrFinalExpected);
5906 }
5907 }
5908 }
5909
5910 env.info.returnResult = null;
5911 // java.lang.Enum may not be subclassed by a non-enum
5912 if (st.tsym == syms.enumSym &&
5913 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0))
5914 log.error(env.tree.pos(), Errors.EnumNoSubclassing);
5915
5916 // Enums may not be extended by source-level classes
5917 if (st.tsym != null &&
5918 ((st.tsym.flags_field & Flags.ENUM) != 0) &&
5919 ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0)) {
5920 log.error(env.tree.pos(), Errors.EnumTypesNotExtensible);
5921 }
5922
5923 if (rs.isSerializable(c.type)) {
5924 env.info.isSerializable = true;
5925 }
5926
5927 if (c.isValueClass()) {
5928 Assert.check(env.tree.hasTag(CLASSDEF));
5929 chk.checkConstraintsOfValueClass((JCClassDecl) env.tree, c);
5930 }
5931
5932 attribClassBody(env, c);
5933
5934 chk.checkDeprecatedAnnotation(env.tree.pos(), c);
5935 chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c);
5936 chk.checkFunctionalInterface((JCClassDecl) env.tree, c);
5937 chk.checkLeaksNotAccessible(env, (JCClassDecl) env.tree);
5938
5939 if (c.isImplicit()) {
5940 chk.checkHasMain(env.tree.pos(), c);
5941 }
5942 } finally {
5943 env.info.returnResult = prevReturnRes;
5944 log.useSource(prev);
5945 chk.setLint(prevLint);
5946 }
5947
5948 }
5949 }
5950
5951 public void visitImport(JCImport tree) {
6054 sym.kind != VAR ||
6055 sym.getConstValue() == null)
6056 log.error(l.head.pos(), Errors.IclsCantHaveStaticDecl(c));
6057 }
6058 }
6059
6060 // Check for proper placement of super()/this() calls.
6061 chk.checkSuperInitCalls(tree);
6062
6063 // Check for cycles among non-initial constructors.
6064 chk.checkCyclicConstructors(tree);
6065
6066 // Check for cycles among annotation elements.
6067 chk.checkNonCyclicElements(tree);
6068
6069 // Check for proper use of serialVersionUID and other
6070 // serialization-related fields and methods
6071 if (env.info.lint.isEnabled(LintCategory.SERIAL)
6072 && rs.isSerializable(c.type)
6073 && !c.isAnonymous()) {
6074 chk.checkSerialStructure(env, tree, c);
6075 }
6076 // Correctly organize the positions of the type annotations
6077 typeAnnotations.organizeTypeAnnotationsBodies(tree);
6078
6079 // Check type annotations applicability rules
6080 validateTypeAnnotations(tree, false);
6081 }
6082 // where
6083 /** get a diagnostic position for an attribute of Type t, or null if attribute missing */
6084 private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) {
6085 for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) {
6086 if (types.isSameType(al.head.annotationType.type, t))
6087 return al.head.pos();
6088 }
6089
6090 return null;
6091 }
6092
6093 private Type capture(Type type) {
6094 return types.capture(type);
|