Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/test/tools/javac/6889255/T6889255.java
38813 views
1
/*
2
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 6889255
27
* @summary ClassReader does not read parameter names correctly
28
*/
29
30
import java.io.*;
31
import java.util.*;
32
import javax.tools.StandardLocation;
33
import com.sun.tools.javac.code.Flags;
34
import com.sun.tools.javac.code.Kinds;
35
import com.sun.tools.javac.code.Scope;
36
import com.sun.tools.javac.code.Symbol.*;
37
import com.sun.tools.javac.code.Type;
38
import com.sun.tools.javac.code.Type.ClassType;
39
import com.sun.tools.javac.code.TypeTag;
40
import com.sun.tools.javac.file.JavacFileManager;
41
import com.sun.tools.javac.jvm.ClassReader;
42
import com.sun.tools.javac.util.Context;
43
import com.sun.tools.javac.util.Names;
44
45
public class T6889255 {
46
boolean testInterfaces = true;
47
boolean testSyntheticMethods = true;
48
49
// The following enums control the generation of the test methods to be compiled.
50
enum GenericKind {
51
NOT_GENERIC,
52
GENERIC
53
};
54
55
enum ClassKind {
56
CLASS("Clss"),
57
INTERFACE("Intf"),
58
ENUM("Enum");
59
final String base;
60
ClassKind(String base) { this.base = base; }
61
};
62
63
enum NestedKind {
64
/** Declare methods inside the outermost container. */
65
NONE,
66
/** Declare methods inside a container with a 'static' modifier. */
67
NESTED,
68
/** Declare methods inside a container without a 'static' modifier. */
69
INNER,
70
/** Declare methods inside a local class in an initializer. */
71
INIT_LOCAL,
72
/** Declare methods inside an anonymous class in an initializer. */
73
INIT_ANON,
74
/** Declare methods inside a local class in a method. */
75
METHOD_LOCAL,
76
/** Declare methods inside an anonymous class in a method. */
77
METHOD_ANON
78
};
79
80
enum MethodKind {
81
ABSTRACT,
82
CONSTRUCTOR,
83
METHOD,
84
STATIC_METHOD,
85
BRIDGE_METHOD
86
};
87
88
enum FinalKind {
89
/** Method body does not reference external final variables. */
90
NO_FINAL,
91
/** Method body references external final variables. */
92
USE_FINAL
93
};
94
95
public static void main(String... args) throws Exception {
96
new T6889255().run();
97
}
98
99
void run() throws Exception {
100
genTest();
101
102
test("no-args", false);
103
test("g", true, "-g");
104
105
if (errors > 0)
106
throw new Exception(errors + " errors found");
107
}
108
109
/**
110
* Create a file containing lots of method definitions to be tested.
111
* There are 3 sets of nested loops that generate the methods.
112
* 1. The outermost set declares [generic] (class | interface | enum)
113
* 2. The middle set declares [(nested | inner | anon | local)] class
114
* 3. The innermost set declares
115
* [generic] (constructor|method|static-method|bridge-method) [using final variables in outer scope]
116
* Invalid combinations are filtered out.
117
*/
118
void genTest() throws Exception {
119
BufferedWriter out = new BufferedWriter(new FileWriter("Test.java"));
120
121
// This interface is used to force bridge methods to be generated, by
122
// implementing its methods with subtypes of Object
123
out.write("interface Base {\n");
124
out.write(" Object base_m1(int i1);\n");
125
out.write(" Object base_m2(int i1);\n");
126
out.write("}\n");
127
128
int outerNum = 0;
129
// Outermost set of loops, to generate a top level container
130
for (GenericKind outerGenericKind: GenericKind.values()) {
131
for (ClassKind outerClassKind: ClassKind.values()) {
132
if (outerGenericKind == GenericKind.GENERIC && outerClassKind == ClassKind.ENUM)
133
continue;
134
String outerClassName = outerClassKind.base + (outerNum++);
135
String outerTypeArg = outerClassKind.toString().charAt(0) + "T";
136
if (outerClassKind == ClassKind.CLASS)
137
out.write("abstract ");
138
out.write(outerClassKind.toString().toLowerCase() + " " + outerClassName);
139
if (outerGenericKind == GenericKind.GENERIC)
140
out.write("<" + outerTypeArg + ">");
141
if (outerClassKind == ClassKind.INTERFACE)
142
out.write(" extends Base");
143
else
144
out.write(" implements Base");
145
out.write(" {\n");
146
if (outerClassKind == ClassKind.ENUM) {
147
out.write(" E1(0,0,0), E2(0,0,0), E3(0,0,0);\n");
148
out.write(" " + outerClassName + "(int i1, int i2, int i3) { }\n");
149
}
150
// Middle set of loops, to generate an optional nested container
151
int nestedNum = 0;
152
int methodNum = 0;
153
for (GenericKind nestedGenericKind: GenericKind.values()) {
154
nextNestedKind:
155
for (NestedKind nestedKind: NestedKind.values()) {
156
// if the nested kind is none, there is no point iterating over all
157
// nested generic kinds, so arbitarily limit it to just one kind
158
if (nestedKind == NestedKind.NONE && nestedGenericKind != GenericKind.NOT_GENERIC)
159
continue;
160
if ((nestedKind == NestedKind.METHOD_ANON || nestedKind == NestedKind.INIT_ANON)
161
&& nestedGenericKind == GenericKind.GENERIC)
162
continue;
163
String indent = " ";
164
boolean haveFinal = false;
165
switch (nestedKind) {
166
case METHOD_ANON: case METHOD_LOCAL:
167
if (outerClassKind == ClassKind.INTERFACE)
168
continue nextNestedKind;
169
out.write(indent + "void m" + + (nestedNum++) + "() {\n");
170
indent += " ";
171
out.write(indent + "final int fi1 = 0;\n");
172
haveFinal = true;
173
break;
174
case INIT_ANON: case INIT_LOCAL:
175
if (outerClassKind == ClassKind.INTERFACE)
176
continue nextNestedKind;
177
out.write(indent + "{\n");
178
indent += " ";
179
break;
180
}
181
for (ClassKind nestedClassKind: ClassKind.values()) {
182
if ((nestedGenericKind == GenericKind.GENERIC)
183
&& (nestedClassKind == ClassKind.ENUM))
184
continue;
185
if ((nestedKind == NestedKind.METHOD_ANON || nestedKind == NestedKind.METHOD_LOCAL
186
|| nestedKind == NestedKind.INIT_ANON || nestedKind == NestedKind.INIT_LOCAL)
187
&& nestedClassKind != ClassKind.CLASS)
188
continue;
189
// if the nested kind is none, there is no point iterating over all
190
// nested class kinds, so arbitarily limit it to just one kind
191
if (nestedKind == NestedKind.NONE && nestedClassKind != ClassKind.CLASS)
192
continue;
193
194
ClassKind methodClassKind;
195
String methodClassName;
196
boolean allowAbstractMethods;
197
boolean allowStaticMethods;
198
switch (nestedKind) {
199
case NONE:
200
methodClassKind = outerClassKind;
201
methodClassName = outerClassName;
202
allowAbstractMethods = (outerClassKind == ClassKind.CLASS);
203
allowStaticMethods = (outerClassKind != ClassKind.INTERFACE);
204
break;
205
case METHOD_ANON:
206
case INIT_ANON:
207
out.write(indent + "new Base() {\n");
208
indent += " ";
209
methodClassKind = ClassKind.CLASS;
210
methodClassName = null;
211
allowAbstractMethods = false;
212
allowStaticMethods = false;
213
break;
214
default: { // INNER, NESTED, LOCAL
215
String nestedClassName = "N" + nestedClassKind.base + (nestedNum++);
216
String nestedTypeArg = nestedClassKind.toString().charAt(0) + "T";
217
out.write(indent);
218
if (nestedKind == NestedKind.NESTED)
219
out.write("static ");
220
if (nestedClassKind == ClassKind.CLASS)
221
out.write("abstract ");
222
out.write(nestedClassKind.toString().toLowerCase() + " " + nestedClassName);
223
if (nestedGenericKind == GenericKind.GENERIC)
224
out.write("<" + nestedTypeArg + ">");
225
if (nestedClassKind == ClassKind.INTERFACE)
226
out.write(" extends Base ");
227
else
228
out.write(" implements Base ");
229
out.write(" {\n");
230
indent += " ";
231
if (nestedClassKind == ClassKind.ENUM) {
232
out.write(indent + "E1(0,0,0), E2(0,0,0), E3(0,0,0);\n");
233
out.write(indent + nestedClassName + "(int i1, int i2, int i3) { }\n");
234
}
235
methodClassKind = nestedClassKind;
236
methodClassName = nestedClassName;
237
allowAbstractMethods = (nestedClassKind == ClassKind.CLASS);
238
allowStaticMethods = (nestedKind == NestedKind.NESTED && nestedClassKind != ClassKind.INTERFACE);
239
break;
240
}
241
}
242
243
// Innermost loops, to generate methods
244
for (GenericKind methodGenericKind: GenericKind.values()) {
245
for (FinalKind finalKind: FinalKind.values()) {
246
for (MethodKind methodKind: MethodKind.values()) {
247
// out.write("// " + outerGenericKind
248
// + " " + outerClassKind
249
// + " " + nestedKind
250
// + " " + nestedGenericKind
251
// + " " + nestedClassKind
252
// + " " + methodGenericKind
253
// + " " + finalKind
254
// + " " + methodKind
255
// + "\n");
256
switch (methodKind) {
257
case CONSTRUCTOR:
258
if (nestedKind == NestedKind.METHOD_ANON || nestedKind == NestedKind.INIT_ANON)
259
break;
260
if (methodClassKind != ClassKind.CLASS)
261
break;
262
if (finalKind == FinalKind.USE_FINAL && !haveFinal)
263
break;
264
out.write(indent);
265
if (methodGenericKind == GenericKind.GENERIC) {
266
out.write("<CT> " + methodClassName + "(CT c1, CT c2");
267
} else {
268
out.write(methodClassName + "(boolean b1, char c2");
269
}
270
if (finalKind == FinalKind.USE_FINAL) {
271
// add a dummy parameter to avoid duplicate declaration
272
out.write(", int i3) { int i = fi1; }\n");
273
} else
274
out.write(") { }\n");
275
break;
276
case ABSTRACT:
277
if (!allowAbstractMethods)
278
continue;
279
// fallthrough
280
case METHOD:
281
if (finalKind == FinalKind.USE_FINAL && !haveFinal)
282
break;
283
out.write(indent);
284
if (methodKind == MethodKind.ABSTRACT)
285
out.write("abstract ");
286
if (methodGenericKind == GenericKind.GENERIC)
287
out.write("<MT> ");
288
out.write("void m" + (methodNum++) + "(int i1, long l2, float f3)");
289
if (methodKind == MethodKind.ABSTRACT || methodClassKind == ClassKind.INTERFACE)
290
out.write(";\n");
291
else {
292
out.write(" {");
293
if (finalKind == FinalKind.USE_FINAL)
294
out.write(" int i = fi1;");
295
out.write(" }\n");
296
}
297
break;
298
case BRIDGE_METHOD:
299
if (methodGenericKind == GenericKind.GENERIC)
300
break;
301
out.write(indent);
302
// methods Base.base_m1 and Base.base_m2 are declared for the
303
// benefit of bridge methods. They need to be implemented
304
// whether or not a final variable is used.
305
String methodName = (finalKind == FinalKind.NO_FINAL ? "base_m1" : "base_m2");
306
out.write("public String " + methodName + "(int i1)");
307
if (methodClassKind == ClassKind.INTERFACE)
308
out.write(";\n");
309
else {
310
out.write(" {");
311
if (finalKind == FinalKind.USE_FINAL && haveFinal)
312
out.write(" int i = fi1;");
313
out.write(" return null; }\n");
314
}
315
break;
316
case STATIC_METHOD:
317
if (!allowStaticMethods)
318
break;
319
if (finalKind == FinalKind.USE_FINAL && !haveFinal)
320
break;
321
out.write(indent + "static ");
322
if (methodGenericKind == GenericKind.GENERIC)
323
out.write("<MT> ");
324
out.write("void m" + (methodNum++) + "(int i1, long l2, float f3) {");
325
if (finalKind == FinalKind.USE_FINAL)
326
out.write(" int i = fi1;");
327
out.write(" }\n");
328
break;
329
}
330
331
}
332
}
333
}
334
if (nestedKind != NestedKind.NONE) {
335
indent = indent.substring(0, indent.length() - 4);
336
out.write(indent + "};\n");
337
}
338
}
339
switch (nestedKind) {
340
case METHOD_ANON: case METHOD_LOCAL:
341
case INIT_ANON: case INIT_LOCAL:
342
indent = indent.substring(0, indent.length() - 4);
343
out.write(indent + "}\n\n");
344
}
345
}
346
}
347
out.write("}\n\n");
348
}
349
}
350
out.close();
351
}
352
353
354
void test(String testName, boolean expectNames, String... opts) throws Exception {
355
System.err.println("Test " + testName
356
+ ": expectNames:" + expectNames
357
+ " javacOpts:" + Arrays.asList(opts));
358
359
File outDir = new File(testName);
360
outDir.mkdirs();
361
compile(outDir, opts);
362
363
Context ctx = new Context();
364
JavacFileManager fm = new JavacFileManager(ctx, true, null);
365
fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(outDir));
366
ClassReader cr = ClassReader.instance(ctx);
367
cr.saveParameterNames = true;
368
Names names = Names.instance(ctx);
369
370
Set<String> classes = getTopLevelClasses(outDir);
371
Deque<String> work = new LinkedList<String>(classes);
372
String classname;
373
while ((classname = work.poll()) != null) {
374
System.err.println("Checking class " + classname);
375
ClassSymbol sym = cr.enterClass(names.table.fromString(classname));
376
sym.complete();
377
378
if ((sym.flags() & Flags.INTERFACE) != 0 && !testInterfaces)
379
continue;
380
381
for (Scope.Entry e = sym.members_field.elems; e != null; e = e.sibling) {
382
System.err.println("Checking member " + e.sym);
383
switch (e.sym.kind) {
384
case Kinds.TYP: {
385
String name = e.sym.flatName().toString();
386
if (!classes.contains(name)) {
387
classes.add(name);
388
work.add(name);
389
}
390
break;
391
}
392
case Kinds.MTH:
393
verify((MethodSymbol) e.sym, expectNames);
394
break;
395
}
396
397
}
398
}
399
}
400
401
void verify(MethodSymbol m, boolean expectNames) {
402
if ((m.flags() & Flags.SYNTHETIC) != 0 && !testSyntheticMethods)
403
return;
404
405
//System.err.println("verify: " + m.params());
406
int i = 1;
407
for (VarSymbol v: m.params()) {
408
String expectName;
409
if (expectNames)
410
expectName = getExpectedName(v, i);
411
else
412
expectName = "arg" + (i - 1);
413
checkEqual(expectName, v.name.toString());
414
i++;
415
}
416
}
417
418
String getExpectedName(VarSymbol v, int i) {
419
// special cases:
420
// synthetic method
421
if (((v.owner.owner.flags() & Flags.ENUM) != 0)
422
&& v.owner.name.toString().equals("valueOf"))
423
return "name";
424
// interfaces don't have saved names
425
// -- no Code attribute for the LocalVariableTable attribute
426
if ((v.owner.owner.flags() & Flags.INTERFACE) != 0)
427
return "arg" + (i - 1);
428
// abstract methods don't have saved names
429
// -- no Code attribute for the LocalVariableTable attribute
430
if ((v.owner.flags() & Flags.ABSTRACT) != 0)
431
return "arg" + (i - 1);
432
// bridge methods use argN. No LVT for them anymore
433
if ((v.owner.flags() & Flags.BRIDGE) != 0)
434
return "arg" + (i - 1);
435
436
// The rest of this method assumes the local conventions in the test program
437
Type t = v.type;
438
String s;
439
if (t.hasTag(TypeTag.CLASS))
440
s = ((ClassType) t).tsym.name.toString();
441
else
442
s = t.toString();
443
return String.valueOf(Character.toLowerCase(s.charAt(0))) + i;
444
}
445
446
void compile(File outDir, String... opts) throws Exception {
447
//File testSrc = new File(System.getProperty("test.src"), ".");
448
List<String> args = new ArrayList<String>();
449
args.add("-d");
450
args.add(outDir.getPath());
451
args.addAll(Arrays.asList(opts));
452
//args.add(new File(testSrc, "Test.java").getPath());
453
args.add("Test.java");
454
StringWriter sw = new StringWriter();
455
PrintWriter pw = new PrintWriter(sw);
456
int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
457
pw.close();
458
if (rc != 0) {
459
System.err.println(sw.toString());
460
throw new Exception("compilation failed unexpectedly");
461
}
462
}
463
464
Set<String> getTopLevelClasses(File outDir) {
465
Set<String> classes = new HashSet<String>();
466
for (String f: outDir.list()) {
467
if (f.endsWith(".class") && !f.contains("$"))
468
classes.add(f.replace(".class", ""));
469
}
470
return classes;
471
}
472
473
void checkEqual(String expect, String found) {
474
if (!expect.equals(found))
475
error("mismatch: expected:" + expect + " found:" + found);
476
}
477
478
void error(String msg) {
479
System.err.println(msg);
480
errors++;
481
throw new Error();
482
}
483
484
int errors;
485
}
486
487