8296010: AssertionError in annotationTargetType

Reviewed-by: jjg
This commit is contained in:
Vicente Romero 2023-02-16 19:06:26 +00:00
parent e5042dd483
commit de80dd9c15
8 changed files with 229 additions and 31 deletions
src/jdk.compiler/share/classes/com/sun/tools/javac
test/langtools/tools/javac

@ -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

@ -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

@ -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) {}
}

@ -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