8296010: AssertionError in annotationTargetType
Reviewed-by: jjg
This commit is contained in:
parent
e5042dd483
commit
de80dd9c15
src/jdk.compiler/share/classes/com/sun/tools/javac
test/langtools/tools/javac
annotations/crashOnUnknownAttr
diags
@ -180,7 +180,7 @@ public class TypeAnnotations {
|
||||
* Determine whether an annotation is a declaration annotation,
|
||||
* a type annotation, or both (or none, i.e a non-annotation masquerading as one).
|
||||
*/
|
||||
public AnnotationType annotationTargetType(Attribute.Compound a, Symbol s) {
|
||||
public AnnotationType annotationTargetType(JCTree pos, Attribute.Compound a, Symbol s) {
|
||||
if (!a.type.tsym.isAnnotationType()) {
|
||||
return AnnotationType.NONE;
|
||||
}
|
||||
@ -188,7 +188,7 @@ public class TypeAnnotations {
|
||||
return (targets == null) ?
|
||||
AnnotationType.DECLARATION :
|
||||
targets.stream()
|
||||
.map(attr -> targetToAnnotationType(attr, s))
|
||||
.map(attr -> targetToAnnotationType(pos, a, attr, s))
|
||||
.reduce(AnnotationType.NONE, this::combineAnnotationType);
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ public class TypeAnnotations {
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationType targetToAnnotationType(Attribute a, Symbol s) {
|
||||
private AnnotationType targetToAnnotationType(JCTree pos, Attribute.Compound anno, Attribute a, Symbol s) {
|
||||
Attribute.Enum e = (Attribute.Enum)a;
|
||||
if (e.value.name == names.TYPE) {
|
||||
if (s.kind == TYP)
|
||||
@ -254,8 +254,7 @@ public class TypeAnnotations {
|
||||
if (s.kind == MDL)
|
||||
return AnnotationType.DECLARATION;
|
||||
} else {
|
||||
Assert.error("annotationTargetType(): unrecognized Attribute name " + e.value.name +
|
||||
" (" + e.value.name.getClass() + ")");
|
||||
// there is an erroneous target, an error should have been reported already
|
||||
return AnnotationType.DECLARATION;
|
||||
}
|
||||
return AnnotationType.NONE;
|
||||
@ -305,8 +304,8 @@ public class TypeAnnotations {
|
||||
* we never build an JCAnnotatedType. This step finds these
|
||||
* annotations and marks them as if they were part of the type.
|
||||
*/
|
||||
private void separateAnnotationsKinds(JCTree typetree, Type type,
|
||||
Symbol sym, TypeAnnotationPosition pos)
|
||||
private void separateAnnotationsKinds(JCTree pos, JCTree typetree, Type type,
|
||||
Symbol sym, TypeAnnotationPosition typeAnnotationPosition)
|
||||
{
|
||||
List<Attribute.Compound> allAnnotations = sym.getRawAttributes();
|
||||
ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<>();
|
||||
@ -314,18 +313,18 @@ public class TypeAnnotations {
|
||||
ListBuffer<Attribute.TypeCompound> onlyTypeAnnos = new ListBuffer<>();
|
||||
|
||||
for (Attribute.Compound a : allAnnotations) {
|
||||
switch (annotationTargetType(a, sym)) {
|
||||
switch (annotationTargetType(pos, a, sym)) {
|
||||
case DECLARATION:
|
||||
declAnnos.append(a);
|
||||
break;
|
||||
case BOTH: {
|
||||
declAnnos.append(a);
|
||||
Attribute.TypeCompound ta = toTypeCompound(a, pos);
|
||||
Attribute.TypeCompound ta = toTypeCompound(a, typeAnnotationPosition);
|
||||
typeAnnos.append(ta);
|
||||
break;
|
||||
}
|
||||
case TYPE: {
|
||||
Attribute.TypeCompound ta = toTypeCompound(a, pos);
|
||||
Attribute.TypeCompound ta = toTypeCompound(a, typeAnnotationPosition);
|
||||
typeAnnos.append(ta);
|
||||
// Also keep track which annotations are only type annotations
|
||||
onlyTypeAnnos.append(ta);
|
||||
@ -355,7 +354,7 @@ public class TypeAnnotations {
|
||||
|
||||
// Declaration annotations are always allowed on constructor returns.
|
||||
// Therefore, use typeAnnotations instead of onlyTypeAnnos.
|
||||
typeWithAnnotations(typetree, type, typeAnnotations, typeAnnotations, pos);
|
||||
typeWithAnnotations(typetree, type, typeAnnotations, typeAnnotations, typeAnnotationPosition);
|
||||
// Note that we don't use the result, the call to
|
||||
// typeWithAnnotations side-effects the type annotation positions.
|
||||
// This is important for constructors of nested classes.
|
||||
@ -364,7 +363,7 @@ public class TypeAnnotations {
|
||||
}
|
||||
|
||||
// type is non-null, add type annotations from declaration context to the type
|
||||
type = typeWithAnnotations(typetree, type, typeAnnotations, onlyTypeAnnos.toList(), pos);
|
||||
type = typeWithAnnotations(typetree, type, typeAnnotations, onlyTypeAnnos.toList(), typeAnnotationPosition);
|
||||
|
||||
if (sym.getKind() == ElementKind.METHOD) {
|
||||
sym.type.asMethodType().restype = type;
|
||||
@ -1134,11 +1133,11 @@ public class TypeAnnotations {
|
||||
TypeAnnotationPosition.methodReturn(tree.pos);
|
||||
// Use null to mark that the annotations go
|
||||
// with the symbol.
|
||||
separateAnnotationsKinds(tree, null, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree, null, tree.sym, pos);
|
||||
} else {
|
||||
final TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.methodReturn(tree.restype.pos);
|
||||
separateAnnotationsKinds(tree.restype,
|
||||
separateAnnotationsKinds(tree, tree.restype,
|
||||
tree.sym.type.getReturnType(),
|
||||
tree.sym, pos);
|
||||
}
|
||||
@ -1151,7 +1150,7 @@ public class TypeAnnotations {
|
||||
final TypeAnnotationPosition pos = TypeAnnotationPosition.methodReceiver(tree.recvparam.vartype.pos);
|
||||
push(tree.recvparam);
|
||||
try {
|
||||
separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type, tree.recvparam.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.recvparam.vartype, tree.recvparam.sym.type, tree.recvparam.sym, pos);
|
||||
} finally {
|
||||
pop();
|
||||
}
|
||||
@ -1164,7 +1163,7 @@ public class TypeAnnotations {
|
||||
final TypeAnnotationPosition pos = TypeAnnotationPosition.methodParameter(i, param.vartype.pos);
|
||||
push(param);
|
||||
try {
|
||||
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
|
||||
separateAnnotationsKinds(param, param.vartype, param.sym.type, param.sym, pos);
|
||||
} finally {
|
||||
pop();
|
||||
}
|
||||
@ -1206,7 +1205,7 @@ public class TypeAnnotations {
|
||||
push(param);
|
||||
try {
|
||||
if (!param.declaredUsingVar()) {
|
||||
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
|
||||
separateAnnotationsKinds(param, param.vartype, param.sym.type, param.sym, pos);
|
||||
}
|
||||
} finally {
|
||||
pop();
|
||||
@ -1239,30 +1238,30 @@ public class TypeAnnotations {
|
||||
if (sigOnly) {
|
||||
TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.field(tree.pos);
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
}
|
||||
} else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) {
|
||||
final TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.localVariable(currentLambda,
|
||||
tree.pos);
|
||||
if (!tree.declaredUsingVar()) {
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
}
|
||||
} else if (tree.sym.getKind() == ElementKind.BINDING_VARIABLE) {
|
||||
final TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.localVariable(currentLambda,
|
||||
tree.pos);
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
|
||||
final TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.exceptionParameter(currentLambda,
|
||||
tree.pos);
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
|
||||
final TypeAnnotationPosition pos =
|
||||
TypeAnnotationPosition.resourceVariable(currentLambda,
|
||||
tree.pos);
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
|
||||
// No type annotations can occur here.
|
||||
} else {
|
||||
|
@ -5659,7 +5659,7 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void visitAnnotation(JCAnnotation tree) {
|
||||
chk.validateTypeAnnotation(tree, false);
|
||||
chk.validateTypeAnnotation(tree, null, false);
|
||||
super.visitAnnotation(tree);
|
||||
}
|
||||
public void visitAnnotatedType(JCAnnotatedType tree) {
|
||||
@ -5668,7 +5668,7 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
public void visitTypeParameter(JCTypeParameter tree) {
|
||||
chk.validateTypeAnnotations(tree.annotations, true);
|
||||
chk.validateTypeAnnotations(tree.annotations, tree.type.tsym, true);
|
||||
scan(tree.bounds);
|
||||
// Don't call super.
|
||||
// This is needed because above we call validateTypeAnnotation with
|
||||
@ -5866,7 +5866,7 @@ public class Attr extends JCTree.Visitor {
|
||||
// This method will raise an error for such a type.
|
||||
for (JCAnnotation ai : annotations) {
|
||||
if (!ai.type.isErroneous() &&
|
||||
typeAnnotations.annotationTargetType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
|
||||
typeAnnotations.annotationTargetType(ai, ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
|
||||
log.error(ai.pos(), Errors.AnnotationTypeNotApplicableToType(ai.type));
|
||||
}
|
||||
}
|
||||
|
@ -2956,9 +2956,9 @@ public class Check {
|
||||
|
||||
/** Check the type annotations.
|
||||
*/
|
||||
public void validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter) {
|
||||
public void validateTypeAnnotations(List<JCAnnotation> annotations, Symbol s, boolean isTypeParameter) {
|
||||
for (JCAnnotation a : annotations)
|
||||
validateTypeAnnotation(a, isTypeParameter);
|
||||
validateTypeAnnotation(a, s, isTypeParameter);
|
||||
}
|
||||
|
||||
/** Check an annotation of a symbol.
|
||||
@ -3127,8 +3127,10 @@ public class Check {
|
||||
}
|
||||
}
|
||||
|
||||
public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
|
||||
public void validateTypeAnnotation(JCAnnotation a, Symbol s, boolean isTypeParameter) {
|
||||
Assert.checkNonNull(a.type);
|
||||
// we just want to validate that the anotation doesn't have any wrong target
|
||||
if (s != null) getApplicableTargets(a, s);
|
||||
validateAnnotationTree(a);
|
||||
|
||||
if (a.hasTag(TYPE_ANNOTATION) &&
|
||||
@ -3457,9 +3459,10 @@ public class Check {
|
||||
} else if (target == names.MODULE) {
|
||||
if (s.kind == MDL)
|
||||
applicableTargets.add(names.MODULE);
|
||||
} else
|
||||
return Optional.empty(); // Unknown ElementType. This should be an error at declaration site,
|
||||
// assume applicable.
|
||||
} else {
|
||||
log.error(a, Errors.AnnotationUnrecognizedAttributeName(a.type, target));
|
||||
return Optional.empty(); // Unknown ElementType
|
||||
}
|
||||
}
|
||||
return Optional.of(applicableTargets);
|
||||
}
|
||||
|
@ -155,6 +155,10 @@ compiler.err.annotation.value.not.allowable.type=\
|
||||
compiler.err.expression.not.allowable.as.annotation.value=\
|
||||
expression not allowed as annotation value
|
||||
|
||||
# 0: type, 1: name
|
||||
compiler.err.annotation.unrecognized.attribute.name=\
|
||||
annotation @{0} has an unknown attribute named ''{1}''
|
||||
|
||||
compiler.err.anon.class.impl.intf.no.args=\
|
||||
anonymous class implements interface; cannot have arguments
|
||||
|
||||
|
156
test/langtools/tools/javac/annotations/crashOnUnknownAttr/A.jcod
Normal file
156
test/langtools/tools/javac/annotations/crashOnUnknownAttr/A.jcod
Normal file
@ -0,0 +1,156 @@
|
||||
class A {
|
||||
0xCAFEBABE;
|
||||
0; // minor version
|
||||
65; // version
|
||||
[] { // Constant Pool
|
||||
; // first element is empty
|
||||
class #2; // #1
|
||||
Utf8 "A"; // #2
|
||||
class #4; // #3
|
||||
Utf8 "java/lang/Object"; // #4
|
||||
class #6; // #5
|
||||
Utf8 "java/lang/annotation/Annotation"; // #6
|
||||
Utf8 "SourceFile"; // #7
|
||||
Utf8 "IncorrectAnno.java"; // #8
|
||||
Utf8 "RuntimeVisibleAnnotations"; // #9
|
||||
Utf8 "Ljava/lang/annotation/Target;"; // #10
|
||||
Utf8 "value"; // #11
|
||||
Utf8 "Ljava/lang/annotation/ElementType;"; // #12
|
||||
Utf8 "TYPE"; // #13
|
||||
Utf8 "FIELD"; // #14
|
||||
Utf8 "METHOD"; // #15
|
||||
Utf8 "PARAMETER"; // #16
|
||||
Utf8 "CONSTRUCTOR"; // #17
|
||||
Utf8 "LOCAL_VARIABLE"; // #18
|
||||
Utf8 "ANNOTATION_TYPE"; // #19
|
||||
Utf8 "TYPE_PARAMETER"; // #20
|
||||
Utf8 "TYPE_USE"; // #21
|
||||
Utf8 "RECORD_COMPONENT"; // #22
|
||||
Utf8 "NO_SUCH"; // #23
|
||||
} // Constant Pool
|
||||
|
||||
0x2600; // access
|
||||
#1;// this_cpx
|
||||
#3;// super_cpx
|
||||
|
||||
[] { // Interfaces
|
||||
#5;
|
||||
} // Interfaces
|
||||
|
||||
[] { // Fields
|
||||
} // Fields
|
||||
|
||||
[] { // Methods
|
||||
} // Methods
|
||||
|
||||
[] { // Attributes
|
||||
Attr(#7) { // SourceFile
|
||||
#8;
|
||||
} // end SourceFile
|
||||
;
|
||||
Attr(#9) { // RuntimeVisibleAnnotations
|
||||
[] { // annotations
|
||||
{ // annotation
|
||||
#10;
|
||||
[] { // element_value_pairs
|
||||
{ // element value pair
|
||||
#11;
|
||||
{ // element_value
|
||||
'[';
|
||||
[] { // array_value
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#13;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#14;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#15;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#16;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#17;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#18;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#19;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#20;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#21;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#22;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
;
|
||||
{ // element_value
|
||||
'e';
|
||||
{ // enum_const_value
|
||||
#12;
|
||||
#23;
|
||||
} // enum_const_value
|
||||
} // element_value
|
||||
} // array_value
|
||||
} // element_value
|
||||
} // element value pair
|
||||
} // element_value_pairs
|
||||
} // annotation
|
||||
}
|
||||
} // end RuntimeVisibleAnnotations
|
||||
} // Attributes
|
||||
} // end class A
|
20
test/langtools/tools/javac/annotations/crashOnUnknownAttr/CrashOnUnknownTargetTypeTest.java
Normal file
20
test/langtools/tools/javac/annotations/crashOnUnknownAttr/CrashOnUnknownTargetTypeTest.java
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @summary compiler is crashing with AssertionError for annotations with unknown target type
|
||||
* @bug 8296010
|
||||
* @build A
|
||||
* @compile/fail/ref=CrashOnUnknownTargetTypeTest.out -XDrawDiagnostics CrashOnUnknownTargetTypeTest.java
|
||||
*/
|
||||
|
||||
public class CrashOnUnknownTargetTypeTest {
|
||||
@A Object o;
|
||||
@A void m() {}
|
||||
void foo(@A int a) {
|
||||
@A int i = 0;
|
||||
}
|
||||
@A CrashOnUnknownTargetTypeTest() {}
|
||||
@A @interface B {}
|
||||
class Inner<@A T> {}
|
||||
@A class Inner2 {}
|
||||
record R(@A int i) {}
|
||||
}
|
13
test/langtools/tools/javac/annotations/crashOnUnknownAttr/CrashOnUnknownTargetTypeTest.out
Normal file
13
test/langtools/tools/javac/annotations/crashOnUnknownAttr/CrashOnUnknownTargetTypeTest.out
Normal file
@ -0,0 +1,13 @@
|
||||
- compiler.warn.unknown.enum.constant: ElementType.class, java.lang.annotation.ElementType, NO_SUCH
|
||||
- compiler.warn.unknown.enum.constant: String.class, java.lang.annotation.ElementType, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:10:5: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:11:5: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:12:14: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:15:5: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:16:5: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:17:17: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:18:5: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:19:14: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
CrashOnUnknownTargetTypeTest.java:13:9: compiler.err.annotation.unrecognized.attribute.name: A, NO_SUCH
|
||||
9 errors
|
||||
2 warnings
|
@ -208,3 +208,6 @@ compiler.warn.target.default.source.conflict
|
||||
compiler.err.preview.not.latest
|
||||
compiler.err.preview.without.source.or.release
|
||||
compiler.misc.illegal.signature # the compiler can now detect more non-denotable types before class writing
|
||||
|
||||
# this one needs a forged class file to be reproduced
|
||||
compiler.err.annotation.unrecognized.attribute.name
|
Loading…
x
Reference in New Issue
Block a user