From 829eeca2e9431584ee628a5b3e4b0ee5b80cf49e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 22 May 2022 21:22:54 +0200 Subject: [PATCH 01/24] always write MethodParameters attribute for methods with mandated parameters --- .../com/sun/tools/javac/jvm/ClassWriter.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 5233f04beb7a8..ece2d7b420aa7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -31,6 +31,7 @@ import java.util.Set; import java.util.LinkedHashSet; import java.util.function.ToIntFunction; +import java.util.stream.Stream; import javax.tools.JavaFileManager; import javax.tools.FileObject; @@ -40,7 +41,6 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Directive.*; -import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException; @@ -1005,7 +1005,7 @@ void writeMethod(MethodSymbol m) { endAttr(alenIdx); acount++; } - if (target.hasMethodParameters() && (options.isSet(PARAMETERS) || m.isConstructor() && (m.flags_field & RECORD) != 0)) { + if (target.hasMethodParameters() && requiresMethodParametersAttr(m)) { if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies. acount += writeMethodParametersAttr(m); } @@ -1016,6 +1016,23 @@ void writeMethod(MethodSymbol m) { endAttrs(acountIdx, acount); } + private boolean requiresMethodParametersAttr(MethodSymbol m) { + if (options.isSet(PARAMETERS)) { + return true; + } + if (m.isConstructor() && (m.flags_field & RECORD) != 0) { + return true; + } + if (!m.extraParams.isEmpty()) { + return m.extraParams.stream().anyMatch(p -> (p.flags_field & MANDATED) != 0); + } + if (m.params != null) { + // parameter is stored in params for Enum#valueOf(name) + return m.params.stream().anyMatch(p -> (p.flags_field & MANDATED) != 0); + } + return false; + } + /** Write code attribute of method. */ void writeCode(Code code) { From 65b1f46126268229a49ecf4211830702e69f8594 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 27 May 2022 18:57:15 +0200 Subject: [PATCH 02/24] only write param names when needed --- .../com/sun/tools/javac/jvm/ClassWriter.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index ece2d7b420aa7..294b872904dd6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -379,7 +379,7 @@ int writeMemberAttrs(Symbol sym, boolean isRecordComponent) { /** * Write method parameter names attribute. */ - int writeMethodParametersAttr(MethodSymbol m) { + int writeMethodParametersAttr(MethodSymbol m, boolean writeParamNames) { MethodType ty = m.externalType(types).asMethodType(); final int allparams = ty.argtypes.size(); if (m.params != null && allparams != 0) { @@ -390,7 +390,10 @@ int writeMethodParametersAttr(MethodSymbol m) { final int flags = ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | ((int) m.flags() & SYNTHETIC); - databuf.appendChar(poolWriter.putName(s.name)); + if (writeParamNames) + databuf.appendChar(poolWriter.putName(s.name)); + else + databuf.appendChar(0); databuf.appendChar(flags); } // Now write the real parameters @@ -398,7 +401,10 @@ int writeMethodParametersAttr(MethodSymbol m) { final int flags = ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | ((int) m.flags() & SYNTHETIC); - databuf.appendChar(poolWriter.putName(s.name)); + if (writeParamNames) + databuf.appendChar(poolWriter.putName(s.name)); + else + databuf.appendChar(0); databuf.appendChar(flags); } // Now write the captured locals @@ -406,7 +412,10 @@ int writeMethodParametersAttr(MethodSymbol m) { final int flags = ((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) | ((int) m.flags() & SYNTHETIC); - databuf.appendChar(poolWriter.putName(s.name)); + if (writeParamNames) + databuf.appendChar(poolWriter.putName(s.name)); + else + databuf.appendChar(0); databuf.appendChar(flags); } endAttr(attrIndex); @@ -1007,7 +1016,7 @@ void writeMethod(MethodSymbol m) { } if (target.hasMethodParameters() && requiresMethodParametersAttr(m)) { if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies. - acount += writeMethodParametersAttr(m); + acount += writeMethodParametersAttr(m, options.isSet(PARAMETERS) || (m.isConstructor() && (m.flags_field & RECORD) != 0)); } acount += writeMemberAttrs(m, false); if (!m.isLambdaMethod()) From aa807199c18759fe87d4a65af9b7a3bbfa13bc9e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 28 May 2022 09:52:36 +0200 Subject: [PATCH 03/24] name index might be 0 --- .../classes/build/tools/symbolgenerator/CreateSymbols.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 5e3cd01a4b891..8f8c5933b4e44 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -2384,7 +2384,10 @@ private boolean readAttribute(ClassFile cf, FeatureDescription feature, Attribut MethodDescription method = (MethodDescription) feature; method.methodParameters = new ArrayList<>(); for (MethodParameters_attribute.Entry e : params.method_parameter_table) { - String name = cf.constant_pool.getUTF8Value(e.name_index); + String name = null; + if (e.name_index != 0) { + name = cf.constant_pool.getUTF8Value(e.name_index); + } MethodDescription.MethodParam param = new MethodDescription.MethodParam(e.flags, name); method.methodParameters.add(param); From 12d10d2cc52acc18f27de1129046e7971fafd0cf Mon Sep 17 00:00:00 2001 From: SirYwell Date: Tue, 7 Jun 2022 15:37:05 +0200 Subject: [PATCH 04/24] split name and flag requirements --- .../com/sun/tools/javac/jvm/ClassWriter.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 294b872904dd6..6e7d5c0d6082d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -31,7 +31,6 @@ import java.util.Set; import java.util.LinkedHashSet; import java.util.function.ToIntFunction; -import java.util.stream.Stream; import javax.tools.JavaFileManager; import javax.tools.FileObject; @@ -1014,9 +1013,12 @@ void writeMethod(MethodSymbol m) { endAttr(alenIdx); acount++; } - if (target.hasMethodParameters() && requiresMethodParametersAttr(m)) { - if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies. - acount += writeMethodParametersAttr(m, options.isSet(PARAMETERS) || (m.isConstructor() && (m.flags_field & RECORD) != 0)); + if (target.hasMethodParameters()) { + if (!m.isLambdaMethod()) { // Per JDK-8138729, do not emit parameters table for lambda bodies. + boolean requiresParamNames = requiresParamNames(m); + if (requiresParamNames || requiresParamFlags(m)) + acount += writeMethodParametersAttr(m, requiresParamNames); + } } acount += writeMemberAttrs(m, false); if (!m.isLambdaMethod()) @@ -1025,13 +1027,20 @@ void writeMethod(MethodSymbol m) { endAttrs(acountIdx, acount); } - private boolean requiresMethodParametersAttr(MethodSymbol m) { - if (options.isSet(PARAMETERS)) { + private boolean requiresParamNames(MethodSymbol m) { + if (options.isSet(PARAMETERS)) return true; - } - if (m.isConstructor() && (m.flags_field & RECORD) != 0) { + if (m.isConstructor() && (m.flags_field & RECORD) != 0) return true; - } + if (m.owner.isEnum() + && m.isStatic() + && m.name == names.valueOf + && (m.params != null && m.params.tail.isEmpty() && (m.params.head.flags_field & MANDATED) != 0)) + return true; + return false; + } + + private boolean requiresParamFlags(MethodSymbol m) { if (!m.extraParams.isEmpty()) { return m.extraParams.stream().anyMatch(p -> (p.flags_field & MANDATED) != 0); } From 09bb0c4ed592ad0e3456bf1f35b09e315bab9af4 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Tue, 7 Jun 2022 16:44:14 +0200 Subject: [PATCH 05/24] adapt change to constant pool in test --- .../typeAnnotations/classfile/AnnotatedExtendsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java index 3c785debf42cd..49b45a1d1355d 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java @@ -59,7 +59,7 @@ public static strictfp void main(String args[]) throws Exception { .classes(classPath.toString()) .run() .getOutput(Task.OutputKind.DIRECT); - if (!javapOut.contains("0: #20(): CLASS_EXTENDS, type_index=65535")) + if (!javapOut.contains("0: #21(): CLASS_EXTENDS, type_index=65535")) throw new AssertionError("Expected output missing: " + javapOut); } } From cbc3e5d44aaa10642754e0a944491b66209e46de Mon Sep 17 00:00:00 2001 From: SirYwell Date: Wed, 8 Jun 2022 21:19:22 +0200 Subject: [PATCH 06/24] revert valueOf hack --- .../share/classes/com/sun/tools/javac/jvm/ClassWriter.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 6e7d5c0d6082d..9a8a308b4eb20 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1032,11 +1032,6 @@ private boolean requiresParamNames(MethodSymbol m) { return true; if (m.isConstructor() && (m.flags_field & RECORD) != 0) return true; - if (m.owner.isEnum() - && m.isStatic() - && m.name == names.valueOf - && (m.params != null && m.params.tail.isEmpty() && (m.params.head.flags_field & MANDATED) != 0)) - return true; return false; } From 3cc4c8ef1b464818ae42c107c6328144d4327e69 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 19 Jun 2022 11:14:52 +0200 Subject: [PATCH 07/24] also require flags for synthetic --- .../share/classes/com/sun/tools/javac/jvm/ClassWriter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 9a8a308b4eb20..f1035ecc16a8b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1037,11 +1037,11 @@ private boolean requiresParamNames(MethodSymbol m) { private boolean requiresParamFlags(MethodSymbol m) { if (!m.extraParams.isEmpty()) { - return m.extraParams.stream().anyMatch(p -> (p.flags_field & MANDATED) != 0); + return m.extraParams.stream().anyMatch(p -> (p.flags_field & (SYNTHETIC | MANDATED)) != 0); } if (m.params != null) { // parameter is stored in params for Enum#valueOf(name) - return m.params.stream().anyMatch(p -> (p.flags_field & MANDATED) != 0); + return m.params.stream().anyMatch(p -> (p.flags_field & (SYNTHETIC | MANDATED)) != 0); } return false; } From 7c7c1934544c08fd337766f7657473978424b35a Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 19 Jun 2022 15:33:02 +0200 Subject: [PATCH 08/24] combine parameter names from LVT and MethodParameters --- .../com/sun/tools/javac/jvm/ClassReader.java | 159 +++++++++--------- 1 file changed, 80 insertions(+), 79 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index d3f252bab0d08..672275042895e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -192,7 +192,13 @@ public class ClassReader { /** A table to hold the constant pool indices for method parameter * names, as given in LocalVariableTable attributes. */ - int[] parameterNameIndices; + int[] parameterNameIndicesLvt; + + /** + * A table to hold the constant pool indices for method parameter + * names, as given in the MethodParameters attribute. + */ + int[] parameterNameIndicesMp; /** * A table to hold the access flags of the method parameters. @@ -219,18 +225,6 @@ void add(List newAnnotations) { } } - /** - * Whether or not any parameter names have been found. - */ - boolean haveParameterNameIndices; - - /** Set this to false every time we start reading a method - * and are saving parameter names. Set it to true when we see - * MethodParameters, if it's set when we see a LocalVariableTable, - * then we ignore the parameter names from the LVT. - */ - boolean sawMethodParameters; - /** * The set of attribute names for which warnings have been generated for the current class */ @@ -880,7 +874,7 @@ protected void read(Symbol sym, int attrLen) { new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { protected void read(Symbol sym, int attrLen) { int newbp = bp + attrLen; - if (saveParameterNames && !sawMethodParameters) { + if (saveParameterNames) { // Pick up parameter names from the variable table. // Parameter names are not explicitly identified as such, // but all parameter name entries in the LocalVariableTable @@ -899,14 +893,13 @@ protected void read(Symbol sym, int attrLen) { int register = nextChar(); if (start_pc == 0) { // ensure array large enough - if (register >= parameterNameIndices.length) { + if (register >= parameterNameIndicesLvt.length) { int newSize = - Math.max(register + 1, parameterNameIndices.length + 8); - parameterNameIndices = - Arrays.copyOf(parameterNameIndices, newSize); + Math.max(register + 1, parameterNameIndicesLvt.length + 8); + parameterNameIndicesLvt = + Arrays.copyOf(parameterNameIndicesLvt, newSize); } - parameterNameIndices[register] = nameIndex; - haveParameterNameIndices = true; + parameterNameIndicesLvt[register] = nameIndex; } } } @@ -1057,11 +1050,9 @@ protected void read(Symbol sym, int attrLen) { protected void read(Symbol sym, int attrlen) { int newbp = bp + attrlen; if (saveParameterNames) { - sawMethodParameters = true; int numEntries = nextByte(); - parameterNameIndices = new int[numEntries]; + parameterNameIndicesMp = new int[numEntries]; parameterAccessFlags = new int[numEntries]; - haveParameterNameIndices = true; int index = 0; for (int i = 0; i < numEntries; i++) { int nameIndex = nextChar(); @@ -1069,7 +1060,7 @@ protected void read(Symbol sym, int attrlen) { if ((flags & (Flags.MANDATED | Flags.SYNTHETIC)) != 0) { continue; } - parameterNameIndices[index] = nameIndex; + parameterNameIndicesMp[index] = nameIndex; parameterAccessFlags[index] = flags; index++; } @@ -2310,13 +2301,11 @@ void initParameterNames(MethodSymbol sym) { final int excessSlots = 4; int expectedParameterSlots = Code.width(sym.type.getParameterTypes()) + excessSlots; - if (parameterNameIndices == null - || parameterNameIndices.length < expectedParameterSlots) { - parameterNameIndices = new int[expectedParameterSlots]; + if (parameterNameIndicesLvt == null + || parameterNameIndicesLvt.length < expectedParameterSlots) { + parameterNameIndicesLvt = new int[expectedParameterSlots]; } else - Arrays.fill(parameterNameIndices, 0); - haveParameterNameIndices = false; - sawMethodParameters = false; + Arrays.fill(parameterNameIndicesLvt, 0); } /** @@ -2331,46 +2320,47 @@ void initParameterNames(MethodSymbol sym) { * anonymous synthetic parameters. */ void setParameters(MethodSymbol sym, Type jvmType) { - // If we get parameter names from MethodParameters, then we - // don't need to skip. - int firstParam = 0; - if (!sawMethodParameters) { - firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; - // the code in readMethod may have skipped the first - // parameter when setting up the MethodType. If so, we - // make a corresponding allowance here for the position of - // the first parameter. Note that this assumes the - // skipped parameter has a width of 1 -- i.e. it is not - // a double width type (long or double.) - if (sym.name == names.init && currentOwner.hasOuterInstance()) { - // Sometimes anonymous classes don't have an outer - // instance, however, there is no reliable way to tell so - // we never strip this$n - if (!currentOwner.name.isEmpty()) - firstParam += 1; - } - - if (sym.type != jvmType) { - // reading the method attributes has caused the - // symbol's type to be changed. (i.e. the Signature - // attribute.) This may happen if there are hidden - // (synthetic) parameters in the descriptor, but not - // in the Signature. The position of these hidden - // parameters is unspecified; for now, assume they are - // at the beginning, and so skip over them. The - // primary case for this is two hidden parameters - // passed into Enum constructors. - int skip = Code.width(jvmType.getParameterTypes()) - - Code.width(sym.type.getParameterTypes()); - firstParam += skip; - } + int firstParamLvt = ((sym.flags() & STATIC) == 0) ? 1 : 0; + // the code in readMethod may have skipped the first + // parameter when setting up the MethodType. If so, we + // make a corresponding allowance here for the position of + // the first parameter. Note that this assumes the + // skipped parameter has a width of 1 -- i.e. it is not + // a double width type (long or double.) + if (sym.name == names.init && currentOwner.hasOuterInstance()) { + // Sometimes anonymous classes don't have an outer + // instance, however, there is no reliable way to tell so + // we never strip this$n + if (!currentOwner.name.isEmpty()) + firstParamLvt += 1; + } + + if (sym.type != jvmType) { + // reading the method attributes has caused the + // symbol's type to be changed. (i.e. the Signature + // attribute.) This may happen if there are hidden + // (synthetic) parameters in the descriptor, but not + // in the Signature. The position of these hidden + // parameters is unspecified; for now, assume they are + // at the beginning, and so skip over them. The + // primary case for this is two hidden parameters + // passed into Enum constructors. + int skip = Code.width(jvmType.getParameterTypes()) + - Code.width(sym.type.getParameterTypes()); + firstParamLvt += skip; } Set paramNames = new HashSet<>(); ListBuffer params = new ListBuffer<>(); - int nameIndex = firstParam; + // we maintain two index pointers, one for the LocalVariableTable attribute + // and the other for the MethodParameters attribute. + // This is needed as the MethodParameters attribute may contain + // name_index = 0 in which case we want to fall back to the LocalVariableTable. + // In such case, we still want to read the flags from the MethodParameters with that index. + int nameIndexLvt = firstParamLvt; + int nameIndexMp = 0; int annotationIndex = 0; for (Type t: sym.type.getParameterTypes()) { - VarSymbol param = parameter(nameIndex, t, sym, paramNames); + VarSymbol param = parameter(nameIndexMp, nameIndexLvt, t, sym, paramNames); params.append(param); if (parameterAnnotations != null) { ParameterAnnotations annotations = parameterAnnotations[annotationIndex]; @@ -2379,7 +2369,8 @@ void setParameters(MethodSymbol sym, Type jvmType) { annotate.normal(new AnnotationCompleter(param, annotations.proxies)); } } - nameIndex += sawMethodParameters ? 1 : Code.width(t); + nameIndexLvt += Code.width(t); + nameIndexMp++; annotationIndex++; } if (parameterAnnotations != null && parameterAnnotations.length != annotationIndex) { @@ -2388,24 +2379,34 @@ void setParameters(MethodSymbol sym, Type jvmType) { Assert.checkNull(sym.params); sym.params = params.toList(); parameterAnnotations = null; - parameterNameIndices = null; + parameterNameIndicesLvt = null; + parameterNameIndicesMp = null; parameterAccessFlags = null; } - - // Returns the name for the parameter at position 'index', either using - // names read from the MethodParameters, or by synthesizing a name that - // is not on the 'exclude' list. - private VarSymbol parameter(int index, Type t, MethodSymbol owner, Set exclude) { + /** + * Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method. + * Flags are optionally read from the MethodParameters attribute. + * Names are optionally read from the MethodParameters attribute. If the constant pool index + * of the name is 0, then the name is optionally read from the LocalVariableTable attribute. + * @param mpIndex the index of the parameter in the MethodParameters attribute + * @param lvtIndex the index of the parameter in the LocalVariableTable attribute + */ + private VarSymbol parameter(int mpIndex, int lvtIndex, Type t, MethodSymbol owner, Set exclude) { long flags = PARAMETER; Name argName; - if (parameterAccessFlags != null && index < parameterAccessFlags.length - && parameterAccessFlags[index] != 0) { - flags |= parameterAccessFlags[index]; - } - if (parameterNameIndices != null && index < parameterNameIndices.length - && parameterNameIndices[index] != 0) { - argName = optPoolEntry(parameterNameIndices[index], poolReader::getName, names.empty); + if (parameterAccessFlags != null && mpIndex < parameterAccessFlags.length + && parameterAccessFlags[mpIndex] != 0) { + flags |= parameterAccessFlags[mpIndex]; + } + if (parameterNameIndicesMp != null + // if name_index is 0, then we might still get a name from the LocalVariableTable + && parameterNameIndicesMp[mpIndex] != 0) { + argName = optPoolEntry(parameterNameIndicesMp[mpIndex], poolReader::getName, names.empty); + flags |= NAME_FILLED; + } else if (parameterNameIndicesLvt != null && lvtIndex < parameterNameIndicesLvt.length + && parameterNameIndicesLvt[lvtIndex] != 0) { + argName = optPoolEntry(parameterNameIndicesLvt[lvtIndex], poolReader::getName, names.empty); flags |= NAME_FILLED; } else { String prefix = "arg"; From ba7986f9e3320ff871bf680a8c9275c18610501f Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 7 Aug 2022 15:37:39 +0200 Subject: [PATCH 09/24] add javac testcase for implicit parameters --- .../ImplicitParameters.java | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java new file mode 100644 index 0000000000000..621a8608bb176 --- /dev/null +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -0,0 +1,128 @@ +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.MethodParameters_attribute; +import com.sun.tools.javac.code.Flags; +import toolbox.Assert; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.ToolBox; + +/* + * @test + * @summary check that implicit parameter flags are available by default + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.code + * jdk.jdeps/com.sun.tools.classfile + * @run main ImplicitParameters + */ +public class ImplicitParameters extends TestRunner { + public ImplicitParameters() { + super(System.err); + } + + public static void main(String[] args) throws Exception { + new ImplicitParameters().runTests(); + } + + @Override + protected void runTests() throws Exception { + Path base = Path.of(".").toAbsolutePath(); + compileCLasses(base); + runTests(method -> new Object[]{ readClassFile(base.resolve("classes"), method) }); + } + + private void compileCLasses(Path base) throws IOException { + String outer = """ + class Outer { + class Inner { + public Inner(Inner notMandated) {} + } + + Inner anonymousInner = this.new Inner(null) {}; + + enum MyEnum {} + + record MyRecord(int a, Object b) { + MyRecord {} + } + } + """; + Path src = base.resolve("src"); + ToolBox tb = new ToolBox(); + tb.writeJavaFiles(src, outer); + Path classes = base.resolve("classes"); + Files.createDirectories(classes); + new JavacTask(tb) + .files(tb.findJavaFiles(src)) + .outdir(classes) + .run(Task.Expect.SUCCESS) + .writeAll(); + } + + private ClassFile readClassFile(Path classes, Method method) { + String className = method.getAnnotation(ClassName.class).value(); + try { + return ClassFile.read(classes.resolve("Outer$" + className + ".class")); + } catch (IOException | ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @interface ClassName { + String value(); + } + + @Test + @ClassName("Inner") + public void testInnerClassConstructor(ClassFile classFile) { + MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); + Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); + MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; + Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + Assert.check((table[1].flags & Flags.MANDATED) == 0, "mandated flag must not be set for explicit parameter"); + } + + @Test + @ClassName("1") + public void testAnonymousClassExtendingInnerClassConstructor(ClassFile classFile) { + MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); + Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); + MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; + Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + Assert.check((table[1].flags & Flags.MANDATED) == 0, "mandated flag must not be set for explicit parameter"); + } + + @Test + @ClassName("MyEnum") + public void testValueOfInEnum(ClassFile classFile) throws ConstantPoolException { + for (com.sun.tools.classfile.Method method : classFile.methods) { + if (method.getName(classFile.constant_pool).equals("valueOf")) { + MethodParameters_attribute methodParameters = (MethodParameters_attribute) method.attributes.get("MethodParameters"); + Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); + MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; + Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + } + } + } + + @Test + @ClassName("MyRecord") + public void testCompactConstructor(ClassFile classFile) { + MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); + Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); + MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; + for (int i = 0; i < methodParameters.method_parameter_table_length; i++) { + Assert.check((table[i].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + } + } +} From bac6aec90e834bfe74a051a358e6925cb8abc117 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 22 May 2022 09:30:58 +0200 Subject: [PATCH 10/24] set mandated flag for parameters of compact constructor --- .../share/classes/com/sun/tools/javac/parser/JavacParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 5270fd24e4c07..5abf2067acf71 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -4020,7 +4020,7 @@ protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) { for (JCVariableDecl param : headerFields) { tmpParams.add(F.at(param) // we will get flags plus annotations from the record component - .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | param.mods.flags & Flags.VARARGS, + .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | Flags.MANDATED | param.mods.flags & Flags.VARARGS, param.mods.annotations), param.name, param.vartype, null)); } From 8eb393990898d349c24e022b06bf7d72d3f070ae Mon Sep 17 00:00:00 2001 From: SirYwell Date: Mon, 8 Aug 2022 20:41:46 +0200 Subject: [PATCH 11/24] update constant pool indexes in AnnoTest --- test/langtools/tools/javap/AnnoTest.java | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/langtools/tools/javap/AnnoTest.java b/test/langtools/tools/javap/AnnoTest.java index 649d7e7b38afa..6f88bf0f9eb78 100644 --- a/test/langtools/tools/javap/AnnoTest.java +++ b/test/langtools/tools/javap/AnnoTest.java @@ -49,50 +49,50 @@ void run() throws Exception { expect(out, "RuntimeVisibleAnnotations:\n" + - " 0: #17(#18=B#19)\n" + + " 0: #18(#19=B#20)\n" + " AnnoTest$ByteAnno(\n" + " value=(byte) 42\n" + " )\n" + - " 1: #20(#18=S#21)\n" + + " 1: #21(#19=S#22)\n" + " AnnoTest$ShortAnno(\n" + " value=(short) 3\n" + " )"); expect(out, "RuntimeInvisibleAnnotations:\n" + - " 0: #23(#18=[J#24,J#26,J#28,J#30,J#32])\n" + + " 0: #24(#19=[J#25,J#27,J#29,J#31,J#33])\n" + " AnnoTest$ArrayAnno(\n" + " value=[1l,2l,3l,4l,5l]\n" + " )\n" + - " 1: #34(#18=Z#35)\n" + + " 1: #35(#19=Z#36)\n" + " AnnoTest$BooleanAnno(\n" + " value=false\n" + " )\n" + - " 2: #36(#37=c#38)\n" + + " 2: #37(#38=c#39)\n" + " AnnoTest$ClassAnno(\n" + " type=class Ljava/lang/Object;\n" + " )\n" + - " 3: #39(#40=e#41.#42)\n" + + " 3: #40(#41=e#42.#43)\n" + " AnnoTest$EnumAnno(\n" + " kind=Ljavax/lang/model/element/ElementKind;.PACKAGE\n" + " )\n" + - " 4: #43(#18=I#44)\n" + + " 4: #44(#19=I#45)\n" + " AnnoTest$IntAnno(\n" + " value=2\n" + " )\n" + - " 5: #45()\n" + + " 5: #46()\n" + " AnnoTest$IntDefaultAnno\n" + - " 6: #46(#47=s#48)\n" + + " 6: #47(#48=s#49)\n" + " AnnoTest$NameAnno(\n" + " name=\"NAME\"\n" + " )\n" + - " 7: #49(#50=D#51,#53=F#54)\n" + + " 7: #50(#51=D#52,#54=F#55)\n" + " AnnoTest$MultiAnno(\n" + " d=3.14159d\n" + " f=2.71828f\n" + " )\n" + - " 8: #55()\n" + + " 8: #56()\n" + " AnnoTest$SimpleAnno\n" + - " 9: #56(#18=@#43(#18=I#57))\n" + + " 9: #57(#19=@#44(#19=I#58))\n" + " AnnoTest$AnnoAnno(\n" + " value=@AnnoTest$IntAnno(\n" + " value=5\n" + @@ -100,7 +100,7 @@ void run() throws Exception { " )"); expect(out, "RuntimeInvisibleTypeAnnotations:\n" + - " 0: #59(): CLASS_EXTENDS, type_index=0\n" + + " 0: #60(): CLASS_EXTENDS, type_index=0\n" + " AnnoTest$TypeAnno"); if (errors > 0) From 17df27fae77ef4c012d8005afead7e868ceb1d7e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 12 Aug 2022 19:23:38 +0200 Subject: [PATCH 12/24] copyright --- .../com/sun/tools/javac/jvm/ClassWriter.java | 2 +- .../ImplicitParameters.java | 22 +++++++++++++++++++ .../classfile/AnnotatedExtendsTest.java | 2 +- test/langtools/tools/javap/AnnoTest.java | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index f1035ecc16a8b..fe9e9818ca865 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index 621a8608bb176..b6bc324007399 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java index 49b45a1d1355d..ba4d4938c8f29 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javap/AnnoTest.java b/test/langtools/tools/javap/AnnoTest.java index 6f88bf0f9eb78..b92411c9e8f19 100644 --- a/test/langtools/tools/javap/AnnoTest.java +++ b/test/langtools/tools/javap/AnnoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 21c547d0adf1838b53df38291817e5e9d15e72c7 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 12 Aug 2022 19:39:48 +0200 Subject: [PATCH 13/24] add bug number to test --- .../ImplicitParameters.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index b6bc324007399..cd7122abed7cc 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -20,6 +20,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/* + * @test + * @bug 8292275 + * @summary check that implicit parameter flags are available by default + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.code + * jdk.jdeps/com.sun.tools.classfile + * @run main ImplicitParameters + */ + import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -36,16 +49,6 @@ import toolbox.TestRunner; import toolbox.ToolBox; -/* - * @test - * @summary check that implicit parameter flags are available by default - * @library /tools/lib - * @modules jdk.compiler/com.sun.tools.javac.api - * jdk.compiler/com.sun.tools.javac.main - * jdk.compiler/com.sun.tools.javac.code - * jdk.jdeps/com.sun.tools.classfile - * @run main ImplicitParameters - */ public class ImplicitParameters extends TestRunner { public ImplicitParameters() { super(System.err); From c9ba84c74a0be76c69bef99b91b92f072a4ce542 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 12 Aug 2022 22:17:08 +0200 Subject: [PATCH 14/24] remove spaces from empty lines in text block --- .../javac/RequiredParameterFlags/ImplicitParameters.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index cd7122abed7cc..e0e49295574e2 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -71,11 +71,11 @@ class Outer { class Inner { public Inner(Inner notMandated) {} } - + Inner anonymousInner = this.new Inner(null) {}; - + enum MyEnum {} - + record MyRecord(int a, Object b) { MyRecord {} } From e453380bad89e52bba05df2728e5e8644c2dc633 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 13 Aug 2022 21:10:02 +0200 Subject: [PATCH 15/24] add access flag based test --- .../RequiredMethodParameterFlagTest.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java new file mode 100644 index 0000000000000..65c921cc9acc1 --- /dev/null +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.AccessFlag; +import java.lang.reflect.Parameter; +import java.util.Set; + +/* + * @test + * @bug 8292275 + * @summary Test required flags on parameters + * @compile RequiredMethodParameterFlagTest.java + * @run main RequiredMethodParameterFlagTest + */ +public class RequiredMethodParameterFlagTest { + public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { + boolean errors = false; + Set mandated = Set.of(AccessFlag.MANDATED); + Set synthetic = Set.of(AccessFlag.SYNTHETIC); + // test for implicit parameters + Parameter[] parameters = Inner.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(Set.of(), parameters[1]); + + parameters = findAnonymous().getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(Set.of(), parameters[1]); + + parameters = MyEnum.class.getDeclaredMethod("valueOf", String.class).getParameters(); + errors |= assertFlags(mandated, parameters[0]); + + parameters = MyRecord.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(mandated, parameters[1]); + + // test for synthetic parameters + // assuming javac creates two synthetic parameters corresponding to Enum(String name, int ordinal) + parameters = MyEnum.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(synthetic, parameters[0]); + errors |= assertFlags(synthetic, parameters[1]); + errors |= assertFlags(Set.of(), parameters[2]); + errors |= assertFlags(Set.of(), parameters[3]); + + if (errors) { + throw new AssertionError(); + } + } + + // returns true on error + private static boolean assertFlags(Set flags, Parameter parameter) { + Set accessFlags = parameter.accessFlags(); + if (!accessFlags.containsAll(flags)) { + System.err.println("Required flags not present"); + System.err.println("Required: " + flags); + System.err.println("Actual: " + accessFlags); + return true; + } + return false; + } + + private static Class findAnonymous() { + try { + return Class.forName("RequiredMethodParameterFlagTest$1"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Anonymous class missing"); + } + } + + class Inner { + public Inner(Inner notMandated) {} + } + + Inner anonymousInner = this.new Inner(null) {}; + + enum MyEnum { + ; + MyEnum(String s, int i) {} + } + + record MyRecord(int a, Object b) { + MyRecord {} + } +} From b393150767c987f83555f3494fdbd32298f91a84 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 13 Aug 2022 22:19:28 +0200 Subject: [PATCH 16/24] fix line breaks --- .../RequiredMethodParameterFlagTest.java | 206 +++++++++--------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java index 65c921cc9acc1..9999f364bd9ba 100644 --- a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -1,103 +1,103 @@ -/* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.lang.reflect.AccessFlag; -import java.lang.reflect.Parameter; -import java.util.Set; - -/* - * @test - * @bug 8292275 - * @summary Test required flags on parameters - * @compile RequiredMethodParameterFlagTest.java - * @run main RequiredMethodParameterFlagTest - */ -public class RequiredMethodParameterFlagTest { - public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { - boolean errors = false; - Set mandated = Set.of(AccessFlag.MANDATED); - Set synthetic = Set.of(AccessFlag.SYNTHETIC); - // test for implicit parameters - Parameter[] parameters = Inner.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(Set.of(), parameters[1]); - - parameters = findAnonymous().getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(Set.of(), parameters[1]); - - parameters = MyEnum.class.getDeclaredMethod("valueOf", String.class).getParameters(); - errors |= assertFlags(mandated, parameters[0]); - - parameters = MyRecord.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(mandated, parameters[1]); - - // test for synthetic parameters - // assuming javac creates two synthetic parameters corresponding to Enum(String name, int ordinal) - parameters = MyEnum.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(synthetic, parameters[0]); - errors |= assertFlags(synthetic, parameters[1]); - errors |= assertFlags(Set.of(), parameters[2]); - errors |= assertFlags(Set.of(), parameters[3]); - - if (errors) { - throw new AssertionError(); - } - } - - // returns true on error - private static boolean assertFlags(Set flags, Parameter parameter) { - Set accessFlags = parameter.accessFlags(); - if (!accessFlags.containsAll(flags)) { - System.err.println("Required flags not present"); - System.err.println("Required: " + flags); - System.err.println("Actual: " + accessFlags); - return true; - } - return false; - } - - private static Class findAnonymous() { - try { - return Class.forName("RequiredMethodParameterFlagTest$1"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Anonymous class missing"); - } - } - - class Inner { - public Inner(Inner notMandated) {} - } - - Inner anonymousInner = this.new Inner(null) {}; - - enum MyEnum { - ; - MyEnum(String s, int i) {} - } - - record MyRecord(int a, Object b) { - MyRecord {} - } -} +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.AccessFlag; +import java.lang.reflect.Parameter; +import java.util.Set; + +/* + * @test + * @bug 8292275 + * @summary Test required flags on parameters + * @compile RequiredMethodParameterFlagTest.java + * @run main RequiredMethodParameterFlagTest + */ +public class RequiredMethodParameterFlagTest { + public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { + boolean errors = false; + Set mandated = Set.of(AccessFlag.MANDATED); + Set synthetic = Set.of(AccessFlag.SYNTHETIC); + // test for implicit parameters + Parameter[] parameters = Inner.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(Set.of(), parameters[1]); + + parameters = findAnonymous().getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(Set.of(), parameters[1]); + + parameters = MyEnum.class.getDeclaredMethod("valueOf", String.class).getParameters(); + errors |= assertFlags(mandated, parameters[0]); + + parameters = MyRecord.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(mandated, parameters[0]); + errors |= assertFlags(mandated, parameters[1]); + + // test for synthetic parameters + // assuming javac creates two synthetic parameters corresponding to Enum(String name, int ordinal) + parameters = MyEnum.class.getDeclaredConstructors()[0].getParameters(); + errors |= assertFlags(synthetic, parameters[0]); + errors |= assertFlags(synthetic, parameters[1]); + errors |= assertFlags(Set.of(), parameters[2]); + errors |= assertFlags(Set.of(), parameters[3]); + + if (errors) { + throw new AssertionError(); + } + } + + // returns true on error + private static boolean assertFlags(Set flags, Parameter parameter) { + Set accessFlags = parameter.accessFlags(); + if (!accessFlags.containsAll(flags)) { + System.err.println("Required flags not present"); + System.err.println("Required: " + flags); + System.err.println("Actual: " + accessFlags); + return true; + } + return false; + } + + private static Class findAnonymous() { + try { + return Class.forName("RequiredMethodParameterFlagTest$1"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Anonymous class missing"); + } + } + + class Inner { + public Inner(Inner notMandated) {} + } + + Inner anonymousInner = this.new Inner(null) {}; + + enum MyEnum { + ; + MyEnum(String s, int i) {} + } + + record MyRecord(int a, Object b) { + MyRecord {} + } +} From 55b81f2fe5a4b8fe6e0b03644105a57dc861622a Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 19 Aug 2022 14:28:40 +0200 Subject: [PATCH 17/24] add annotation processing test --- .../MethodParameters/ClassContainer.java | 30 +++++ .../ImplicitParametersProcessor.java | 105 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java create mode 100644 test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java new file mode 100644 index 0000000000000..659d07fad1833 --- /dev/null +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +class ClassContainer { + + enum MyEnum {} + + record MyRecord(int a, Object b) { + MyRecord {} + } +} diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java new file mode 100644 index 0000000000000..ab185540ec26f --- /dev/null +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8292275 + * @summary Check origin of implicit parameters + * @library /tools/javac/lib + * @modules java.compiler + * jdk.compiler + * @build JavacTestingAbstractProcessor ImplicitParametersProcessor + * @compile -processor ImplicitParametersProcessor -proc:only ClassContainer.java + */ +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static javax.lang.model.util.ElementFilter.constructorsIn; +import static javax.lang.model.util.ElementFilter.methodsIn; +import static javax.lang.model.util.ElementFilter.typesIn; + +public class ImplicitParametersProcessor extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return true; + } + boolean hasError = false; + for (TypeElement typeElement : typesIn(roundEnv.getRootElements())) { + for (TypeElement innerType : typesIn(typeElement.getEnclosedElements())) { + System.out.println("Visiting " + innerType);if ("MyRecord".contentEquals(innerType.getSimpleName())) { + hasError |= checkAllExecutables(innerType, Map.of( + "", List.of(Elements.Origin.MANDATED, Elements.Origin.MANDATED) + )); + } else if ("MyEnum".contentEquals(innerType.getSimpleName())) { + hasError |= checkAllExecutables(innerType, Map.of( + "valueOf", List.of(Elements.Origin.MANDATED) + )); + } + } + } + if (hasError) { + throw new IllegalStateException("Wrong element origins found"); + } + return true; + } + + boolean checkAllExecutables(TypeElement element, Map> expectations) { + boolean hasError = false; + for (ExecutableElement executable : constructorsIn(element.getEnclosedElements())) { + hasError |= checkExecutable(expectations, executable); + } + for (ExecutableElement executable : methodsIn(element.getEnclosedElements())) { + hasError |= checkExecutable(expectations, executable); + } + return hasError; + } + + private boolean checkExecutable(Map> expectations, ExecutableElement executable) { + System.out.println("Looking at executable " + executable); + List list = expectations.get(executable.getSimpleName().toString()); + if (list == null) { + System.out.println("ignoring this executable due to missing expectations"); + return false; + } + List parameters = executable.getParameters(); + System.out.println("found " + parameters); + boolean hasError = false; + for (int i = 0; i < parameters.size(); i++) { + VariableElement parameter = parameters.get(i); + Elements.Origin origin = eltUtils.getOrigin(parameter); + if (origin != list.get(i)) { + System.out.println("ERROR: Wrong origin. Expected: " + list.get(i) + " but got " + origin); + hasError = true; + } + } + return hasError; + } +} From ebb09f8d19f656ac879075c09f8ce8c9614577db Mon Sep 17 00:00:00 2001 From: SirYwell Date: Fri, 19 Aug 2022 14:29:12 +0200 Subject: [PATCH 18/24] cleanup --- .../ImplicitParameters.java | 19 +- .../MethodParameters/ClassContainer.java | 60 ++--- .../ImplicitParametersProcessor.java | 211 +++++++++--------- 3 files changed, 146 insertions(+), 144 deletions(-) diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index e0e49295574e2..01147a6f6c77c 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,6 @@ * @run main ImplicitParameters */ -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.MethodParameters_attribute; @@ -49,6 +43,13 @@ import toolbox.TestRunner; import toolbox.ToolBox; +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; + public class ImplicitParameters extends TestRunner { public ImplicitParameters() { super(System.err); @@ -61,11 +62,11 @@ public static void main(String[] args) throws Exception { @Override protected void runTests() throws Exception { Path base = Path.of(".").toAbsolutePath(); - compileCLasses(base); + compileClasses(base); runTests(method -> new Object[]{ readClassFile(base.resolve("classes"), method) }); } - private void compileCLasses(Path base) throws IOException { + private void compileClasses(Path base) throws IOException { String outer = """ class Outer { class Inner { diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java index 659d07fad1833..a5bbb021fe09d 100644 --- a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -class ClassContainer { - - enum MyEnum {} - - record MyRecord(int a, Object b) { - MyRecord {} - } -} +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +class ClassContainer { + + enum MyEnum {} + + record MyRecord(int a, Object b) { + MyRecord {} + } +} diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java index ab185540ec26f..1b70133a77b6d 100644 --- a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java @@ -1,105 +1,106 @@ -/* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8292275 - * @summary Check origin of implicit parameters - * @library /tools/javac/lib - * @modules java.compiler - * jdk.compiler - * @build JavacTestingAbstractProcessor ImplicitParametersProcessor - * @compile -processor ImplicitParametersProcessor -proc:only ClassContainer.java - */ -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.util.Elements; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static javax.lang.model.util.ElementFilter.constructorsIn; -import static javax.lang.model.util.ElementFilter.methodsIn; -import static javax.lang.model.util.ElementFilter.typesIn; - -public class ImplicitParametersProcessor extends JavacTestingAbstractProcessor { - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (roundEnv.processingOver()) { - return true; - } - boolean hasError = false; - for (TypeElement typeElement : typesIn(roundEnv.getRootElements())) { - for (TypeElement innerType : typesIn(typeElement.getEnclosedElements())) { - System.out.println("Visiting " + innerType);if ("MyRecord".contentEquals(innerType.getSimpleName())) { - hasError |= checkAllExecutables(innerType, Map.of( - "", List.of(Elements.Origin.MANDATED, Elements.Origin.MANDATED) - )); - } else if ("MyEnum".contentEquals(innerType.getSimpleName())) { - hasError |= checkAllExecutables(innerType, Map.of( - "valueOf", List.of(Elements.Origin.MANDATED) - )); - } - } - } - if (hasError) { - throw new IllegalStateException("Wrong element origins found"); - } - return true; - } - - boolean checkAllExecutables(TypeElement element, Map> expectations) { - boolean hasError = false; - for (ExecutableElement executable : constructorsIn(element.getEnclosedElements())) { - hasError |= checkExecutable(expectations, executable); - } - for (ExecutableElement executable : methodsIn(element.getEnclosedElements())) { - hasError |= checkExecutable(expectations, executable); - } - return hasError; - } - - private boolean checkExecutable(Map> expectations, ExecutableElement executable) { - System.out.println("Looking at executable " + executable); - List list = expectations.get(executable.getSimpleName().toString()); - if (list == null) { - System.out.println("ignoring this executable due to missing expectations"); - return false; - } - List parameters = executable.getParameters(); - System.out.println("found " + parameters); - boolean hasError = false; - for (int i = 0; i < parameters.size(); i++) { - VariableElement parameter = parameters.get(i); - Elements.Origin origin = eltUtils.getOrigin(parameter); - if (origin != list.get(i)) { - System.out.println("ERROR: Wrong origin. Expected: " + list.get(i) + " but got " + origin); - hasError = true; - } - } - return hasError; - } -} +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8292275 + * @summary Check origin of implicit parameters + * @library /tools/javac/lib + * @modules java.compiler + * jdk.compiler + * @build JavacTestingAbstractProcessor ImplicitParametersProcessor + * @compile -processor ImplicitParametersProcessor -proc:only ClassContainer.java + */ + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static javax.lang.model.util.ElementFilter.constructorsIn; +import static javax.lang.model.util.ElementFilter.methodsIn; +import static javax.lang.model.util.ElementFilter.typesIn; + +public class ImplicitParametersProcessor extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return true; + } + boolean hasError = false; + for (TypeElement typeElement : typesIn(roundEnv.getRootElements())) { + for (TypeElement innerType : typesIn(typeElement.getEnclosedElements())) { + System.out.println("Visiting " + innerType); + if ("MyRecord".contentEquals(innerType.getSimpleName())) { + hasError |= checkAllExecutables(innerType, Map.of( + "", List.of(Elements.Origin.MANDATED, Elements.Origin.MANDATED) + )); + } else if ("MyEnum".contentEquals(innerType.getSimpleName())) { + hasError |= checkAllExecutables(innerType, Map.of( + "valueOf", List.of(Elements.Origin.MANDATED) + )); + } + } + } + if (hasError) { + throw new IllegalStateException("Wrong element origins found"); + } + return true; + } + + boolean checkAllExecutables(TypeElement element, Map> expectations) { + boolean hasError = false; + for (ExecutableElement executable : constructorsIn(element.getEnclosedElements())) { + hasError |= checkExecutable(expectations, executable); + } + for (ExecutableElement executable : methodsIn(element.getEnclosedElements())) { + hasError |= checkExecutable(expectations, executable); + } + return hasError; + } + + private boolean checkExecutable(Map> expectations, ExecutableElement executable) { + System.out.println("Looking at executable " + executable); + List list = expectations.get(executable.getSimpleName().toString()); + if (list == null) { + System.out.println("ignoring this executable due to missing expectations"); + return false; + } + List parameters = executable.getParameters(); + boolean hasError = false; + for (int i = 0; i < parameters.size(); i++) { + VariableElement parameter = parameters.get(i); + Elements.Origin origin = eltUtils.getOrigin(parameter); + if (origin != list.get(i)) { + System.err.println("ERROR: Wrong origin for " + executable + ". Expected: " + list.get(i) + " but got " + origin + " at index " + i); + hasError = true; + } + } + return hasError; + } +} From 883a2dc1eb07d2b9bbbca737da17685c61f2f477 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Tue, 23 Aug 2022 21:30:34 +0200 Subject: [PATCH 19/24] address comments --- .../MethodParameters/ClassContainer.java | 30 ------------- .../ImplicitParametersProcessor.java | 45 ++++++++++++------- 2 files changed, 28 insertions(+), 47 deletions(-) delete mode 100644 test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java deleted file mode 100644 index a5bbb021fe09d..0000000000000 --- a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ClassContainer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -class ClassContainer { - - enum MyEnum {} - - record MyRecord(int a, Object b) { - MyRecord {} - } -} diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java index 1b70133a77b6d..7d12edb84d769 100644 --- a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java @@ -24,12 +24,12 @@ /* * @test * @bug 8292275 - * @summary Check origin of implicit parameters + * @summary Verify specific executables in enums and records have mandated parameters * @library /tools/javac/lib * @modules java.compiler * jdk.compiler * @build JavacTestingAbstractProcessor ImplicitParametersProcessor - * @compile -processor ImplicitParametersProcessor -proc:only ClassContainer.java + * @compile -processor ImplicitParametersProcessor -proc:only ImplicitParametersProcessor.java */ import javax.annotation.processing.RoundEnvironment; @@ -37,9 +37,11 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.util.Elements; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static javax.lang.model.util.ElementFilter.constructorsIn; import static javax.lang.model.util.ElementFilter.methodsIn; @@ -56,15 +58,9 @@ public boolean process(Set annotations, RoundEnvironment for (TypeElement typeElement : typesIn(roundEnv.getRootElements())) { for (TypeElement innerType : typesIn(typeElement.getEnclosedElements())) { System.out.println("Visiting " + innerType); - if ("MyRecord".contentEquals(innerType.getSimpleName())) { - hasError |= checkAllExecutables(innerType, Map.of( - "", List.of(Elements.Origin.MANDATED, Elements.Origin.MANDATED) - )); - } else if ("MyEnum".contentEquals(innerType.getSimpleName())) { - hasError |= checkAllExecutables(innerType, Map.of( - "valueOf", List.of(Elements.Origin.MANDATED) - )); - } + ExpectedOrigin[] expectedOrigins = innerType.getAnnotationsByType(ExpectedOrigin.class); + hasError |= checkAllExecutables(innerType, Arrays.stream(expectedOrigins) + .collect(Collectors.toMap(ExpectedOrigin::method, ExpectedOrigin::origins))); } } if (hasError) { @@ -73,7 +69,7 @@ public boolean process(Set annotations, RoundEnvironment return true; } - boolean checkAllExecutables(TypeElement element, Map> expectations) { + boolean checkAllExecutables(TypeElement element, Map expectations) { boolean hasError = false; for (ExecutableElement executable : constructorsIn(element.getEnclosedElements())) { hasError |= checkExecutable(expectations, executable); @@ -84,10 +80,10 @@ boolean checkAllExecutables(TypeElement element, Map> expectations, ExecutableElement executable) { + private boolean checkExecutable(Map expectations, ExecutableElement executable) { System.out.println("Looking at executable " + executable); - List list = expectations.get(executable.getSimpleName().toString()); - if (list == null) { + Elements.Origin[] origins = expectations.get(executable.getSimpleName().toString()); + if (origins == null) { System.out.println("ignoring this executable due to missing expectations"); return false; } @@ -96,11 +92,26 @@ private boolean checkExecutable(Map> expectations, for (int i = 0; i < parameters.size(); i++) { VariableElement parameter = parameters.get(i); Elements.Origin origin = eltUtils.getOrigin(parameter); - if (origin != list.get(i)) { - System.err.println("ERROR: Wrong origin for " + executable + ". Expected: " + list.get(i) + " but got " + origin + " at index " + i); + if (origin != origins[i]) { + System.err.println("ERROR: Wrong origin for " + executable + ". Expected: " + origins[i] + " but got " + origin + " at index " + i); hasError = true; } } return hasError; } + + // the valueOf(String) method has one mandated parameter + @ExpectedOrigin(method = "valueOf", origins = {Elements.Origin.MANDATED}) + enum MyEnum {} + + // the parameters of a compact record constructor are mandated + @ExpectedOrigin(method = "", origins = {Elements.Origin.MANDATED, Elements.Origin.MANDATED}) + record MyRecord(int a, Object b) { + MyRecord {} + } + + @interface ExpectedOrigin { + String method(); + Elements.Origin[] origins(); + } } From 43780935e1dcda6c6734fa87fcafaea1fe5a572b Mon Sep 17 00:00:00 2001 From: SirYwell Date: Mon, 9 Jan 2023 08:16:47 +0100 Subject: [PATCH 20/24] Update copyright year --- .../src/classes/build/tools/symbolgenerator/CreateSymbols.java | 2 +- .../share/classes/com/sun/tools/javac/jvm/ClassReader.java | 2 +- .../share/classes/com/sun/tools/javac/jvm/ClassWriter.java | 2 +- .../share/classes/com/sun/tools/javac/parser/JavacParser.java | 2 +- .../reflect/AccessFlag/RequiredMethodParameterFlagTest.java | 2 +- .../tools/javac/RequiredParameterFlags/ImplicitParameters.java | 2 +- .../typeAnnotations/classfile/AnnotatedExtendsTest.java | 2 +- .../elements/MethodParameters/ImplicitParametersProcessor.java | 2 +- test/langtools/tools/javap/AnnoTest.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 8f8c5933b4e44..7ac3dc6fdac63 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 4d0e9eae2d8a9..6a55154aad6e3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index fe9e9818ca865..fed7f61ec38bc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 77e97bcf3e240..16521b32e84db 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java index 9999f364bd9ba..6705dc8f021d9 100644 --- a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index 01147a6f6c77c..fcd0fb7987ca1 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java index ba4d4938c8f29..450e2b5956a54 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java index 7d12edb84d769..526aa53de1e81 100644 --- a/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java +++ b/test/langtools/tools/javac/processing/model/util/elements/MethodParameters/ImplicitParametersProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/langtools/tools/javap/AnnoTest.java b/test/langtools/tools/javap/AnnoTest.java index b92411c9e8f19..e7bf407491559 100644 --- a/test/langtools/tools/javap/AnnoTest.java +++ b/test/langtools/tools/javap/AnnoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 6183083e4e444e9d53b382fb5c203f5ff993fdd8 Mon Sep 17 00:00:00 2001 From: liach Date: Wed, 22 Mar 2023 10:26:06 -0500 Subject: [PATCH 21/24] Updated RequiredMethodParameterFlagTest, checks against Local classes as well --- .../RequiredMethodParameterFlagTest.java | 118 +++++++++++------- 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java index 6705dc8f021d9..70b926d7f6b10 100644 --- a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -21,68 +21,75 @@ * questions. */ +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + import java.lang.reflect.AccessFlag; +import java.lang.reflect.Executable; import java.lang.reflect.Parameter; +import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 8292275 * @summary Test required flags on parameters * @compile RequiredMethodParameterFlagTest.java - * @run main RequiredMethodParameterFlagTest + * @run junit RequiredMethodParameterFlagTest */ -public class RequiredMethodParameterFlagTest { - public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { - boolean errors = false; +class RequiredMethodParameterFlagTest { + + private static final Set CHECKED_FLAGS = Set.of(AccessFlag.MANDATED, AccessFlag.SYNTHETIC); + + static Stream testCases() throws ReflectiveOperationException { Set mandated = Set.of(AccessFlag.MANDATED); Set synthetic = Set.of(AccessFlag.SYNTHETIC); - // test for implicit parameters - Parameter[] parameters = Inner.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(Set.of(), parameters[1]); - - parameters = findAnonymous().getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(Set.of(), parameters[1]); - - parameters = MyEnum.class.getDeclaredMethod("valueOf", String.class).getParameters(); - errors |= assertFlags(mandated, parameters[0]); - - parameters = MyRecord.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(mandated, parameters[0]); - errors |= assertFlags(mandated, parameters[1]); - - // test for synthetic parameters - // assuming javac creates two synthetic parameters corresponding to Enum(String name, int ordinal) - parameters = MyEnum.class.getDeclaredConstructors()[0].getParameters(); - errors |= assertFlags(synthetic, parameters[0]); - errors |= assertFlags(synthetic, parameters[1]); - errors |= assertFlags(Set.of(), parameters[2]); - errors |= assertFlags(Set.of(), parameters[3]); - - if (errors) { - throw new AssertionError(); - } - } - // returns true on error - private static boolean assertFlags(Set flags, Parameter parameter) { - Set accessFlags = parameter.accessFlags(); - if (!accessFlags.containsAll(flags)) { - System.err.println("Required flags not present"); - System.err.println("Required: " + flags); - System.err.println("Actual: " + accessFlags); - return true; - } - return false; + return Stream.of( + // test for implicit parameters + // inner class + Arguments.of(Inner.class.getDeclaredConstructors()[0], + List.of(mandated, Set.of())), + // anonymous class + Arguments.of(Class.forName("RequiredMethodParameterFlagTest$1") + .getDeclaredConstructors()[0], + List.of(mandated, Set.of(), Set.of())), + // enum class + Arguments.of(MyEnum.class.getDeclaredMethod("valueOf", String.class), + List.of(mandated)), + // record class + Arguments.of(MyRecord.class.getDeclaredConstructors()[0], + List.of(mandated, mandated)), + // local class + Arguments.of(Class.forName("RequiredMethodParameterFlagTest$1Task") + .getDeclaredConstructors()[0], + List.of(mandated, Set.of(), synthetic)), + // test for synthetic parameters + // assuming javac creates two synthetic parameters corresponding to + // Enum(String name, int ordinal) + Arguments.of(MyEnum.class.getDeclaredConstructors()[0], + List.of(synthetic, synthetic, Set.of(), Set.of())) + ); } - private static Class findAnonymous() { - try { - return Class.forName("RequiredMethodParameterFlagTest$1"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Anonymous class missing"); + @ParameterizedTest + @MethodSource("testCases") + public void check(Executable method, List> paramFlags) { + Parameter[] parameters = method.getParameters(); + assertEquals(paramFlags.size(), parameters.length, () -> "Parameter count of " + method); + + for (int i = 0; i < parameters.length; i++) { + Set expected = new HashSet<>(paramFlags.get(i)); + expected.retainAll(CHECKED_FLAGS); + Set found = new HashSet<>(parameters[i].accessFlags()); + found.retainAll(CHECKED_FLAGS); + final int index = i; + assertEquals(expected, found, () -> "Parameter " + index + " in " + method); } } @@ -92,6 +99,23 @@ public Inner(Inner notMandated) {} Inner anonymousInner = this.new Inner(null) {}; + private void instanceMethod(int i) { + class Task implements Runnable { + final int j; + + Task(int j) { + this.j = j; + } + + @Override + public void run() { + System.out.println(RequiredMethodParameterFlagTest.this.toString() + (i * j)); + } + } + + new Task(5).run(); + } + enum MyEnum { ; MyEnum(String s, int i) {} From 9879b820d0c9bfcae00c5e41b585032130c62254 Mon Sep 17 00:00:00 2001 From: liach Date: Wed, 22 Mar 2023 17:43:51 +0100 Subject: [PATCH 22/24] Parity for the parameter flag tests in javac and reflection --- .../RequiredMethodParameterFlagTest.java | 24 +++-- .../ImplicitParameters.java | 90 +++++++++++++++---- 2 files changed, 89 insertions(+), 25 deletions(-) diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java index 70b926d7f6b10..c25381b2888bd 100644 --- a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -53,26 +53,30 @@ static Stream testCases() throws ReflectiveOperationException { return Stream.of( // test for implicit parameters // inner class - Arguments.of(Inner.class.getDeclaredConstructors()[0], + Arguments.of(Outer.Inner.class.getDeclaredConstructors()[0], List.of(mandated, Set.of())), - // anonymous class - Arguments.of(Class.forName("RequiredMethodParameterFlagTest$1") + // anonymous class extending an inner class + Arguments.of(Class.forName("Outer$1") .getDeclaredConstructors()[0], List.of(mandated, Set.of(), Set.of())), + // anonymous class + Arguments.of(Class.forName("Outer$2") + .getDeclaredConstructors()[0], + List.of(mandated)), // enum class - Arguments.of(MyEnum.class.getDeclaredMethod("valueOf", String.class), + Arguments.of(Outer.MyEnum.class.getDeclaredMethod("valueOf", String.class), List.of(mandated)), // record class - Arguments.of(MyRecord.class.getDeclaredConstructors()[0], + Arguments.of(Outer.MyRecord.class.getDeclaredConstructors()[0], List.of(mandated, mandated)), // local class - Arguments.of(Class.forName("RequiredMethodParameterFlagTest$1Task") + Arguments.of(Class.forName("Outer$1Task") .getDeclaredConstructors()[0], List.of(mandated, Set.of(), synthetic)), // test for synthetic parameters // assuming javac creates two synthetic parameters corresponding to // Enum(String name, int ordinal) - Arguments.of(MyEnum.class.getDeclaredConstructors()[0], + Arguments.of(Outer.MyEnum.class.getDeclaredConstructors()[0], List.of(synthetic, synthetic, Set.of(), Set.of())) ); } @@ -92,13 +96,17 @@ public void check(Executable method, List> paramFlags) { assertEquals(expected, found, () -> "Parameter " + index + " in " + method); } } +} +class Outer { class Inner { public Inner(Inner notMandated) {} } Inner anonymousInner = this.new Inner(null) {}; + Object anonymous = new Object() {}; + private void instanceMethod(int i) { class Task implements Runnable { final int j; @@ -109,7 +117,7 @@ class Task implements Runnable { @Override public void run() { - System.out.println(RequiredMethodParameterFlagTest.this.toString() + (i * j)); + System.out.println(Outer.this.toString() + (i * j)); } } diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index fcd0fb7987ca1..4a711a93d67ba 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -46,11 +46,14 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.constant.ConstantDescs; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; public class ImplicitParameters extends TestRunner { + private static final int CHECKED_FLAGS = Flags.MANDATED | Flags.SYNTHETIC; + public ImplicitParameters() { super(System.err); } @@ -75,7 +78,29 @@ public Inner(Inner notMandated) {} Inner anonymousInner = this.new Inner(null) {}; - enum MyEnum {} + Object anonymous = new Object() {}; + + private void instanceMethod(int i) { + class Task implements Runnable { + final int j; + + Task(int j) { + this.j = j; + } + + @Override + public void run() { + System.out.println(Outer.this.toString() + (i * j)); + } + } + + new Task(5).run(); + } + + enum MyEnum { + ; + MyEnum(String s, int i) {} + } record MyRecord(int a, Object b) { MyRecord {} @@ -111,21 +136,30 @@ private ClassFile readClassFile(Path classes, Method method) { @Test @ClassName("Inner") public void testInnerClassConstructor(ClassFile classFile) { - MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); - Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); - MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; - Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); - Assert.check((table[1].flags & Flags.MANDATED) == 0, "mandated flag must not be set for explicit parameter"); + checkParameters(classFile.methods[0], Flags.MANDATED, 0); + } + + @Test + @ClassName("1Task") + public void testLocalClassConstructor(ClassFile classFile) throws ConstantPoolException { + for (com.sun.tools.classfile.Method method : classFile.methods) { + if (method.getName(classFile.constant_pool).equals(ConstantDescs.INIT_NAME)) { + checkParameters(method, Flags.MANDATED, 0, Flags.SYNTHETIC); + break; + } + } } @Test @ClassName("1") public void testAnonymousClassExtendingInnerClassConstructor(ClassFile classFile) { - MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); - Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); - MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; - Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); - Assert.check((table[1].flags & Flags.MANDATED) == 0, "mandated flag must not be set for explicit parameter"); + checkParameters(classFile.methods[0], Flags.MANDATED, 0, 0); + } + + @Test + @ClassName("2") + public void testAnonymousClassConstructor(ClassFile classFile) { + checkParameters(classFile.methods[0], Flags.MANDATED); } @Test @@ -133,10 +167,19 @@ public void testAnonymousClassExtendingInnerClassConstructor(ClassFile classFile public void testValueOfInEnum(ClassFile classFile) throws ConstantPoolException { for (com.sun.tools.classfile.Method method : classFile.methods) { if (method.getName(classFile.constant_pool).equals("valueOf")) { - MethodParameters_attribute methodParameters = (MethodParameters_attribute) method.attributes.get("MethodParameters"); - Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); - MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; - Assert.check((table[0].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + checkParameters(method, Flags.MANDATED); + break; + } + } + } + + @Test + @ClassName("MyEnum") + public void testEnumClassConstructor(ClassFile classFile) throws ConstantPoolException { + for (com.sun.tools.classfile.Method method : classFile.methods) { + if (method.getName(classFile.constant_pool).equals(ConstantDescs.INIT_NAME)) { + checkParameters(method, Flags.SYNTHETIC, Flags.SYNTHETIC, 0, 0); + break; } } } @@ -144,11 +187,24 @@ public void testValueOfInEnum(ClassFile classFile) throws ConstantPoolException @Test @ClassName("MyRecord") public void testCompactConstructor(ClassFile classFile) { - MethodParameters_attribute methodParameters = (MethodParameters_attribute) classFile.methods[0].attributes.get("MethodParameters"); + checkParameters(classFile.methods[0], Flags.MANDATED, Flags.MANDATED); + } + + private void checkParameters(com.sun.tools.classfile.Method method, int... parametersFlags) { + MethodParameters_attribute methodParameters = (MethodParameters_attribute) method.attributes.get("MethodParameters"); Assert.checkNonNull(methodParameters, "MethodParameters attribute must be present"); MethodParameters_attribute.Entry[] table = methodParameters.method_parameter_table; + Assert.check(table.length == parametersFlags.length, () -> "Expected " + parametersFlags.length + + " MethodParameters entries, found " + table.length); for (int i = 0; i < methodParameters.method_parameter_table_length; i++) { - Assert.check((table[i].flags & Flags.MANDATED) != 0, "mandated flag must be set for implicit parameter"); + int foundFlags = table[i].flags & CHECKED_FLAGS; + int desiredFlags = parametersFlags[i] & CHECKED_FLAGS; + Assert.check(foundFlags == desiredFlags, () -> "Expected mandated and synthethic flags to be " + + convertFlags(desiredFlags) + ", found " + convertFlags(foundFlags)); } } + + private static String convertFlags(int flags) { + return ((flags & Flags.MANDATED) == Flags.MANDATED) + " and " + ((flags & Flags.SYNTHETIC) == Flags.SYNTHETIC); + } } From c42e9f36b4dd1efce6ce547cf6a47744feb0e23f Mon Sep 17 00:00:00 2001 From: liach Date: Thu, 23 Mar 2023 02:59:24 -0500 Subject: [PATCH 23/24] Update tests --- .../AccessFlag/RequiredMethodParameterFlagTest.java | 3 ++- .../javac/RequiredParameterFlags/ImplicitParameters.java | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java index c25381b2888bd..7343ccc82b858 100644 --- a/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java +++ b/test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java @@ -83,7 +83,7 @@ static Stream testCases() throws ReflectiveOperationException { @ParameterizedTest @MethodSource("testCases") - public void check(Executable method, List> paramFlags) { + void check(Executable method, List> paramFlags) { Parameter[] parameters = method.getParameters(); assertEquals(paramFlags.size(), parameters.length, () -> "Parameter count of " + method); @@ -98,6 +98,7 @@ public void check(Executable method, List> paramFlags) { } } +// keep this in sync with test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java class Outer { class Inner { public Inner(Inner notMandated) {} diff --git a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java index 4a711a93d67ba..3683ae4251080 100644 --- a/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java +++ b/test/langtools/tools/javac/RequiredParameterFlags/ImplicitParameters.java @@ -53,6 +53,7 @@ public class ImplicitParameters extends TestRunner { private static final int CHECKED_FLAGS = Flags.MANDATED | Flags.SYNTHETIC; + private static final int NO_FLAGS = 0; public ImplicitParameters() { super(System.err); @@ -70,6 +71,7 @@ protected void runTests() throws Exception { } private void compileClasses(Path base) throws IOException { + // Keep this in sync with test/jdk/java/lang/reflect/AccessFlag/RequiredMethodParameterFlagTest.java String outer = """ class Outer { class Inner { @@ -144,7 +146,7 @@ public void testInnerClassConstructor(ClassFile classFile) { public void testLocalClassConstructor(ClassFile classFile) throws ConstantPoolException { for (com.sun.tools.classfile.Method method : classFile.methods) { if (method.getName(classFile.constant_pool).equals(ConstantDescs.INIT_NAME)) { - checkParameters(method, Flags.MANDATED, 0, Flags.SYNTHETIC); + checkParameters(method, Flags.MANDATED, NO_FLAGS, Flags.SYNTHETIC); break; } } @@ -153,7 +155,7 @@ public void testLocalClassConstructor(ClassFile classFile) throws ConstantPoolEx @Test @ClassName("1") public void testAnonymousClassExtendingInnerClassConstructor(ClassFile classFile) { - checkParameters(classFile.methods[0], Flags.MANDATED, 0, 0); + checkParameters(classFile.methods[0], Flags.MANDATED, NO_FLAGS, NO_FLAGS); } @Test @@ -178,7 +180,7 @@ public void testValueOfInEnum(ClassFile classFile) throws ConstantPoolException public void testEnumClassConstructor(ClassFile classFile) throws ConstantPoolException { for (com.sun.tools.classfile.Method method : classFile.methods) { if (method.getName(classFile.constant_pool).equals(ConstantDescs.INIT_NAME)) { - checkParameters(method, Flags.SYNTHETIC, Flags.SYNTHETIC, 0, 0); + checkParameters(method, Flags.SYNTHETIC, Flags.SYNTHETIC, NO_FLAGS, NO_FLAGS); break; } } From 400e1ec9598e027485e8f4088701229bc7d30467 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 29 Apr 2023 20:42:27 +0200 Subject: [PATCH 24/24] Use ternary operator Co-authored-by: liach <7806504+liach@users.noreply.github.com> --- .../classes/build/tools/symbolgenerator/CreateSymbols.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 7ac3dc6fdac63..03cb62429c17c 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -2384,10 +2384,8 @@ private boolean readAttribute(ClassFile cf, FeatureDescription feature, Attribut MethodDescription method = (MethodDescription) feature; method.methodParameters = new ArrayList<>(); for (MethodParameters_attribute.Entry e : params.method_parameter_table) { - String name = null; - if (e.name_index != 0) { - name = cf.constant_pool.getUTF8Value(e.name_index); - } + String name = e.name_index == 0 ? null + : cf.constant_pool.getUTF8Value(e.name_index); MethodDescription.MethodParam param = new MethodDescription.MethodParam(e.flags, name); method.methodParameters.add(param);