Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit 4ffbe84

Browse files
committedJan 5, 2021
8256266: Binding variables don't correctly support declaration annotations and the final modifier
Reviewed-by: mcimadamore
1 parent 216c2ec commit 4ffbe84

File tree

10 files changed

+237
-12
lines changed

10 files changed

+237
-12
lines changed
 

‎src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1865,8 +1865,8 @@ public Name getSimpleName() {
18651865

18661866
public static class BindingSymbol extends VarSymbol {
18671867

1868-
public BindingSymbol(Name name, Type type, Symbol owner) {
1869-
super(Flags.HASINIT | Flags.MATCH_BINDING, name, type, owner);
1868+
public BindingSymbol(long flags, Name name, Type type, Symbol owner) {
1869+
super(flags | Flags.HASINIT | Flags.MATCH_BINDING, name, type, owner);
18701870
}
18711871

18721872
public boolean isAliasFor(BindingSymbol b) {

‎src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ private void separateAnnotationsKinds(JCTree typetree, Type type,
389389
if (sym.getKind() == ElementKind.PARAMETER ||
390390
sym.getKind() == ElementKind.LOCAL_VARIABLE ||
391391
sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
392-
sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
392+
sym.getKind() == ElementKind.EXCEPTION_PARAMETER ||
393+
sym.getKind() == ElementKind.BINDING_VARIABLE) {
393394
appendTypeAnnotationsToOwner(sym, typeAnnotations);
394395
}
395396
}
@@ -1264,6 +1265,11 @@ public void visitVarDef(final JCVariableDecl tree) {
12641265
if (!tree.isImplicitlyTyped()) {
12651266
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
12661267
}
1268+
} else if (tree.sym.getKind() == ElementKind.BINDING_VARIABLE) {
1269+
final TypeAnnotationPosition pos =
1270+
TypeAnnotationPosition.localVariable(currentLambda,
1271+
tree.pos);
1272+
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
12671273
} else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
12681274
final TypeAnnotationPosition pos =
12691275
TypeAnnotationPosition.exceptionParameter(currentLambda,

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -4000,12 +4000,13 @@ public void visitTypeTest(JCInstanceOf tree) {
40004000
public void visitBindingPattern(JCBindingPattern tree) {
40014001
ResultInfo varInfo = new ResultInfo(KindSelector.TYP, resultInfo.pt, resultInfo.checkContext);
40024002
tree.type = tree.var.type = attribTree(tree.var.vartype, env, varInfo);
4003-
BindingSymbol v = new BindingSymbol(tree.var.name, tree.var.vartype.type, env.info.scope.owner);
4003+
BindingSymbol v = new BindingSymbol(tree.var.mods.flags, tree.var.name, tree.var.vartype.type, env.info.scope.owner);
40044004
v.pos = tree.pos;
40054005
tree.var.sym = v;
40064006
if (chk.checkUnique(tree.var.pos(), v, env.info.scope)) {
40074007
chk.checkTransparentVar(tree.var.pos(), v, env.info.scope);
40084008
}
4009+
annotate.annotateLater(tree.var.mods.annotations, env, v, tree.pos());
40094010
annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var.pos());
40104011
annotate.flush();
40114012
result = tree.type;
@@ -5761,7 +5762,7 @@ public void visitVarDef(JCVariableDecl that) {
57615762
@Override
57625763
public void visitBindingPattern(JCBindingPattern that) {
57635764
if (that.var.sym == null) {
5764-
that.var.sym = new BindingSymbol(that.var.name, that.var.type, syms.noSymbol);
5765+
that.var.sym = new BindingSymbol(0, that.var.name, that.var.type, syms.noSymbol);
57655766
that.var.sym.adr = 0;
57665767
}
57675768
super.visitBindingPattern(that);

‎src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

+23-6
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,13 @@ JCExpression illegal() {
490490

491491
/** Diagnose a modifier flag from the set, if any. */
492492
protected void checkNoMods(long mods) {
493+
checkNoMods(token.pos, mods);
494+
}
495+
496+
protected void checkNoMods(int pos, long mods) {
493497
if (mods != 0) {
494498
long lowestMod = mods & -mods;
495-
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ModNotAllowedHere(Flags.asFlagSet(lowestMod)));
499+
log.error(DiagnosticFlag.SYNTAX, pos, Errors.ModNotAllowedHere(Flags.asFlagSet(lowestMod)));
496500
}
497501
}
498502

@@ -932,17 +936,30 @@ JCExpression term2Rest(JCExpression t, int minprec) {
932936
if (token.kind == INSTANCEOF) {
933937
int pos = token.pos;
934938
nextToken();
939+
int patternPos = token.pos;
940+
JCModifiers mods = optFinal(0);
935941
int typePos = token.pos;
936-
JCExpression type = parseType();
942+
JCExpression type = unannotatedType(false);
937943
JCTree pattern;
938944
if (token.kind == IDENTIFIER) {
939945
checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
940-
JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
941946
JCVariableDecl var = toP(F.at(token.pos).VarDef(mods, ident(), type, null));
942-
TreeInfo.getStartPos(var);
943-
pattern = toP(F.at(typePos).BindingPattern(var));
944-
TreeInfo.getStartPos(pattern);
947+
pattern = toP(F.at(patternPos).BindingPattern(var));
945948
} else {
949+
checkNoMods(typePos, mods.flags & ~Flags.DEPRECATED);
950+
if (mods.annotations.nonEmpty()) {
951+
checkSourceLevel(mods.annotations.head.pos, Feature.TYPE_ANNOTATIONS);
952+
List<JCAnnotation> typeAnnos =
953+
mods.annotations
954+
.map(decl -> {
955+
JCAnnotation typeAnno = F.at(decl.pos)
956+
.TypeAnnotation(decl.annotationType,
957+
decl.args);
958+
endPosTable.replaceTree(decl, typeAnno);
959+
return typeAnno;
960+
});
961+
type = insertAnnotationsToMostInner(type, typeAnnos, false);
962+
}
946963
pattern = type;
947964
}
948965
odStack[top] = F.at(pos).TypeTest(odStack[top], pattern);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright (c) 2020, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8256266
27+
* @summary Verify annotations work correctly on binding variables
28+
* @library /tools/javac/lib
29+
* @modules java.compiler
30+
* jdk.compiler
31+
* jdk.jdeps/com.sun.tools.classfile
32+
* @build JavacTestingAbstractProcessor
33+
* @compile Annotations.java
34+
* @compile -processor Annotations -proc:only Annotations.java
35+
* @run main Annotations
36+
*/
37+
38+
import com.sun.source.tree.InstanceOfTree;
39+
import com.sun.source.util.TreePath;
40+
import java.lang.annotation.ElementType;
41+
import java.lang.annotation.Target;
42+
import java.util.Set;
43+
import javax.annotation.processing.RoundEnvironment;
44+
import javax.lang.model.element.Element;
45+
import javax.lang.model.element.TypeElement;
46+
import javax.lang.model.type.TypeMirror;
47+
48+
import com.sun.source.tree.BindingPatternTree;
49+
import com.sun.source.tree.VariableTree;
50+
import com.sun.source.util.TreePathScanner;
51+
import com.sun.source.util.Trees;
52+
import com.sun.tools.classfile.*;
53+
import java.io.InputStream;
54+
import java.util.Arrays;
55+
56+
public class Annotations extends JavacTestingAbstractProcessor {
57+
public static void main(String... args) throws Exception {
58+
new Annotations().run();
59+
}
60+
61+
void run() throws Exception {
62+
InputStream annotationsClass =
63+
Annotations.class.getResourceAsStream("Annotations.class");
64+
ClassFile cf = ClassFile.read(annotationsClass);
65+
for (Method m : cf.methods) {
66+
if ("test".equals(cf.constant_pool.getUTF8Value(m.name_index))) {
67+
Code_attribute codeAttr =
68+
(Code_attribute) m.attributes.map.get(Attribute.Code);
69+
Attribute annoAttr =
70+
codeAttr.attributes.map.get(Attribute.RuntimeInvisibleTypeAnnotations);
71+
RuntimeInvisibleTypeAnnotations_attribute annotations =
72+
(RuntimeInvisibleTypeAnnotations_attribute) annoAttr;
73+
String expected = "[@Annotations$DTA; pos: [LOCAL_VARIABLE, {start_pc = 35, length = 7, index = 1}, pos = -1], " +
74+
"@Annotations$TA; pos: [LOCAL_VARIABLE, {start_pc = 56, length = 7, index = 1}, pos = -1]]";
75+
String actual = Arrays.toString(annotations.annotations);
76+
if (!expected.equals(actual)) {
77+
throw new AssertionError("Unexpected type annotations: " +
78+
actual);
79+
}
80+
}
81+
}
82+
}
83+
84+
private static void test(Object o) {
85+
if (o instanceof @DA String da) {
86+
System.err.println(da);
87+
}
88+
if (o instanceof @DTA String dta) {
89+
System.err.println(dta);
90+
}
91+
if (o instanceof @TA String ta) {
92+
System.err.println(ta);
93+
}
94+
}
95+
96+
@Override
97+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
98+
Trees trees = Trees.instance(processingEnv);
99+
100+
for (Element root : roundEnv.getRootElements()) {
101+
TreePath tp = trees.getPath(root);
102+
new TreePathScanner<Void, Void>() {
103+
@Override
104+
public Void visitInstanceOf(InstanceOfTree node, Void p) {
105+
BindingPatternTree bpt = (BindingPatternTree) node.getPattern();
106+
VariableTree var = bpt.getVariable();
107+
Element varEl = trees.getElement(new TreePath(getCurrentPath(), var));
108+
String expectedDeclAnnos;
109+
String expectedType;
110+
switch (var.getName().toString()) {
111+
case "da" -> {
112+
expectedDeclAnnos = "@Annotations.DA";
113+
expectedType = "java.lang.String";
114+
}
115+
case "dta" -> {
116+
expectedDeclAnnos = "@Annotations.DTA";
117+
expectedType = "@Annotations.DTA java.lang.String";
118+
}
119+
case "ta" -> {
120+
expectedDeclAnnos = "";
121+
expectedType = "@Annotations.TA java.lang.String";
122+
}
123+
default -> {
124+
throw new AssertionError("Unexpected variable: " + var);
125+
}
126+
}
127+
String declAnnos = varEl.getAnnotationMirrors().toString();
128+
if (!expectedDeclAnnos.equals(declAnnos)) {
129+
throw new AssertionError("Unexpected modifiers: " + declAnnos +
130+
" for: " + var.getName());
131+
}
132+
TypeMirror varType = varEl.asType();
133+
String type = varType.toString();
134+
if (!expectedType.equals(type)) {
135+
throw new AssertionError("Unexpected type: " + type +
136+
" for: " + var.getName());
137+
}
138+
return super.visitInstanceOf(node, p);
139+
}
140+
}.scan(tp.getCompilationUnit(), null);
141+
}
142+
return false;
143+
}
144+
145+
@Target(ElementType.LOCAL_VARIABLE)
146+
@interface DA {}
147+
@Target({ElementType.TYPE_USE, ElementType.LOCAL_VARIABLE})
148+
@interface DTA {}
149+
@Target(ElementType.TYPE_USE)
150+
@interface TA {}
151+
}
152+

‎test/langtools/tools/javac/patterns/BindingsTest1.java

+15
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,21 @@ public void run() {
185185
String s2 = s;
186186
}
187187

188+
if (o1 instanceof final String s) {
189+
Runnable r1 = new Runnable() {
190+
@Override
191+
public void run() {
192+
s.length();
193+
}
194+
};
195+
r1.run();
196+
Runnable r2 = () -> {
197+
s.length();
198+
};
199+
r2.run();
200+
String s2 = s;
201+
}
202+
188203
boolean result = (o1 instanceof String a1) ? (o1 instanceof String a2) : (!(o1 instanceof String a3));
189204
boolean result2 = (o1 instanceof String a1) ? (o1 instanceof String a2) : (!(switch (0) { default -> false; }));
190205

‎test/langtools/tools/javac/patterns/BindingsTest2.java

+6
Original file line numberDiff line numberDiff line change
@@ -241,5 +241,11 @@ public static void main(String[] args) {
241241
s.length();
242242
}
243243
}
244+
245+
{
246+
if (o1 instanceof final String s) {
247+
s = "";
248+
}
249+
}
244250
}
245251
}

‎test/langtools/tools/javac/patterns/BindingsTest2.out

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ BindingsTest2.java:212:13: compiler.err.cant.resolve.location: kindname.variable
4646
BindingsTest2.java:221:17: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
4747
BindingsTest2.java:231:17: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
4848
BindingsTest2.java:241:17: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null)
49+
BindingsTest2.java:247:17: compiler.err.cant.assign.val.to.final.var: s
4950
BindingsTest2.java:135:17: compiler.err.unreachable.stmt
5051
BindingsTest2.java:160:17: compiler.err.unreachable.stmt
5152
BindingsTest2.java:185:17: compiler.err.unreachable.stmt
52-
51 errors
53+
52 errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* @test /nodynamiccopyright/
2+
* @bug 8256266
3+
* @summary Binding variables cannot have (non-annotation) modifiers.
4+
* @compile/fail/ref=NoModifiersOnBinding.out -XDrawDiagnostics NoModifiersOnBinding.java
5+
*/
6+
7+
public class NoModifiersOnBinding {
8+
9+
private static void test(Object o) {
10+
if (o instanceof final String) {
11+
System.err.println(s);
12+
}
13+
if (o instanceof /**@deprecated*/ String) {
14+
System.err.println(s);
15+
}
16+
if (o instanceof static String s) {
17+
System.err.println(s);
18+
}
19+
if (o instanceof /**@deprecated*/ String s) {
20+
System.err.println(s);
21+
}
22+
}
23+
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
NoModifiersOnBinding.java:10:32: compiler.err.mod.not.allowed.here: final
2+
NoModifiersOnBinding.java:16:33: compiler.err.mod.not.allowed.here: static
3+
2 errors

0 commit comments

Comments
 (0)
This repository has been archived.