Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/Environment.java
38918 views
1
/*
2
* Copyright (c) 1994, 2003, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.tools.java;
27
28
import java.util.Stack;
29
import java.io.IOException;
30
import sun.tools.tree.Context;
31
//JCOV
32
import java.io.File;
33
//end JCOV
34
35
/**
36
* This class defines the environment for a compilation.
37
* It is used to load classes, resolve class names and
38
* report errors. It is an abstract class, a subclass
39
* must define implementations for some of the functions.<p>
40
*
41
* An environment has a source object associated with it.
42
* This is the thing against which errors are reported, it
43
* is usually a file name, a field or a class.<p>
44
*
45
* Environments can be nested to change the source object.<p>
46
*
47
* WARNING: The contents of this source file are not part of any
48
* supported API. Code that depends on them does so at its own risk:
49
* they are subject to change or removal without notice.
50
*
51
* @author Arthur van Hoff
52
*/
53
54
public class Environment implements Constants {
55
/**
56
* The actual environment to which everything is forwarded.
57
*/
58
Environment env;
59
60
/**
61
* External character encoding name
62
*/
63
String encoding;
64
65
/**
66
* The object that is currently being parsed/compiled.
67
* It is either a file name (String) or a field (MemberDefinition)
68
* or a class (ClassDeclaration or ClassDefinition).
69
*/
70
Object source;
71
72
public Environment(Environment env, Object source) {
73
if (env != null && env.env != null && env.getClass() == this.getClass())
74
env = env.env; // a small optimization
75
this.env = env;
76
this.source = source;
77
}
78
public Environment() {
79
this(null, null);
80
}
81
82
/**
83
* Tells whether an Identifier refers to a package which should be
84
* exempt from the "exists" check in Imports#resolve().
85
*/
86
public boolean isExemptPackage(Identifier id) {
87
return env.isExemptPackage(id);
88
}
89
90
/**
91
* Return a class declaration given a fully qualified class name.
92
*/
93
public ClassDeclaration getClassDeclaration(Identifier nm) {
94
return env.getClassDeclaration(nm);
95
}
96
97
/**
98
* Return a class definition given a fully qualified class name.
99
* <p>
100
* Should be called only with 'internal' class names, i.e., the result
101
* of a call to 'resolveName' or a synthetic class name.
102
*/
103
public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound {
104
if (nm.isInner()) {
105
ClassDefinition c = getClassDefinition(nm.getTopName());
106
Identifier tail = nm.getFlatName();
107
walkTail:
108
while (tail.isQualified()) {
109
tail = tail.getTail();
110
Identifier head = tail.getHead();
111
//System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
112
String hname = head.toString();
113
// If the name is of the form 'ClassName.N$localName', where N is
114
// a number, the field 'N$localName' may not necessarily be a member
115
// of the class named by 'ClassName', but might be a member of some
116
// inaccessible class contained within it. We use 'getLocalClass'
117
// to do the lookup in this case. This is part of a fix for bugid
118
// 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'.
119
// This should also work for anonymous class names of the form
120
// 'ClassName.N'. Note that the '.' qualifications get converted to
121
// '$' characters when determining the external name of the class and
122
// the name of the class file.
123
if (hname.length() > 0
124
&& Character.isDigit(hname.charAt(0))) {
125
ClassDefinition localClass = c.getLocalClass(hname);
126
if (localClass != null) {
127
c = localClass;
128
continue walkTail;
129
}
130
} else {
131
for (MemberDefinition f = c.getFirstMatch(head);
132
f != null; f = f.getNextMatch()) {
133
if (f.isInnerClass()) {
134
c = f.getInnerClass();
135
continue walkTail;
136
}
137
}
138
}
139
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
140
}
141
//System.out.println("FOUND " + c + " FOR " + nm);
142
return c;
143
}
144
return getClassDeclaration(nm).getClassDefinition(this);
145
}
146
147
148
/**
149
* Return a class declaration given a type. Only works for
150
* class types.
151
*/
152
public ClassDeclaration getClassDeclaration(Type t) {
153
return getClassDeclaration(t.getClassName());
154
}
155
156
/**
157
* Return a class definition given a type. Only works for
158
* class types.
159
*/
160
public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound {
161
return getClassDefinition(t.getClassName());
162
}
163
164
/**
165
* Check if a class exists (without actually loading it).
166
* (Since inner classes cannot in general be examined without
167
* loading source, this method does not accept inner names.)
168
*/
169
public boolean classExists(Identifier nm) {
170
return env.classExists(nm);
171
}
172
173
public final boolean classExists(Type t) {
174
return !t.isType(TC_CLASS) || classExists(t.getClassName());
175
}
176
177
/**
178
* Get the package path for a package
179
*/
180
public Package getPackage(Identifier pkg) throws IOException {
181
return env.getPackage(pkg);
182
}
183
184
/**
185
* Load the definition of a class.
186
*/
187
public void loadDefinition(ClassDeclaration c) {
188
env.loadDefinition(c);
189
}
190
191
/**
192
* Return the source of the environment (ie: the thing being compiled/parsed).
193
*/
194
public final Object getSource() {
195
return source;
196
}
197
198
/**
199
* Resolve a type. Make sure that all the classes referred to by
200
* the type have a definition. Report errors. Return true if
201
* the type is well-formed. Presently used for types appearing
202
* in member declarations, which represent named types internally as
203
* qualified identifiers. Type names appearing in local variable
204
* declarations and within expressions are represented as identifier
205
* or field expressions, and are resolved by 'toType', which delegates
206
* handling of the non-inner portion of the name to this method.
207
* <p>
208
* In 'toType', the various stages of qualification are represented by
209
* separate AST nodes. Here, we are given a single identifier which
210
* contains the entire qualification structure. It is not possible in
211
* general to set the error location to the exact position of a component
212
* that is in error, so an error message must refer to the entire qualified
213
* name. An attempt to keep track of the string length of the components of
214
* the name and to offset the location accordingly fails because the initial
215
* prefix of the name may have been rewritten by an earlier call to
216
* 'resolveName'. See 'SourceMember.resolveTypeStructure'. The situation
217
* is actually even worse than this, because only a single location is
218
* passed in for an entire declaration, which may contain many type names.
219
* All error messages are thus poorly localized. These checks should be
220
* done while traversing the parse tree for the type, not the type descriptor.
221
* <p>
222
* DESIGN NOTE:
223
* As far as I can tell, the two-stage resolution of names represented in
224
* string form is an artifact of the late implementation of inner classes
225
* and the use of mangled names internally within the compiler. All
226
* qualified names should have their hiearchical structure made explicit
227
* in the parse tree at the phase at which they are presented for static
228
* semantic checking. This would affect class names appearing in 'extends',
229
* 'implements', and 'throws' clauses, as well as in member declarations.
230
*/
231
public boolean resolve(long where, ClassDefinition c, Type t) {
232
switch (t.getTypeCode()) {
233
case TC_CLASS: {
234
ClassDefinition def;
235
try {
236
Identifier nm = t.getClassName();
237
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
238
resolve(nm); // elicit complaints about ambiguity
239
}
240
def = getQualifiedClassDefinition(where, nm, c, false);
241
if (!c.canAccess(this, def.getClassDeclaration())) {
242
// Reported error location may be imprecise
243
// if the name is qualified.
244
error(where, "cant.access.class", def);
245
return true; // return false later
246
}
247
def.noteUsedBy(c, where, env);
248
} catch (AmbiguousClass ee) {
249
error(where, "ambig.class", ee.name1, ee.name2);
250
return false;
251
} catch (ClassNotFound e) {
252
// For now, report "class.and.package" only when the code
253
// is going to fail anyway.
254
try {
255
if (e.name.isInner() &&
256
getPackage(e.name.getTopName()).exists()) {
257
env.error(where, "class.and.package",
258
e.name.getTopName());
259
}
260
} catch (IOException ee) {
261
env.error(where, "io.exception", "package check");
262
}
263
// This error message is also emitted for 'new' expressions.
264
// error(where, "class.not.found", e.name, "declaration");
265
error(where, "class.not.found.no.context", e.name);
266
return false;
267
}
268
return true;
269
}
270
271
case TC_ARRAY:
272
return resolve(where, c, t.getElementType());
273
274
case TC_METHOD:
275
boolean ok = resolve(where, c, t.getReturnType());
276
Type args[] = t.getArgumentTypes();
277
for (int i = args.length ; i-- > 0 ; ) {
278
ok &= resolve(where, c, args[i]);
279
}
280
return ok;
281
}
282
return true;
283
}
284
285
/**
286
* Given its fully-qualified name, verify that a class is defined and accessible.
287
* Used to check components of qualified names in contexts where a class is expected.
288
* Like 'resolve', but is given a single type name, not a type descriptor.
289
*/
290
public boolean resolveByName(long where, ClassDefinition c, Identifier nm) {
291
return resolveByName(where, c, nm, false);
292
}
293
294
public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) {
295
return resolveByName(where, c, nm, true);
296
}
297
298
private boolean resolveByName(long where, ClassDefinition c,
299
Identifier nm, boolean isExtends) {
300
ClassDefinition def;
301
try {
302
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
303
resolve(nm); // elicit complaints about ambiguity
304
}
305
def = getQualifiedClassDefinition(where, nm, c, isExtends);
306
ClassDeclaration decl = def.getClassDeclaration();
307
if (!((!isExtends && c.canAccess(this, decl))
308
||
309
(isExtends && c.extendsCanAccess(this, decl)))) {
310
error(where, "cant.access.class", def);
311
return true; // return false later
312
}
313
} catch (AmbiguousClass ee) {
314
error(where, "ambig.class", ee.name1, ee.name2);
315
return false;
316
} catch (ClassNotFound e) {
317
// For now, report "class.and.package" only when the code
318
// is going to fail anyway.
319
try {
320
if (e.name.isInner() &&
321
getPackage(e.name.getTopName()).exists()) {
322
env.error(where, "class.and.package",
323
e.name.getTopName());
324
}
325
} catch (IOException ee) {
326
env.error(where, "io.exception", "package check");
327
}
328
error(where, "class.not.found", e.name, "type name");
329
return false;
330
}
331
return true;
332
}
333
334
/**
335
* Like 'getClassDefinition(env)', but check access on each component.
336
* Currently called only by 'resolve' above. It is doubtful that calls
337
* to 'getClassDefinition(env)' are appropriate now.
338
*/
339
public final ClassDefinition
340
getQualifiedClassDefinition(long where,
341
Identifier nm,
342
ClassDefinition ctxClass,
343
boolean isExtends) throws ClassNotFound {
344
if (nm.isInner()) {
345
ClassDefinition c = getClassDefinition(nm.getTopName());
346
Identifier tail = nm.getFlatName();
347
walkTail:
348
while (tail.isQualified()) {
349
tail = tail.getTail();
350
Identifier head = tail.getHead();
351
// System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
352
String hname = head.toString();
353
// Handle synthesized names of local and anonymous classes.
354
// See 'getClassDefinition(env)' above.
355
if (hname.length() > 0
356
&& Character.isDigit(hname.charAt(0))) {
357
ClassDefinition localClass = c.getLocalClass(hname);
358
if (localClass != null) {
359
c = localClass;
360
continue walkTail;
361
}
362
} else {
363
for (MemberDefinition f = c.getFirstMatch(head);
364
f != null; f = f.getNextMatch()) {
365
if (f.isInnerClass()) {
366
ClassDeclaration rdecl = c.getClassDeclaration();
367
c = f.getInnerClass();
368
ClassDeclaration fdecl = c.getClassDeclaration();
369
// This check is presumably applicable even if the
370
// original source-code name (expanded by 'resolveNames')
371
// was a simple, unqualified name. Hopefully, JLS 2e
372
// will clarify the matter.
373
if ((!isExtends
374
&& !ctxClass.canAccess(env, fdecl))
375
||
376
(isExtends
377
&& !ctxClass.extendsCanAccess(env, fdecl))) {
378
// Reported error location is imprecise.
379
env.error(where, "no.type.access", head, rdecl, ctxClass);
380
}
381
// The JLS 6.6.2 restrictions on access to protected members
382
// depend in an essential way upon the syntactic form of the name.
383
// Since the compiler has previously expanded the class names
384
// here into fully-qualified form ('resolveNames'), this check
385
// cannot be performed here. Unfortunately, the original names
386
// are clobbered during 'basicCheck', which is also the phase that
387
// resolves the inheritance structure, required to implement the
388
// access restrictions. Pending a large-scale revision of the
389
// name-resolution machinery, we forgo this check, with the result
390
// that the JLS 6.6.2 restrictions are not enforced for some cases
391
// of qualified access to inner classes. Some qualified names are
392
// resolved elsewhere via a different mechanism, and will be
393
// treated correctly -- see 'FieldExpression.checkCommon'.
394
/*---------------------------------------*
395
if (f.isProtected()) {
396
Type rty = Type.tClass(rdecl.getName()); // hack
397
if (!ctxClass.protectedAccess(env, f, rty)) {
398
// Reported error location is imprecise.
399
env.error(where, "invalid.protected.type.use",
400
head, ctxClass, rty);
401
}
402
}
403
*---------------------------------------*/
404
continue walkTail;
405
}
406
}
407
}
408
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
409
}
410
//System.out.println("FOUND " + c + " FOR " + nm);
411
return c;
412
}
413
return getClassDeclaration(nm).getClassDefinition(this);
414
}
415
416
/**
417
* Resolve the names within a type, returning the adjusted type.
418
* Adjust class names to reflect scoping.
419
* Do not report errors.
420
* <p>
421
* NOTE: It would be convenient to check for errors here, such as
422
* verifying that each component of a qualified name exists and is
423
* accessible. Why must this be done in a separate phase?
424
* <p>
425
* If the 'synth' argument is true, indicating that the member whose
426
* type is being resolved is synthetic, names are resolved with respect
427
* to the package scope. (Fix for 4097882)
428
*/
429
public Type resolveNames(ClassDefinition c, Type t, boolean synth) {
430
if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t);
431
switch (t.getTypeCode()) {
432
case TC_CLASS: {
433
Identifier name = t.getClassName();
434
Identifier rname;
435
if (synth) {
436
rname = resolvePackageQualifiedName(name);
437
} else {
438
rname = c.resolveName(this, name);
439
}
440
if (name != rname) {
441
t = Type.tClass(rname);
442
}
443
break;
444
}
445
446
case TC_ARRAY:
447
t = Type.tArray(resolveNames(c, t.getElementType(), synth));
448
break;
449
450
case TC_METHOD: {
451
Type ret = t.getReturnType();
452
Type rret = resolveNames(c, ret, synth);
453
Type args[] = t.getArgumentTypes();
454
Type rargs[] = new Type[args.length];
455
boolean changed = (ret != rret);
456
for (int i = args.length ; i-- > 0 ; ) {
457
Type arg = args[i];
458
Type rarg = resolveNames(c, arg, synth);
459
rargs[i] = rarg;
460
if (arg != rarg) {
461
changed = true;
462
}
463
}
464
if (changed) {
465
t = Type.tMethod(rret, rargs);
466
}
467
break;
468
}
469
}
470
return t;
471
}
472
473
/**
474
* Resolve a class name, using only package and import directives.
475
* Report no errors.
476
* <p>
477
*/
478
public Identifier resolveName(Identifier name) {
479
// This logic is pretty exactly parallel to that of
480
// ClassDefinition.resolveName().
481
if (name.isQualified()) {
482
// Try to resolve the first identifier component,
483
// because inner class names take precedence over
484
// package prefixes. (Cf. ClassDefinition.resolveName.)
485
Identifier rhead = resolveName(name.getHead());
486
487
if (rhead.hasAmbigPrefix()) {
488
// The first identifier component refers to an
489
// ambiguous class. Limp on. We throw away the
490
// rest of the classname as it is irrelevant.
491
// (part of solution for 4059855).
492
return rhead;
493
}
494
495
if (!this.classExists(rhead)) {
496
return this.resolvePackageQualifiedName(name);
497
}
498
try {
499
return this.getClassDefinition(rhead).
500
resolveInnerClass(this, name.getTail());
501
} catch (ClassNotFound ee) {
502
// return partially-resolved name someone else can fail on
503
return Identifier.lookupInner(rhead, name.getTail());
504
}
505
}
506
try {
507
return resolve(name);
508
} catch (AmbiguousClass ee) {
509
// Don't force a resolution of the name if it is ambiguous.
510
// Forcing the resolution would tack the current package
511
// name onto the front of the class, which would be wrong.
512
// Instead, mark the name as ambiguous and let a later stage
513
// find the error by calling env.resolve(name).
514
// (part of solution for 4059855).
515
516
if (name.hasAmbigPrefix()) {
517
return name;
518
} else {
519
return name.addAmbigPrefix();
520
}
521
} catch (ClassNotFound ee) {
522
// last chance to make something halfway sensible
523
Imports imports = getImports();
524
if (imports != null)
525
return imports.forceResolve(this, name);
526
}
527
return name;
528
}
529
530
/**
531
* Discover if name consists of a package prefix, followed by the
532
* name of a class (that actually exists), followed possibly by
533
* some inner class names. If we can't find a class that exists,
534
* return the name unchanged.
535
* <p>
536
* This routine is used after a class name fails to
537
* be resolved by means of imports or inner classes.
538
* However, import processing uses this routine directly,
539
* since import names must be exactly qualified to start with.
540
*/
541
public final Identifier resolvePackageQualifiedName(Identifier name) {
542
Identifier tail = null;
543
for (;;) {
544
if (classExists(name)) {
545
break;
546
}
547
if (!name.isQualified()) {
548
name = (tail == null) ? name : Identifier.lookup(name, tail);
549
tail = null;
550
break;
551
}
552
Identifier nm = name.getName();
553
tail = (tail == null)? nm: Identifier.lookup(nm, tail);
554
name = name.getQualifier();
555
}
556
if (tail != null)
557
name = Identifier.lookupInner(name, tail);
558
return name;
559
}
560
561
/**
562
* Resolve a class name, using only package and import directives.
563
*/
564
public Identifier resolve(Identifier nm) throws ClassNotFound {
565
if (env == null) return nm; // a pretty useless no-op
566
return env.resolve(nm);
567
}
568
569
/**
570
* Get the imports used to resolve class names.
571
*/
572
public Imports getImports() {
573
if (env == null) return null; // lame default
574
return env.getImports();
575
}
576
577
/**
578
* Create a new class.
579
*/
580
public ClassDefinition makeClassDefinition(Environment origEnv, long where,
581
IdentifierToken name,
582
String doc, int modifiers,
583
IdentifierToken superClass,
584
IdentifierToken interfaces[],
585
ClassDefinition outerClass) {
586
if (env == null) return null; // lame default
587
return env.makeClassDefinition(origEnv, where, name,
588
doc, modifiers,
589
superClass, interfaces, outerClass);
590
}
591
592
/**
593
* Create a new field.
594
*/
595
public MemberDefinition makeMemberDefinition(Environment origEnv, long where,
596
ClassDefinition clazz,
597
String doc, int modifiers,
598
Type type, Identifier name,
599
IdentifierToken argNames[],
600
IdentifierToken expIds[],
601
Object value) {
602
if (env == null) return null; // lame default
603
return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers,
604
type, name, argNames, expIds, value);
605
}
606
607
/**
608
* Returns true if the given method is applicable to the given arguments
609
*/
610
611
public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound {
612
Type mType = m.getType();
613
if (!mType.isType(TC_METHOD))
614
return false;
615
Type mArgs[] = mType.getArgumentTypes();
616
if (args.length != mArgs.length)
617
return false;
618
for (int i = args.length ; --i >= 0 ;)
619
if (!isMoreSpecific(args[i], mArgs[i]))
620
return false;
621
return true;
622
}
623
624
625
/**
626
* Returns true if "best" is in every argument at least as good as "other"
627
*/
628
public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other)
629
throws ClassNotFound {
630
Type bestType = best.getClassDeclaration().getType();
631
Type otherType = other.getClassDeclaration().getType();
632
boolean result = isMoreSpecific(bestType, otherType)
633
&& isApplicable(other, best.getType().getArgumentTypes());
634
// System.out.println("isMoreSpecific: " + best + "/" + other
635
// + " => " + result);
636
return result;
637
}
638
639
/**
640
* Returns true if "from" is a more specific type than "to"
641
*/
642
643
public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound {
644
return implicitCast(from, to);
645
}
646
647
/**
648
* Return true if an implicit cast from this type to
649
* the given type is allowed.
650
*/
651
public boolean implicitCast(Type from, Type to) throws ClassNotFound {
652
if (from == to)
653
return true;
654
655
int toTypeCode = to.getTypeCode();
656
657
switch(from.getTypeCode()) {
658
case TC_BYTE:
659
if (toTypeCode == TC_SHORT)
660
return true;
661
case TC_SHORT:
662
case TC_CHAR:
663
if (toTypeCode == TC_INT) return true;
664
case TC_INT:
665
if (toTypeCode == TC_LONG) return true;
666
case TC_LONG:
667
if (toTypeCode == TC_FLOAT) return true;
668
case TC_FLOAT:
669
if (toTypeCode == TC_DOUBLE) return true;
670
case TC_DOUBLE:
671
default:
672
return false;
673
674
case TC_NULL:
675
return to.inMask(TM_REFERENCE);
676
677
case TC_ARRAY:
678
if (!to.isType(TC_ARRAY)) {
679
return (to == Type.tObject || to == Type.tCloneable
680
|| to == Type.tSerializable);
681
} else {
682
// both are arrays. recurse down both until one isn't an array
683
do {
684
from = from.getElementType();
685
to = to.getElementType();
686
} while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY));
687
if ( from.inMask(TM_ARRAY|TM_CLASS)
688
&& to.inMask(TM_ARRAY|TM_CLASS)) {
689
return isMoreSpecific(from, to);
690
} else {
691
return (from.getTypeCode() == to.getTypeCode());
692
}
693
}
694
695
case TC_CLASS:
696
if (toTypeCode == TC_CLASS) {
697
ClassDefinition fromDef = getClassDefinition(from);
698
ClassDefinition toDef = getClassDefinition(to);
699
return toDef.implementedBy(this,
700
fromDef.getClassDeclaration());
701
} else {
702
return false;
703
}
704
}
705
}
706
707
708
/**
709
* Return true if an explicit cast from this type to
710
* the given type is allowed.
711
*/
712
public boolean explicitCast(Type from, Type to) throws ClassNotFound {
713
if (implicitCast(from, to)) {
714
return true;
715
}
716
if (from.inMask(TM_NUMBER)) {
717
return to.inMask(TM_NUMBER);
718
}
719
if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) {
720
ClassDefinition fromClass = getClassDefinition(from);
721
ClassDefinition toClass = getClassDefinition(to);
722
if (toClass.isFinal()) {
723
return fromClass.implementedBy(this,
724
toClass.getClassDeclaration());
725
}
726
if (fromClass.isFinal()) {
727
return toClass.implementedBy(this,
728
fromClass.getClassDeclaration());
729
}
730
731
// The code here used to omit this case. If both types
732
// involved in a cast are interfaces, then JLS 5.5 requires
733
// that we do a simple test -- make sure none of the methods
734
// in toClass and fromClass have the same signature but
735
// different return types. (bug number 4028359)
736
if (toClass.isInterface() && fromClass.isInterface()) {
737
return toClass.couldImplement(fromClass);
738
}
739
740
return toClass.isInterface() ||
741
fromClass.isInterface() ||
742
fromClass.superClassOf(this, toClass.getClassDeclaration());
743
}
744
if (to.isType(TC_ARRAY)) {
745
if (from.isType(TC_ARRAY)) {
746
Type t1 = from.getElementType();
747
Type t2 = to.getElementType();
748
while ((t1.getTypeCode() == TC_ARRAY)
749
&& (t2.getTypeCode() == TC_ARRAY)) {
750
t1 = t1.getElementType();
751
t2 = t2.getElementType();
752
}
753
if (t1.inMask(TM_ARRAY|TM_CLASS) &&
754
t2.inMask(TM_ARRAY|TM_CLASS)) {
755
return explicitCast(t1, t2);
756
}
757
} else if (from == Type.tObject || from == Type.tCloneable
758
|| from == Type.tSerializable)
759
return true;
760
}
761
return false;
762
}
763
764
/**
765
* Flags.
766
*/
767
public int getFlags() {
768
return env.getFlags();
769
}
770
771
/**
772
* Debugging flags. There used to be a method debug()
773
* that has been replaced because -g has changed meaning
774
* (it now cooperates with -O and line number, variable
775
* range and source file info can be toggled separately).
776
*/
777
public final boolean debug_lines() {
778
return (getFlags() & F_DEBUG_LINES) != 0;
779
}
780
public final boolean debug_vars() {
781
return (getFlags() & F_DEBUG_VARS) != 0;
782
}
783
public final boolean debug_source() {
784
return (getFlags() & F_DEBUG_SOURCE) != 0;
785
}
786
787
/**
788
* Optimization flags. There used to be a method optimize()
789
* that has been replaced because -O has changed meaning in
790
* javac to be replaced with -O and -O:interclass.
791
*/
792
public final boolean opt() {
793
return (getFlags() & F_OPT) != 0;
794
}
795
public final boolean opt_interclass() {
796
return (getFlags() & F_OPT_INTERCLASS) != 0;
797
}
798
799
/**
800
* Verbose
801
*/
802
public final boolean verbose() {
803
return (getFlags() & F_VERBOSE) != 0;
804
}
805
806
/**
807
* Dump debugging stuff
808
*/
809
public final boolean dump() {
810
return (getFlags() & F_DUMP) != 0;
811
}
812
813
/**
814
* Verbose
815
*/
816
public final boolean warnings() {
817
return (getFlags() & F_WARNINGS) != 0;
818
}
819
820
/**
821
* Dependencies
822
*/
823
public final boolean dependencies() {
824
return (getFlags() & F_DEPENDENCIES) != 0;
825
}
826
827
/**
828
* Print Dependencies to stdout
829
*/
830
public final boolean print_dependencies() {
831
return (getFlags() & F_PRINT_DEPENDENCIES) != 0;
832
}
833
834
/**
835
* Deprecation warnings are enabled.
836
*/
837
public final boolean deprecation() {
838
return (getFlags() & F_DEPRECATION) != 0;
839
}
840
841
/**
842
* Do not support virtual machines before version 1.2.
843
* This option is not supported and is only here for testing purposes.
844
*/
845
public final boolean version12() {
846
return (getFlags() & F_VERSION12) != 0;
847
}
848
849
/**
850
* Floating point is strict by default
851
*/
852
public final boolean strictdefault() {
853
return (getFlags() & F_STRICTDEFAULT) != 0;
854
}
855
856
/**
857
* Release resources, if any.
858
*/
859
public void shutdown() {
860
if (env != null) {
861
env.shutdown();
862
}
863
}
864
865
/**
866
* Issue an error.
867
* source - the input source, usually a file name string
868
* offset - the offset in the source of the error
869
* err - the error number (as defined in this interface)
870
* arg1 - an optional argument to the error (null if not applicable)
871
* arg2 - a second optional argument to the error (null if not applicable)
872
* arg3 - a third optional argument to the error (null if not applicable)
873
*/
874
public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) {
875
env.error(source, where, err, arg1, arg2, arg3);
876
}
877
public final void error(long where, String err, Object arg1, Object arg2, Object arg3) {
878
error(source, where, err, arg1, arg2, arg3);
879
}
880
public final void error(long where, String err, Object arg1, Object arg2) {
881
error(source, where, err, arg1, arg2, null);
882
}
883
public final void error(long where, String err, Object arg1) {
884
error(source, where, err, arg1, null, null);
885
}
886
public final void error(long where, String err) {
887
error(source, where, err, null, null, null);
888
}
889
890
/**
891
* Output a string. This can either be an error message or something
892
* for debugging. This should be used instead of println.
893
*/
894
public void output(String msg) {
895
env.output(msg);
896
}
897
898
private static boolean debugging = (System.getProperty("javac.debug") != null);
899
900
public static void debugOutput(Object msg) {
901
if (Environment.debugging)
902
System.out.println(msg.toString());
903
}
904
905
/**
906
* set character encoding name
907
*/
908
public void setCharacterEncoding(String encoding) {
909
this.encoding = encoding;
910
}
911
912
/**
913
* Return character encoding name
914
*/
915
public String getCharacterEncoding() {
916
return encoding;
917
}
918
919
/**
920
* Return major version to use in generated class files.
921
*/
922
public short getMajorVersion() {
923
if (env==null) return JAVA_DEFAULT_VERSION; // needed for javah
924
return env.getMajorVersion();
925
}
926
927
/**
928
* Return minor version to use in generated class files.
929
*/
930
public short getMinorVersion() {
931
if (env==null) return JAVA_DEFAULT_MINOR_VERSION; // needed for javah
932
return env.getMinorVersion();
933
}
934
935
// JCOV
936
/**
937
* get coverage flag
938
*/
939
public final boolean coverage() {
940
return (getFlags() & F_COVERAGE) != 0;
941
}
942
943
/**
944
* get flag of generation the coverage data file
945
*/
946
public final boolean covdata() {
947
return (getFlags() & F_COVDATA) != 0;
948
}
949
950
/**
951
* Return the coverage data file
952
*/
953
public File getcovFile() {
954
return env.getcovFile();
955
}
956
957
// end JCOV
958
959
/**
960
* Debug tracing.
961
* Currently, this code is used only for tracing the loading and
962
* checking of classes, particularly the demand-driven aspects.
963
* This code should probably be integrated with 'debugOutput' above,
964
* but we need to give more thought to the issue of classifying debugging
965
* messages and allowing those only those of interest to be enabled.
966
*
967
* Calls to these methods are generally conditioned on the final variable
968
* 'Constants.tracing', which allows the calls to be completely omitted
969
* in a production release to avoid space and time overhead.
970
*/
971
972
private static boolean dependtrace =
973
(System.getProperty("javac.trace.depend") != null);
974
975
public void dtEnter(String s) {
976
if (dependtrace) System.out.println(">>> " + s);
977
}
978
979
public void dtExit(String s) {
980
if (dependtrace) System.out.println("<<< " + s);
981
}
982
983
public void dtEvent(String s) {
984
if (dependtrace) System.out.println(s);
985
}
986
987
/**
988
* Enable diagnostic dump of class modifier bits, including those
989
* in InnerClasses attributes, as they are written to the classfile.
990
* In the future, may also enable dumping field and method modifiers.
991
*/
992
993
private static boolean dumpmodifiers =
994
(System.getProperty("javac.dump.modifiers") != null);
995
996
public boolean dumpModifiers() { return dumpmodifiers; }
997
998
}
999
1000