Skip to content

Commit 1d71dd8

Browse files
committed
8230105: -XDfind=diamond crashes
Avoiding side-effects in Analyzer's speculative attribution. Reviewed-by: mcimadamore, vromero
1 parent 277ef75 commit 1d71dd8

File tree

13 files changed

+267
-20
lines changed

13 files changed

+267
-20
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@
2626
package com.sun.tools.javac.comp;
2727

2828
import java.util.ArrayDeque;
29+
import java.util.Arrays;
2930
import java.util.EnumSet;
3031
import java.util.HashMap;
3132
import java.util.Map;
3233
import java.util.Queue;
33-
import java.util.function.Predicate;
34+
import java.util.stream.Collectors;
3435

3536
import com.sun.source.tree.LambdaExpressionTree;
3637
import com.sun.source.tree.NewClassTree;
@@ -42,6 +43,7 @@
4243
import com.sun.tools.javac.code.Type;
4344
import com.sun.tools.javac.code.Types;
4445
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
46+
import com.sun.tools.javac.comp.DeferredAttr.AttributionMode;
4547
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
4648
import com.sun.tools.javac.tree.JCTree;
4749
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -446,7 +448,7 @@ void process(JCEnhancedForLoop oldTree, JCEnhancedForLoop newTree, boolean hasEr
446448
*/
447449
Env<AttrContext> copyEnvIfNeeded(JCTree tree, Env<AttrContext> env) {
448450
if (!analyzerModes.isEmpty() &&
449-
!env.info.isSpeculative &&
451+
!env.info.attributionMode.isSpeculative &&
450452
TreeInfo.isStatement(tree) &&
451453
!tree.hasTag(LABELLED)) {
452454
Env<AttrContext> analyzeEnv =
@@ -562,10 +564,14 @@ void doAnalysis(RewritingContext rewriting) {
562564

563565
//TODO: to further refine the analysis, try all rewriting combinations
564566
deferredAttr.attribSpeculative(treeToAnalyze, rewriting.env, attr.statInfo, new TreeRewriter(rewriting),
565-
t -> rewriting.diagHandler(), argumentAttr.withLocalCacheContext());
567+
t -> rewriting.diagHandler(), AttributionMode.ANALYZER, argumentAttr.withLocalCacheContext());
566568
rewriting.analyzer.process(rewriting.oldTree, rewriting.replacement, rewriting.erroneous);
567569
} catch (Throwable ex) {
568-
Assert.error("Analyzer error when processing: " + rewriting.originalTree);
570+
Assert.error("Analyzer error when processing: " +
571+
rewriting.originalTree + ":" + ex.toString() + "\n" +
572+
Arrays.stream(ex.getStackTrace())
573+
.map(se -> se.toString())
574+
.collect(Collectors.joining("\n")));
569575
} finally {
570576
log.useSource(prevSource.getFile());
571577
localCacheContext.leave();
@@ -628,6 +634,11 @@ public void visitBlock(JCBlock tree) {
628634
//do nothing (prevents seeing same stuff twice)
629635
}
630636

637+
@Override
638+
public void visitLambda(JCLambda tree) {
639+
//do nothing (prevents seeing same stuff in lambda expression twice)
640+
}
641+
631642
@Override
632643
public void visitSwitch(JCSwitch tree) {
633644
scan(tree.getExpression());

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ protected ArgumentAttr(Context context) {
136136
*/
137137
void setResult(JCExpression tree, Type type) {
138138
result = type;
139-
if (env.info.isSpeculative) {
139+
if (env.info.attributionMode == DeferredAttr.AttributionMode.SPECULATIVE) {
140140
//if we are in a speculative branch we can save the type in the tree itself
141141
//as there's no risk of polluting the original tree.
142142
tree.type = result;
@@ -365,7 +365,7 @@ final public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrC
365365
speculativeTypes.put(resultInfo, t);
366366
return t;
367367
} else {
368-
if (!env.info.isSpeculative) {
368+
if (!env.info.attributionMode.isSpeculative) {
369369
argumentTypeCache.remove(new UniquePos(dt.tree));
370370
}
371371
return deferredAttr.basicCompleter.complete(dt, resultInfo, deferredAttrContext);

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -735,11 +735,9 @@ Type attribType(JCTree tree, Env<AttrContext> env, Type pt) {
735735
*/
736736
public Type attribStat(JCTree tree, Env<AttrContext> env) {
737737
Env<AttrContext> analyzeEnv = analyzer.copyEnvIfNeeded(tree, env);
738-
try {
739-
return attribTree(tree, env, statInfo);
740-
} finally {
741-
analyzer.analyzeIfNeeded(tree, analyzeEnv);
742-
}
738+
Type result = attribTree(tree, env, statInfo);
739+
analyzer.analyzeIfNeeded(tree, analyzeEnv);
740+
return result;
743741
}
744742

745743
/** Attribute a list of expressions, returning a list of types.
@@ -933,7 +931,7 @@ Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
933931

934932
public void visitClassDef(JCClassDecl tree) {
935933
Optional<ArgumentAttr.LocalCacheContext> localCacheContext =
936-
Optional.ofNullable(env.info.isSpeculative ?
934+
Optional.ofNullable(env.info.attributionMode.isSpeculative ?
937935
argumentAttr.withLocalCacheContext() : null);
938936
try {
939937
// Local and anonymous classes have not been entered yet, so we need to
@@ -3232,7 +3230,7 @@ public void visitReference(final JCMemberReference that) {
32323230
return;
32333231
}
32343232

3235-
if (!env.info.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) {
3233+
if (!env.info.attributionMode.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) {
32363234
Type enclosingType = exprType.getEnclosingType();
32373235
if (enclosingType != null && enclosingType.hasTag(CLASS)) {
32383236
// Check for the existence of an apropriate outer instance

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.sun.tools.javac.util.*;
3030
import com.sun.tools.javac.code.*;
3131
import com.sun.tools.javac.code.Scope.WriteableScope;
32+
import com.sun.tools.javac.comp.DeferredAttr.AttributionMode;
3233

3334
/** Contains information specific to the attribute and enter
3435
* passes, to be used in place of the generic field in environments.
@@ -67,7 +68,7 @@ public class AttrContext {
6768

6869
/** Is this a speculative attribution environment?
6970
*/
70-
boolean isSpeculative = false;
71+
AttributionMode attributionMode = AttributionMode.FULL;
7172

7273
/**
7374
* Is this an attribution environment for an anonymous class instantiated using <> ?
@@ -133,7 +134,7 @@ AttrContext dup(WriteableScope scope) {
133134
info.defaultSuperCallSite = defaultSuperCallSite;
134135
info.isSerializable = isSerializable;
135136
info.isLambda = isLambda;
136-
info.isSpeculative = isSpeculative;
137+
info.attributionMode = attributionMode;
137138
info.isAnonymousDiamond = isAnonymousDiamond;
138139
info.isNewClass = isNewClass;
139140
info.preferredTreeForDiagnostics = preferredTreeForDiagnostics;

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,25 +481,28 @@ JCLambda attribSpeculativeLambda(JCLambda that, Env<AttrContext> env, ResultInfo
481481
*/
482482
JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
483483
return attribSpeculative(tree, env, resultInfo, treeCopier,
484-
(newTree)->new DeferredAttrDiagHandler(log, newTree), null);
484+
(newTree)->new DeferredAttrDiagHandler(log, newTree), AttributionMode.SPECULATIVE, null);
485485
}
486486

487487
JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, LocalCacheContext localCache) {
488488
return attribSpeculative(tree, env, resultInfo, treeCopier,
489-
(newTree)->new DeferredAttrDiagHandler(log, newTree), localCache);
489+
(newTree)->new DeferredAttrDiagHandler(log, newTree), AttributionMode.SPECULATIVE, localCache);
490490
}
491491

492492
<Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, TreeCopier<Z> deferredCopier,
493-
Function<JCTree, DeferredDiagnosticHandler> diagHandlerCreator,
493+
Function<JCTree, DeferredDiagnosticHandler> diagHandlerCreator, AttributionMode attributionMode,
494494
LocalCacheContext localCache) {
495495
final JCTree newTree = deferredCopier.copy(tree);
496496
Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
497-
speculativeEnv.info.isSpeculative = true;
497+
speculativeEnv.info.attributionMode = attributionMode;
498498
Log.DeferredDiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator.apply(newTree);
499+
int nwarnings = log.nwarnings;
500+
log.nwarnings = 0;
499501
try {
500502
attr.attribTree(newTree, speculativeEnv, resultInfo);
501503
return newTree;
502504
} finally {
505+
log.nwarnings += nwarnings;
503506
enter.unenter(env.toplevel, newTree);
504507
log.popDiagnosticHandler(deferredDiagnosticHandler);
505508
if (localCache != null) {
@@ -1286,4 +1289,26 @@ public void visitReference(JCMemberReference tree) {
12861289
}
12871290
}
12881291
}
1292+
1293+
/**
1294+
* Mode of attribution (used in AttrContext).
1295+
*/
1296+
enum AttributionMode {
1297+
/**Normal, non-speculative, attribution.*/
1298+
FULL(false),
1299+
/**Speculative attribution on behalf of an Analyzer.*/
1300+
ANALYZER(true),
1301+
/**Speculative attribution.*/
1302+
SPECULATIVE(true);
1303+
1304+
AttributionMode(boolean isSpeculative) {
1305+
this.isSpeculative = isSpeculative;
1306+
}
1307+
1308+
boolean isSpeculative() {
1309+
return isSpeculative;
1310+
}
1311+
1312+
final boolean isSpeculative;
1313+
}
12891314
}

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2391,7 +2391,7 @@ Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck,
23912391
if (kind.contains(KindSelector.TYP)) {
23922392
RecoveryLoadClass recoveryLoadClass =
23932393
allowModules && !kind.contains(KindSelector.PCK) &&
2394-
!pck.exists() && !env.info.isSpeculative ?
2394+
!pck.exists() && !env.info.attributionMode.isSpeculative ?
23952395
doRecoveryLoadClass : noRecovery;
23962396
Symbol sym = loadClass(env, fullname, recoveryLoadClass);
23972397
if (sym.exists()) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @test
3+
* @bug 8230105
4+
* @summary Verify analyzers work reasonably in combination with mandatory warnings
5+
* @compile/ref=AnalyzerMandatoryWarnings.out -Xlint:deprecation -XDrawDiagnostics -Xmaxwarns 1 -XDfind=lambda AnalyzerMandatoryWarnings.java
6+
*/
7+
public class AnalyzerMandatoryWarnings {
8+
private void test() {
9+
Runnable r = new Runnable() {
10+
public void run() {
11+
Depr r;
12+
}
13+
};
14+
}
15+
}
16+
@Deprecated class Depr {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
AnalyzerMandatoryWarnings.java:11:17: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package
2+
1 warning
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @test /nodynamiccopyright/
3+
* @bug 8230105
4+
* @summary Ensuring speculative analysis on behalf of Analyzers works reasonably.
5+
* @compile/ref=AnalyzerNotQuiteSpeculative.out -XDfind=diamond -XDrawDiagnostics AnalyzerNotQuiteSpeculative.java
6+
*/
7+
public class AnalyzerNotQuiteSpeculative {
8+
private void test() {
9+
Subclass1 c1 = null;
10+
Subclass2 c2 = null;
11+
Base b = null;
12+
13+
t(new C<Base>(c1).set(c2));
14+
t(new C<Base>(b).set(c2));
15+
}
16+
17+
public static class Base {}
18+
public static class Subclass1 extends Base {}
19+
public static class Subclass2 extends Base {}
20+
public class C<T extends Base> {
21+
public C(T t) {}
22+
public C<T> set(T t) { return this; }
23+
}
24+
<T extends Base> void t(C<? extends Base> l) {}
25+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
AnalyzerNotQuiteSpeculative.java:14:16: compiler.warn.diamond.redundant.args
2+
1 warning

0 commit comments

Comments
 (0)