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/ClassDefinition.java
38918 views
1
/*
2
* Copyright (c) 1994, 2006, 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.*;
29
import java.io.OutputStream;
30
import java.io.PrintStream;
31
import sun.tools.tree.Context;
32
import sun.tools.tree.Vset;
33
import sun.tools.tree.Expression;
34
import sun.tools.tree.LocalMember;
35
import sun.tools.tree.UplevelReference;
36
37
/**
38
* This class is a Java class definition
39
*
40
* WARNING: The contents of this source file are not part of any
41
* supported API. Code that depends on them does so at its own risk:
42
* they are subject to change or removal without notice.
43
*/
44
public
45
class ClassDefinition implements Constants {
46
47
protected Object source;
48
protected long where;
49
protected int modifiers;
50
protected Identifier localName; // for local classes
51
protected ClassDeclaration declaration;
52
protected IdentifierToken superClassId;
53
protected IdentifierToken interfaceIds[];
54
protected ClassDeclaration superClass;
55
protected ClassDeclaration interfaces[];
56
protected ClassDefinition outerClass;
57
protected MemberDefinition outerMember;
58
protected MemberDefinition innerClassMember; // field for me in outerClass
59
protected MemberDefinition firstMember;
60
protected MemberDefinition lastMember;
61
protected boolean resolved;
62
protected String documentation;
63
protected boolean error;
64
protected boolean nestError;
65
protected UplevelReference references;
66
protected boolean referencesFrozen;
67
private Hashtable fieldHash = new Hashtable(31);
68
private int abstr;
69
70
// Table of local and anonymous classes whose internal names are constructed
71
// using the current class as a prefix. This is part of a fix for
72
// bugid 4054523 and 4030421. See also 'Environment.getClassDefinition'
73
// and 'BatchEnvironment.makeClassDefinition'. Allocated on demand.
74
private Hashtable localClasses = null;
75
private final int LOCAL_CLASSES_SIZE = 31;
76
77
// The immediately surrounding context in which the class appears.
78
// Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.
79
// Null for classes that are not local or inside a local class.
80
// At present, this field exists only for the benefit of 'resolveName' as part
81
// of the fix for 4095716.
82
protected Context classContext;
83
84
// The saved class context is now also used in 'SourceClass.getAccessMember'.
85
// Provide read-only access via this method. Part of fix for 4098093.
86
public Context getClassContext() {
87
return classContext;
88
}
89
90
91
/**
92
* Constructor
93
*/
94
protected ClassDefinition(Object source, long where, ClassDeclaration declaration,
95
int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {
96
this.source = source;
97
this.where = where;
98
this.declaration = declaration;
99
this.modifiers = modifiers;
100
this.superClassId = superClass;
101
this.interfaceIds = interfaces;
102
}
103
104
/**
105
* Get the source of the class
106
*/
107
public final Object getSource() {
108
return source;
109
}
110
111
/**
112
* Check if there were any errors in this class.
113
*/
114
public final boolean getError() {
115
return error;
116
}
117
118
/**
119
* Mark this class to be erroneous.
120
*/
121
public final void setError() {
122
this.error = true;
123
setNestError();
124
}
125
126
/**
127
* Check if there were any errors in our class nest.
128
*/
129
public final boolean getNestError() {
130
// Check to see if our error value is set, or if any of our
131
// outer classes' error values are set. This will work in
132
// conjunction with setError(), which sets the error value
133
// of its outer class, to yield true is any of our nest
134
// siblings has an error. This addresses bug 4111488: either
135
// code should be generated for all classes in a nest, or
136
// none of them.
137
return nestError || ((outerClass != null) ? outerClass.getNestError() : false);
138
}
139
140
/**
141
* Mark this class, and all siblings in its class nest, to be
142
* erroneous.
143
*/
144
public final void setNestError() {
145
this.nestError = true;
146
if (outerClass != null) {
147
// If we have an outer class, set it to be erroneous as well.
148
// This will work in conjunction with getError(), which checks
149
// the error value of its outer class, to set the whole class
150
// nest to be erroneous. This address bug 4111488: either
151
// code should be generated for all classes in a nest, or
152
// none of them.
153
outerClass.setNestError();
154
}
155
}
156
157
/**
158
* Get the position in the input
159
*/
160
public final long getWhere() {
161
return where;
162
}
163
164
/**
165
* Get the class declaration
166
*/
167
public final ClassDeclaration getClassDeclaration() {
168
return declaration;
169
}
170
171
/**
172
* Get the class' modifiers
173
*/
174
public final int getModifiers() {
175
return modifiers;
176
}
177
public final void subModifiers(int mod) {
178
modifiers &= ~mod;
179
}
180
public final void addModifiers(int mod) {
181
modifiers |= mod;
182
}
183
184
// *** DEBUG ***
185
protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);
186
187
/**
188
* Get the class' super class
189
*/
190
public final ClassDeclaration getSuperClass() {
191
/*---
192
if (superClass == null && superClassId != null)
193
throw new CompilerError("getSuperClass "+superClassId);
194
// There are obscure cases where null is the right answer,
195
// in order to enable some error reporting later on.
196
// For example: class T extends T.N { class N { } }
197
---*/
198
199
// *** DEBUG ***
200
// This method should not be called if the superclass has not been resolved.
201
if (!supersCheckStarted) throw new CompilerError("unresolved super");
202
203
return superClass;
204
}
205
206
/**
207
* Get the super class, and resolve names now if necessary.
208
*
209
* It is only possible to resolve names at this point if we are
210
* a source class. The provision of this method at this level
211
* in the class hierarchy is dubious, but see 'getInnerClass' below.
212
* All other calls to 'getSuperClass(env)' appear in 'SourceClass'.
213
* NOTE: An older definition of this method has been moved to
214
* 'SourceClass', where it overrides this one.
215
*
216
* @see #resolveTypeStructure
217
*/
218
219
public ClassDeclaration getSuperClass(Environment env) {
220
return getSuperClass();
221
}
222
223
/**
224
* Get the class' interfaces
225
*/
226
public final ClassDeclaration getInterfaces()[] {
227
if (interfaces == null) throw new CompilerError("getInterfaces");
228
return interfaces;
229
}
230
231
/**
232
* Get the class' enclosing class (or null if not inner)
233
*/
234
public final ClassDefinition getOuterClass() {
235
return outerClass;
236
}
237
238
/**
239
* Set the class' enclosing class. Must be done at most once.
240
*/
241
protected final void setOuterClass(ClassDefinition outerClass) {
242
if (this.outerClass != null) throw new CompilerError("setOuterClass");
243
this.outerClass = outerClass;
244
}
245
246
/**
247
* Set the class' enclosing current instance pointer.
248
* Must be done at most once.
249
*/
250
protected final void setOuterMember(MemberDefinition outerMember) {
251
252
if (isStatic() || !isInnerClass()) throw new CompilerError("setOuterField");
253
if (this.outerMember != null) throw new CompilerError("setOuterField");
254
this.outerMember = outerMember;
255
}
256
257
/**
258
* Tell if the class is inner.
259
* This predicate also returns true for top-level nested types.
260
* To test for a true inner class as seen by the programmer,
261
* use <tt>!isTopLevel()</tt>.
262
*/
263
public final boolean isInnerClass() {
264
return outerClass != null;
265
}
266
267
/**
268
* Tell if the class is a member of another class.
269
* This is false for package members and for block-local classes.
270
*/
271
public final boolean isMember() {
272
return outerClass != null && !isLocal();
273
}
274
275
/**
276
* Tell if the class is "top-level", which is either a package member,
277
* or a static member of another top-level class.
278
*/
279
public final boolean isTopLevel() {
280
return outerClass == null || isStatic() || isInterface();
281
}
282
283
/**
284
* Tell if the class is local or inside a local class,
285
* which means it cannot be mentioned outside of its file.
286
*/
287
288
// The comment above is true only because M_LOCAL is set
289
// whenever M_ANONYMOUS is. I think it is risky to assume that
290
// isAnonymous(x) => isLocal(x).
291
292
public final boolean isInsideLocal() {
293
return isLocal() ||
294
(outerClass != null && outerClass.isInsideLocal());
295
}
296
297
/**
298
* Tell if the class is local or or anonymous class, or inside
299
* such a class, which means it cannot be mentioned outside of
300
* its file.
301
*/
302
public final boolean isInsideLocalOrAnonymous() {
303
return isLocal() || isAnonymous () ||
304
(outerClass != null && outerClass.isInsideLocalOrAnonymous());
305
}
306
307
/**
308
* Return a simple identifier for this class (idNull if anonymous).
309
*/
310
public Identifier getLocalName() {
311
if (localName != null) {
312
return localName;
313
}
314
// This is also the name of the innerClassMember, if any:
315
return getName().getFlatName().getName();
316
}
317
318
/**
319
* Set the local name of a class. Must be a local class.
320
*/
321
public void setLocalName(Identifier name) {
322
if (isLocal()) {
323
localName = name;
324
}
325
}
326
327
/**
328
* If inner, get the field for this class in the enclosing class
329
*/
330
public final MemberDefinition getInnerClassMember() {
331
if (outerClass == null)
332
return null;
333
if (innerClassMember == null) {
334
// We must find the field in the outer class.
335
Identifier nm = getName().getFlatName().getName();
336
for (MemberDefinition field = outerClass.getFirstMatch(nm);
337
field != null; field = field.getNextMatch()) {
338
if (field.isInnerClass()) {
339
innerClassMember = field;
340
break;
341
}
342
}
343
if (innerClassMember == null)
344
throw new CompilerError("getInnerClassField");
345
}
346
return innerClassMember;
347
}
348
349
/**
350
* If inner, return an innermost uplevel self pointer, if any exists.
351
* Otherwise, return null.
352
*/
353
public final MemberDefinition findOuterMember() {
354
return outerMember;
355
}
356
357
/**
358
* See if this is a (nested) static class.
359
*/
360
public final boolean isStatic() {
361
return (modifiers & ACC_STATIC) != 0;
362
}
363
364
/**
365
* Get the class' top-level enclosing class
366
*/
367
public final ClassDefinition getTopClass() {
368
ClassDefinition p, q;
369
for (p = this; (q = p.outerClass) != null; p = q)
370
;
371
return p;
372
}
373
374
/**
375
* Get the class' first field or first match
376
*/
377
public final MemberDefinition getFirstMember() {
378
return firstMember;
379
}
380
public final MemberDefinition getFirstMatch(Identifier name) {
381
return (MemberDefinition)fieldHash.get(name);
382
}
383
384
/**
385
* Get the class' name
386
*/
387
public final Identifier getName() {
388
return declaration.getName();
389
}
390
391
/**
392
* Get the class' type
393
*/
394
public final Type getType() {
395
return declaration.getType();
396
}
397
398
/**
399
* Get the class' documentation
400
*/
401
public String getDocumentation() {
402
return documentation;
403
}
404
405
/**
406
* Return true if the given documentation string contains a deprecation
407
* paragraph. This is true if the string contains the tag @deprecated
408
* is the first word in a line.
409
*/
410
public static boolean containsDeprecated(String documentation) {
411
if (documentation == null) {
412
return false;
413
}
414
doScan:
415
for (int scan = 0;
416
(scan = documentation.indexOf(paraDeprecated, scan)) >= 0;
417
scan += paraDeprecated.length()) {
418
// make sure there is only whitespace between this word
419
// and the beginning of the line
420
for (int beg = scan-1; beg >= 0; beg--) {
421
char ch = documentation.charAt(beg);
422
if (ch == '\n' || ch == '\r') {
423
break; // OK
424
}
425
if (!Character.isSpace(ch)) {
426
continue doScan;
427
}
428
}
429
// make sure the char after the word is space or end of line
430
int end = scan+paraDeprecated.length();
431
if (end < documentation.length()) {
432
char ch = documentation.charAt(end);
433
if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {
434
continue doScan;
435
}
436
}
437
return true;
438
}
439
return false;
440
}
441
442
public final boolean inSamePackage(ClassDeclaration c) {
443
// find out if the class stored in c is defined in the same
444
// package as the current class.
445
return inSamePackage(c.getName().getQualifier());
446
}
447
448
public final boolean inSamePackage(ClassDefinition c) {
449
// find out if the class stored in c is defined in the same
450
// package as the current class.
451
return inSamePackage(c.getName().getQualifier());
452
}
453
454
public final boolean inSamePackage(Identifier packageName) {
455
return (getName().getQualifier().equals(packageName));
456
}
457
458
/**
459
* Checks
460
*/
461
public final boolean isInterface() {
462
return (getModifiers() & M_INTERFACE) != 0;
463
}
464
public final boolean isClass() {
465
return (getModifiers() & M_INTERFACE) == 0;
466
}
467
public final boolean isPublic() {
468
return (getModifiers() & M_PUBLIC) != 0;
469
}
470
public final boolean isPrivate() {
471
return (getModifiers() & M_PRIVATE) != 0;
472
}
473
public final boolean isProtected() {
474
return (getModifiers() & M_PROTECTED) != 0;
475
}
476
public final boolean isPackagePrivate() {
477
return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;
478
}
479
public final boolean isFinal() {
480
return (getModifiers() & M_FINAL) != 0;
481
}
482
public final boolean isAbstract() {
483
return (getModifiers() & M_ABSTRACT) != 0;
484
}
485
public final boolean isSynthetic() {
486
return (getModifiers() & M_SYNTHETIC) != 0;
487
}
488
public final boolean isDeprecated() {
489
return (getModifiers() & M_DEPRECATED) != 0;
490
}
491
public final boolean isAnonymous() {
492
return (getModifiers() & M_ANONYMOUS) != 0;
493
}
494
public final boolean isLocal() {
495
return (getModifiers() & M_LOCAL) != 0;
496
}
497
public final boolean hasConstructor() {
498
return getFirstMatch(idInit) != null;
499
}
500
501
502
/**
503
* Check to see if a class must be abstract. This method replaces
504
* isAbstract(env)
505
*/
506
public final boolean mustBeAbstract(Environment env) {
507
// If it is declared abstract, return true.
508
// (Fix for 4110534.)
509
if (isAbstract()) {
510
return true;
511
}
512
513
// Check to see if the class should have been declared to be
514
// abstract.
515
516
// We make sure that the inherited method collection has been
517
// performed.
518
collectInheritedMethods(env);
519
520
// We check for any abstract methods inherited or declared
521
// by this class.
522
Iterator methods = getMethods();
523
while (methods.hasNext()) {
524
MemberDefinition method = (MemberDefinition) methods.next();
525
526
if (method.isAbstract()) {
527
return true;
528
}
529
}
530
531
// We check for hidden "permanently abstract" methods in
532
// our superclasses.
533
return getPermanentlyAbstractMethods().hasNext();
534
}
535
536
/**
537
* Check if this is a super class of another class
538
*/
539
public boolean superClassOf(Environment env, ClassDeclaration otherClass)
540
throws ClassNotFound {
541
while (otherClass != null) {
542
if (getClassDeclaration().equals(otherClass)) {
543
return true;
544
}
545
otherClass = otherClass.getClassDefinition(env).getSuperClass();
546
}
547
return false;
548
}
549
550
/**
551
* Check if this is an enclosing class of another class
552
*/
553
public boolean enclosingClassOf(ClassDefinition otherClass) {
554
while ((otherClass = otherClass.getOuterClass()) != null) {
555
if (this == otherClass) {
556
return true;
557
}
558
}
559
return false;
560
}
561
562
/**
563
* Check if this is a sub class of another class
564
*/
565
public boolean subClassOf(Environment env, ClassDeclaration otherClass) throws ClassNotFound {
566
ClassDeclaration c = getClassDeclaration();
567
while (c != null) {
568
if (c.equals(otherClass)) {
569
return true;
570
}
571
c = c.getClassDefinition(env).getSuperClass();
572
}
573
return false;
574
}
575
576
/**
577
* Check if this class is implemented by another class
578
*/
579
public boolean implementedBy(Environment env, ClassDeclaration c) throws ClassNotFound {
580
for (; c != null ; c = c.getClassDefinition(env).getSuperClass()) {
581
if (getClassDeclaration().equals(c)) {
582
return true;
583
}
584
ClassDeclaration intf[] = c.getClassDefinition(env).getInterfaces();
585
for (int i = 0 ; i < intf.length ; i++) {
586
if (implementedBy(env, intf[i])) {
587
return true;
588
}
589
}
590
}
591
return false;
592
}
593
594
/**
595
* Check to see if a class which implements interface `this' could
596
* possibly implement the interface `intDef'. Note that the only
597
* way that this can fail is if `this' and `intDef' have methods
598
* which are of the same signature and different return types. This
599
* method is used by Environment.explicitCast() to determine if a
600
* cast between two interfaces is legal.
601
*
602
* This method should only be called on a class after it has been
603
* basicCheck()'ed.
604
*/
605
public boolean couldImplement(ClassDefinition intDef) {
606
// Check to see if we could have done the necessary checks.
607
if (!doInheritanceChecks) {
608
throw new CompilerError("couldImplement: no checks");
609
}
610
611
// This method should only be called for interfaces.
612
if (!isInterface() || !intDef.isInterface()) {
613
throw new CompilerError("couldImplement: not interface");
614
}
615
616
// Make sure we are not called before we have collected our
617
// inheritance information.
618
if (allMethods == null) {
619
throw new CompilerError("couldImplement: called early");
620
}
621
622
// Get the other classes' methods. getMethods() in
623
// general can return methods which are not visible to the
624
// current package. We need to make sure that these do not
625
// prevent this class from being implemented.
626
Iterator otherMethods = intDef.getMethods();
627
628
while (otherMethods.hasNext()) {
629
// Get one of the methods from intDef...
630
MemberDefinition method =
631
(MemberDefinition) otherMethods.next();
632
633
Identifier name = method.getName();
634
Type type = method.getType();
635
636
// See if we implement a method of the same signature...
637
MemberDefinition myMethod = allMethods.lookupSig(name, type);
638
639
//System.out.println("Comparing\n\t" + myMethod +
640
// "\nand\n\t" + method);
641
642
if (myMethod != null) {
643
// We do. Make sure the methods have the same return type.
644
if (!myMethod.sameReturnType(method)) {
645
return false;
646
}
647
}
648
}
649
650
return true;
651
}
652
653
/**
654
* Check if another class can be accessed from the 'extends' or 'implements'
655
* clause of this class.
656
*/
657
public boolean extendsCanAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
658
659
// Names in the 'extends' or 'implements' clause of an inner class
660
// are checked as if they appeared in the body of the surrounding class.
661
if (outerClass != null) {
662
return outerClass.canAccess(env, c);
663
}
664
665
// We are a package member.
666
667
ClassDefinition cdef = c.getClassDefinition(env);
668
669
if (cdef.isLocal()) {
670
// No locals should be in scope in the 'extends' or
671
// 'implements' clause of a package member.
672
throw new CompilerError("top local");
673
}
674
675
if (cdef.isInnerClass()) {
676
MemberDefinition f = cdef.getInnerClassMember();
677
678
// Access to public member is always allowed.
679
if (f.isPublic()) {
680
return true;
681
}
682
683
// Private access is ok only from the same class nest. This can
684
// happen only if the class represented by 'this' encloses the inner
685
// class represented by 'f'.
686
if (f.isPrivate()) {
687
return getClassDeclaration().equals(f.getTopClass().getClassDeclaration());
688
}
689
690
// Protected or default access -- allow access if in same package.
691
return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
692
}
693
694
// Access to public member is always allowed.
695
if (cdef.isPublic()) {
696
return true;
697
}
698
699
// Default access -- allow access if in same package.
700
return getName().getQualifier().equals(c.getName().getQualifier());
701
}
702
703
/**
704
* Check if another class can be accessed from within the body of this class.
705
*/
706
public boolean canAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
707
ClassDefinition cdef = c.getClassDefinition(env);
708
709
if (cdef.isLocal()) {
710
// if it's in scope, it's accessible
711
return true;
712
}
713
714
if (cdef.isInnerClass()) {
715
return canAccess(env, cdef.getInnerClassMember());
716
}
717
718
// Public access is always ok
719
if (cdef.isPublic()) {
720
return true;
721
}
722
723
// It must be in the same package
724
return getName().getQualifier().equals(c.getName().getQualifier());
725
}
726
727
/**
728
* Check if a field can be accessed from a class
729
*/
730
731
public boolean canAccess(Environment env, MemberDefinition f)
732
throws ClassNotFound {
733
734
// Public access is always ok
735
if (f.isPublic()) {
736
return true;
737
}
738
// Protected access is ok from a subclass
739
if (f.isProtected() && subClassOf(env, f.getClassDeclaration())) {
740
return true;
741
}
742
// Private access is ok only from the same class nest
743
if (f.isPrivate()) {
744
return getTopClass().getClassDeclaration()
745
.equals(f.getTopClass().getClassDeclaration());
746
}
747
// It must be in the same package
748
return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
749
}
750
751
/**
752
* Check if a class is entitled to inline access to a class from
753
* another class.
754
*/
755
public boolean permitInlinedAccess(Environment env, ClassDeclaration c)
756
throws ClassNotFound {
757
758
return (env.opt() && c.equals(declaration)) ||
759
(env.opt_interclass() && canAccess(env, c));
760
}
761
762
/**
763
* Check if a class is entitled to inline access to a method from
764
* another class.
765
*/
766
public boolean permitInlinedAccess(Environment env, MemberDefinition f)
767
throws ClassNotFound {
768
return (env.opt()
769
&& (f.clazz.getClassDeclaration().equals(declaration))) ||
770
(env.opt_interclass() && canAccess(env, f));
771
}
772
773
/**
774
* We know the the field is marked protected (and not public) and that
775
* the field is visible (as per canAccess). Can we access the field as
776
* <accessor>.<field>, where <accessor> has the type <accessorType>?
777
*
778
* Protected fields can only be accessed when the accessorType is a
779
* subclass of the current class
780
*/
781
public boolean protectedAccess(Environment env, MemberDefinition f,
782
Type accessorType)
783
throws ClassNotFound
784
{
785
786
return
787
// static protected fields are accessible
788
f.isStatic()
789
|| // allow array.clone()
790
(accessorType.isType(TC_ARRAY) && (f.getName() == idClone)
791
&& (f.getType().getArgumentTypes().length == 0))
792
|| // <accessorType> is a subtype of the current class
793
(accessorType.isType(TC_CLASS)
794
&& env.getClassDefinition(accessorType.getClassName())
795
.subClassOf(env, getClassDeclaration()))
796
|| // we are accessing the field from a friendly class (same package)
797
(getName().getQualifier()
798
.equals(f.getClassDeclaration().getName().getQualifier()));
799
}
800
801
802
/**
803
* Find or create an access method for a private member,
804
* or return null if this is not possible.
805
*/
806
public MemberDefinition getAccessMember(Environment env, Context ctx,
807
MemberDefinition field, boolean isSuper) {
808
throw new CompilerError("binary getAccessMember");
809
}
810
811
/**
812
* Find or create an update method for a private member,
813
* or return null if this is not possible.
814
*/
815
public MemberDefinition getUpdateMember(Environment env, Context ctx,
816
MemberDefinition field, boolean isSuper) {
817
throw new CompilerError("binary getUpdateMember");
818
}
819
820
/**
821
* Get a field from this class. Report ambiguous fields.
822
* If no accessible field is found, this method may return an
823
* inaccessible field to allow a useful error message.
824
*
825
* getVariable now takes the source class `source' as an argument.
826
* This allows getVariable to check whether a field is inaccessible
827
* before it signals that a field is ambiguous. The compiler used to
828
* signal an ambiguity even when one of the fields involved was not
829
* accessible. (bug 4053724)
830
*/
831
public MemberDefinition getVariable(Environment env,
832
Identifier nm,
833
ClassDefinition source)
834
throws AmbiguousMember, ClassNotFound {
835
836
return getVariable0(env, nm, source, true, true);
837
}
838
839
/*
840
* private fields are never inherited. package-private fields are
841
* not inherited across package boundaries. To capture this, we
842
* take two booleans as parameters: showPrivate indicates whether
843
* we have passed a class boundary, and showPackage indicates whether
844
* we have crossed a package boundary.
845
*/
846
private MemberDefinition getVariable0(Environment env,
847
Identifier nm,
848
ClassDefinition source,
849
boolean showPrivate,
850
boolean showPackage)
851
throws AmbiguousMember, ClassNotFound {
852
853
// Check to see if this field is defined in the current class
854
for (MemberDefinition member = getFirstMatch(nm);
855
member != null;
856
member = member.getNextMatch()) {
857
if (member.isVariable()) {
858
if ((showPrivate || !member.isPrivate()) &&
859
(showPackage || !member.isPackagePrivate())) {
860
// It is defined in this class.
861
return member;
862
} else {
863
// Even though this definition is not inherited,
864
// it hides all definitions in supertypes.
865
return null;
866
}
867
}
868
}
869
870
// Find the field in our superclass.
871
ClassDeclaration sup = getSuperClass();
872
MemberDefinition field = null;
873
if (sup != null) {
874
field =
875
sup.getClassDefinition(env)
876
.getVariable0(env, nm, source,
877
false,
878
showPackage && inSamePackage(sup));
879
}
880
881
// Find the field in our superinterfaces.
882
for (int i = 0 ; i < interfaces.length ; i++) {
883
// Try to look up the field in an interface. Since interfaces
884
// only have public fields, the values of the two boolean
885
// arguments are not important.
886
MemberDefinition field2 =
887
interfaces[i].getClassDefinition(env)
888
.getVariable0(env, nm, source, true, true);
889
890
if (field2 != null) {
891
// If we have two different, accessible fields, then
892
// we've found an ambiguity.
893
if (field != null &&
894
source.canAccess(env, field) &&
895
field2 != field) {
896
897
throw new AmbiguousMember(field2, field);
898
}
899
field = field2;
900
}
901
}
902
return field;
903
}
904
905
/**
906
* Tells whether to report a deprecation error for this class.
907
*/
908
public boolean reportDeprecated(Environment env) {
909
return (isDeprecated()
910
|| (outerClass != null && outerClass.reportDeprecated(env)));
911
}
912
913
/**
914
* Note that this class is being used somehow by <tt>ref</tt>.
915
* Report deprecation errors, etc.
916
*/
917
public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
918
// (Have this deal with canAccess() checks, too?)
919
if (reportDeprecated(env)) {
920
env.error(where, "warn.class.is.deprecated", this);
921
}
922
}
923
924
/**
925
* Get an inner class.
926
* Look in supers but not outers.
927
* (This is used directly to resolve expressions like "site.K", and
928
* inside a loop to resolve lone names like "K" or the "K" in "K.L".)
929
*
930
* Called from 'Context' and 'FieldExpression' as well as this class.
931
*
932
* @see FieldExpression.checkCommon
933
* @see resolveName
934
*/
935
public MemberDefinition getInnerClass(Environment env, Identifier nm)
936
throws ClassNotFound {
937
// Note: AmbiguousClass will not be thrown unless and until
938
// inner classes can be defined inside interfaces.
939
940
// Check if it is defined in the current class
941
for (MemberDefinition field = getFirstMatch(nm);
942
field != null ; field = field.getNextMatch()) {
943
if (field.isInnerClass()) {
944
if (field.getInnerClass().isLocal()) {
945
continue; // ignore this name; it is internally generated
946
}
947
return field;
948
}
949
}
950
951
// Get it from the super class
952
// It is likely that 'getSuperClass()' could be made to work here
953
// but we would have to assure somehow that 'resolveTypeStructure'
954
// has been called on the current class nest. Since we can get
955
// here from 'resolveName', which is called from 'resolveSupers',
956
// it is possible that the first attempt to resolve the superclass
957
// will originate here, instead of in the call to 'getSuperClass'
958
// in 'checkSupers'. See 'resolveTypeStructure', in which a call
959
// to 'resolveSupers' precedes the call to 'checkSupers'. Why is
960
// name resolution done twice, first in 'resolveName'?
961
// NOTE: 'SourceMember.resolveTypeStructure' may initiate type
962
// structure resolution for an inner class. Normally, this
963
// occurs during the resolution of the outer class, but fields
964
// added after the resolution of their containing class will
965
// be resolved late -- see 'addMember(env,field)' below.
966
// This should only happen for synthetic members, which should
967
// never be an inner class.
968
ClassDeclaration sup = getSuperClass(env);
969
if (sup != null)
970
return sup.getClassDefinition(env).getInnerClass(env, nm);
971
972
return null;
973
}
974
975
/**
976
* Lookup a method. This code implements the method lookup
977
* mechanism specified in JLS 15.11.2.
978
*
979
* This mechanism cannot be used to lookup synthetic methods.
980
*/
981
private MemberDefinition matchMethod(Environment env,
982
ClassDefinition accessor,
983
Identifier methodName,
984
Type[] argumentTypes,
985
boolean isAnonConstCall,
986
Identifier accessPackage)
987
throws AmbiguousMember, ClassNotFound {
988
989
if (allMethods == null || !allMethods.isFrozen()) {
990
// This may be too restrictive.
991
throw new CompilerError("matchMethod called early");
992
// collectInheritedMethods(env);
993
}
994
995
// A tentative maximally specific method.
996
MemberDefinition tentative = null;
997
998
// A list of other methods which may be maximally specific too.
999
List candidateList = null;
1000
1001
// Get all the methods inherited by this class which
1002
// have the name `methodName'.
1003
Iterator methods = allMethods.lookupName(methodName);
1004
1005
while (methods.hasNext()) {
1006
MemberDefinition method = (MemberDefinition)methods.next();
1007
1008
// See if this method is applicable.
1009
if (!env.isApplicable(method, argumentTypes)) {
1010
continue;
1011
}
1012
1013
// See if this method is accessible.
1014
if (accessor != null) {
1015
if (!accessor.canAccess(env, method)) {
1016
continue;
1017
}
1018
} else if (isAnonConstCall) {
1019
if (method.isPrivate() ||
1020
(method.isPackagePrivate() &&
1021
accessPackage != null &&
1022
!inSamePackage(accessPackage))) {
1023
// For anonymous constructor accesses, we
1024
// haven't yet built an accessing class.
1025
// We disallow anonymous classes from seeing
1026
// private/package-private inaccessible
1027
// constructors in their superclass.
1028
continue;
1029
}
1030
} else {
1031
// If accessor is null, we assume that the access
1032
// is allowed. Query: is this option used?
1033
}
1034
1035
if (tentative == null) {
1036
// `method' becomes our tentative maximally specific match.
1037
tentative = method;
1038
} else {
1039
if (env.isMoreSpecific(method, tentative)) {
1040
// We have found a method which is a strictly better
1041
// match than `tentative'. Replace it.
1042
tentative = method;
1043
} else {
1044
// If this method could possibly be another
1045
// maximally specific method, add it to our
1046
// list of other candidates.
1047
if (!env.isMoreSpecific(tentative,method)) {
1048
if (candidateList == null) {
1049
candidateList = new ArrayList();
1050
}
1051
candidateList.add(method);
1052
}
1053
}
1054
}
1055
}
1056
1057
if (tentative != null && candidateList != null) {
1058
// Find out if our `tentative' match is a uniquely
1059
// maximally specific.
1060
Iterator candidates = candidateList.iterator();
1061
while (candidates.hasNext()) {
1062
MemberDefinition method = (MemberDefinition)candidates.next();
1063
if (!env.isMoreSpecific(tentative, method)) {
1064
throw new AmbiguousMember(tentative, method);
1065
}
1066
}
1067
}
1068
1069
return tentative;
1070
}
1071
1072
/**
1073
* Lookup a method. This code implements the method lookup
1074
* mechanism specified in JLS 15.11.2.
1075
*
1076
* This mechanism cannot be used to lookup synthetic methods.
1077
*/
1078
public MemberDefinition matchMethod(Environment env,
1079
ClassDefinition accessor,
1080
Identifier methodName,
1081
Type[] argumentTypes)
1082
throws AmbiguousMember, ClassNotFound {
1083
1084
return matchMethod(env, accessor, methodName,
1085
argumentTypes, false, null);
1086
}
1087
1088
/**
1089
* Lookup a method. This code implements the method lookup
1090
* mechanism specified in JLS 15.11.2.
1091
*
1092
* This mechanism cannot be used to lookup synthetic methods.
1093
*/
1094
public MemberDefinition matchMethod(Environment env,
1095
ClassDefinition accessor,
1096
Identifier methodName)
1097
throws AmbiguousMember, ClassNotFound {
1098
1099
return matchMethod(env, accessor, methodName,
1100
Type.noArgs, false, null);
1101
}
1102
1103
/**
1104
* A version of matchMethod to be used only for constructors
1105
* when we cannot pass in a sourceClass argument. We just assert
1106
* our package name.
1107
*
1108
* This is used only for anonymous classes, where we have to look up
1109
* a (potentially) protected constructor with no valid sourceClass
1110
* parameter available.
1111
*/
1112
public MemberDefinition matchAnonConstructor(Environment env,
1113
Identifier accessPackage,
1114
Type argumentTypes[])
1115
throws AmbiguousMember, ClassNotFound {
1116
1117
return matchMethod(env, null, idInit, argumentTypes,
1118
true, accessPackage);
1119
}
1120
1121
/**
1122
* Find a method, ie: exact match in this class or any of the super
1123
* classes.
1124
*
1125
* Only called by javadoc. For now I am holding off rewriting this
1126
* code to rely on collectInheritedMethods(), as that code has
1127
* not gotten along with javadoc in the past.
1128
*/
1129
public MemberDefinition findMethod(Environment env, Identifier nm, Type t)
1130
throws ClassNotFound {
1131
// look in the current class
1132
MemberDefinition f;
1133
for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1134
// Note that non-method types return false for equalArguments().
1135
if (f.getType().equalArguments(t)) {
1136
return f;
1137
}
1138
}
1139
1140
// constructors are not inherited
1141
if (nm.equals(idInit)) {
1142
return null;
1143
}
1144
1145
// look in the super class
1146
ClassDeclaration sup = getSuperClass();
1147
if (sup == null)
1148
return null;
1149
1150
return sup.getClassDefinition(env).findMethod(env, nm, t);
1151
}
1152
1153
// We create a stub for this. Source classes do more work.
1154
protected void basicCheck(Environment env) throws ClassNotFound {
1155
// Do the outer class first.
1156
if (outerClass != null)
1157
outerClass.basicCheck(env);
1158
}
1159
1160
/**
1161
* Check this class.
1162
*/
1163
public void check(Environment env) throws ClassNotFound {
1164
}
1165
1166
public Vset checkLocalClass(Environment env, Context ctx,
1167
Vset vset, ClassDefinition sup,
1168
Expression args[], Type argTypes[]
1169
) throws ClassNotFound {
1170
throw new CompilerError("checkLocalClass");
1171
}
1172
1173
//---------------------------------------------------------------
1174
// The non-synthetic methods defined in this class or in any
1175
// of its parents (class or interface). This member is used
1176
// to cache work done in collectInheritedMethods for use by
1177
// getMethods() and matchMethod(). It should be accessed by
1178
// no other method without forethought.
1179
MethodSet allMethods = null;
1180
1181
// One of our superclasses may contain an abstract method which
1182
// we are unable to ever implement. This happens when there is
1183
// a package-private abstract method in our parent and we are in
1184
// a different package than our parent. In these cases, we
1185
// keep a list of the "permanently abstract" or "unimplementable"
1186
// methods so that we can correctly detect that this class is
1187
// indeed abstract and so that we can give somewhat comprehensible
1188
// error messages.
1189
private List permanentlyAbstractMethods = new ArrayList();
1190
1191
/**
1192
* This method returns an Iterator of all abstract methods
1193
* in our superclasses which we are unable to implement.
1194
*/
1195
protected Iterator getPermanentlyAbstractMethods() {
1196
// This method can only be called after collectInheritedMethods.
1197
if (allMethods == null) {
1198
throw new CompilerError("isPermanentlyAbstract() called early");
1199
}
1200
1201
return permanentlyAbstractMethods.iterator();
1202
}
1203
1204
/**
1205
* A flag used by turnOffInheritanceChecks() to indicate if
1206
* inheritance checks are on or off.
1207
*/
1208
protected static boolean doInheritanceChecks = true;
1209
1210
/**
1211
* This is a workaround to allow javadoc to turn off certain
1212
* inheritance/override checks which interfere with javadoc
1213
* badly. In the future it might be good to eliminate the
1214
* shared sources of javadoc and javac to avoid the need for this
1215
* sort of workaround.
1216
*/
1217
public static void turnOffInheritanceChecks() {
1218
doInheritanceChecks = false;
1219
}
1220
1221
/**
1222
* Add all of the methods declared in or above `parent' to
1223
* `allMethods', the set of methods in the current class.
1224
* `myMethods' is the set of all methods declared in this
1225
* class, and `mirandaMethods' is a repository for Miranda methods.
1226
* If mirandaMethods is null, no mirandaMethods will be
1227
* generated.
1228
*
1229
* For a definition of Miranda methods, see the comment above the
1230
* method addMirandaMethods() which occurs later in this file.
1231
*/
1232
private void collectOneClass(Environment env,
1233
ClassDeclaration parent,
1234
MethodSet myMethods,
1235
MethodSet allMethods,
1236
MethodSet mirandaMethods) {
1237
1238
// System.out.println("Inheriting methods from " + parent);
1239
1240
try {
1241
ClassDefinition pClass = parent.getClassDefinition(env);
1242
Iterator methods = pClass.getMethods(env);
1243
while (methods.hasNext()) {
1244
MemberDefinition method =
1245
(MemberDefinition) methods.next();
1246
1247
// Private methods are not inherited.
1248
//
1249
// Constructors are not inherited.
1250
//
1251
// Any non-abstract methods in an interface come
1252
// from java.lang.Object. This means that they
1253
// should have already been added to allMethods
1254
// when we walked our superclass lineage.
1255
if (method.isPrivate() ||
1256
method.isConstructor() ||
1257
(pClass.isInterface() && !method.isAbstract())) {
1258
1259
continue;
1260
}
1261
1262
// Get the components of the methods' signature.
1263
Identifier name = method.getName();
1264
Type type = method.getType();
1265
1266
// Check for a method of the same signature which
1267
// was locally declared.
1268
MemberDefinition override =
1269
myMethods.lookupSig(name, type);
1270
1271
// Is this method inaccessible due to package-private
1272
// visibility?
1273
if (method.isPackagePrivate() &&
1274
!inSamePackage(method.getClassDeclaration())) {
1275
1276
if (override != null && this instanceof
1277
sun.tools.javac.SourceClass) {
1278
// We give a warning when a class shadows an
1279
// inaccessible package-private method from
1280
// its superclass. This warning is meant
1281
// to prevent people from relying on overriding
1282
// when it does not happen. This warning should
1283
// probably be removed to be consistent with the
1284
// general "no warnings" policy of this
1285
// compiler.
1286
//
1287
// The `instanceof' above is a hack so that only
1288
// SourceClass generates this warning, not a
1289
// BinaryClass, for example.
1290
env.error(method.getWhere(),
1291
"warn.no.override.access",
1292
override,
1293
override.getClassDeclaration(),
1294
method.getClassDeclaration());
1295
}
1296
1297
// If our superclass has a package-private abstract
1298
// method that we have no access to, then we add
1299
// this method to our list of permanently abstract
1300
// methods. The idea is, since we cannot override
1301
// the method, we can never make this class
1302
// non-abstract.
1303
if (method.isAbstract()) {
1304
permanentlyAbstractMethods.add(method);
1305
}
1306
1307
// `method' is inaccessible. We do not inherit it.
1308
continue;
1309
}
1310
1311
if (override != null) {
1312
// `method' and `override' have the same signature.
1313
// We are required to check that `override' is a
1314
// legal override of `method'
1315
1316
//System.out.println ("About to check override of " +
1317
// method);
1318
1319
override.checkOverride(env, method);
1320
} else {
1321
// In the absence of a definition in the class
1322
// itself, we check to see if this definition
1323
// can be successfully merged with any other
1324
// inherited definitions.
1325
1326
// Have we added a member of the same signature
1327
// to `allMethods' already?
1328
MemberDefinition formerMethod =
1329
allMethods.lookupSig(name, type);
1330
1331
// If the previous definition is nonexistent or
1332
// ignorable, replace it.
1333
if (formerMethod == null) {
1334
//System.out.println("Added " + method + " to " +
1335
// this);
1336
1337
if (mirandaMethods != null &&
1338
pClass.isInterface() && !isInterface()) {
1339
// Whenever a class inherits a method
1340
// from an interface, that method is
1341
// one of our "miranda" methods. Early
1342
// VMs require that these methods be
1343
// added as true members to the class
1344
// to enable method lookup to work in the
1345
// VM.
1346
method =
1347
new sun.tools.javac.SourceMember(method,this,
1348
env);
1349
mirandaMethods.add(method);
1350
1351
//System.out.println("Added " + method +
1352
// " to " + this + " as a Miranda");
1353
}
1354
1355
// There is no previous inherited definition.
1356
// Add `method' to `allMethods'.
1357
allMethods.add(method);
1358
} else if (isInterface() &&
1359
!formerMethod.isAbstract() &&
1360
method.isAbstract()) {
1361
// If we are in an interface and we have inherited
1362
// both an abstract method and a non-abstract method
1363
// then we know that the non-abstract method is
1364
// a placeholder from Object put in for type checking
1365
// and the abstract method was already checked to
1366
// be proper by our superinterface.
1367
allMethods.replace(method);
1368
1369
} else {
1370
// Okay, `formerMethod' and `method' both have the
1371
// same signature. See if they are compatible.
1372
1373
//System.out.println ("About to check meet of " +
1374
// method);
1375
1376
if (!formerMethod.checkMeet(env,
1377
method,
1378
this.getClassDeclaration())) {
1379
// The methods are incompatible. Skip to
1380
// next method.
1381
continue;
1382
}
1383
1384
if (formerMethod.couldOverride(env, method)) {
1385
// Do nothing. The current definition
1386
// is specific enough.
1387
1388
//System.out.println("trivial meet of " +
1389
// method);
1390
continue;
1391
}
1392
1393
if (method.couldOverride(env, formerMethod)) {
1394
// `method' is more specific than
1395
// `formerMethod'. replace `formerMethod'.
1396
1397
//System.out.println("new def of " + method);
1398
if (mirandaMethods != null &&
1399
pClass.isInterface() && !isInterface()) {
1400
// Whenever a class inherits a method
1401
// from an interface, that method is
1402
// one of our "miranda" methods. Early
1403
// VMs require that these methods be
1404
// added as true members to the class
1405
// to enable method lookup to work in the
1406
// VM.
1407
method =
1408
new sun.tools.javac.SourceMember(method,
1409
this,env);
1410
1411
mirandaMethods.replace(method);
1412
1413
//System.out.println("Added " + method +
1414
// " to " + this + " as a Miranda");
1415
}
1416
1417
allMethods.replace(method);
1418
1419
continue;
1420
}
1421
1422
// Neither method is more specific than the other.
1423
// Oh well. We need to construct a nontrivial
1424
// meet of the two methods.
1425
//
1426
// This is not yet implemented, so we give
1427
// a message with a helpful workaround.
1428
env.error(this.where,
1429
"nontrivial.meet", method,
1430
formerMethod.getClassDefinition(),
1431
method.getClassDeclaration()
1432
);
1433
}
1434
}
1435
}
1436
} catch (ClassNotFound ee) {
1437
env.error(getWhere(), "class.not.found", ee.name, this);
1438
}
1439
}
1440
1441
/**
1442
* <p>Collect all methods defined in this class or inherited from
1443
* any of our superclasses or interfaces. Look for any
1444
* incompatible definitions.
1445
*
1446
* <p>This function is also responsible for collecting the
1447
* <em>Miranda</em> methods for a class. For a definition of
1448
* Miranda methods, see the comment in addMirandaMethods()
1449
* below.
1450
*/
1451
protected void collectInheritedMethods(Environment env) {
1452
// The methods defined in this class.
1453
MethodSet myMethods;
1454
MethodSet mirandaMethods;
1455
1456
//System.out.println("Called collectInheritedMethods() for " +
1457
// this);
1458
1459
if (allMethods != null) {
1460
if (allMethods.isFrozen()) {
1461
// We have already done the collection. No need to
1462
// do it again.
1463
return;
1464
} else {
1465
// We have run into a circular need to collect our methods.
1466
// This should not happen at this stage.
1467
throw new CompilerError("collectInheritedMethods()");
1468
}
1469
}
1470
1471
myMethods = new MethodSet();
1472
allMethods = new MethodSet();
1473
1474
// For testing, do not generate miranda methods.
1475
if (env.version12()) {
1476
mirandaMethods = null;
1477
} else {
1478
mirandaMethods = new MethodSet();
1479
}
1480
1481
// Any methods defined in the current class get added
1482
// to both the myMethods and the allMethods MethodSets.
1483
1484
for (MemberDefinition member = getFirstMember();
1485
member != null;
1486
member = member.nextMember) {
1487
1488
// We only collect methods. Initializers are not relevant.
1489
if (member.isMethod() &&
1490
!member.isInitializer()) {
1491
1492
//System.out.println("Declared in " + this + ", " + member);
1493
1494
////////////////////////////////////////////////////////////
1495
// PCJ 2003-07-30 modified the following code because with
1496
// the covariant return type feature of the 1.5 compiler,
1497
// there might be multiple methods with the same signature
1498
// but different return types, and MethodSet doesn't
1499
// support that. We use a new utility method that attempts
1500
// to ensure that the appropriate method winds up in the
1501
// MethodSet. See 4892308.
1502
////////////////////////////////////////////////////////////
1503
// myMethods.add(member);
1504
// allMethods.add(member);
1505
////////////////////////////////////////////////////////////
1506
methodSetAdd(env, myMethods, member);
1507
methodSetAdd(env, allMethods, member);
1508
////////////////////////////////////////////////////////////
1509
}
1510
}
1511
1512
// We're ready to start adding inherited methods. First add
1513
// the methods from our superclass.
1514
1515
//System.out.println("About to start superclasses for " + this);
1516
1517
ClassDeclaration scDecl = getSuperClass(env);
1518
if (scDecl != null) {
1519
collectOneClass(env, scDecl,
1520
myMethods, allMethods, mirandaMethods);
1521
1522
// Make sure that we add all unimplementable methods from our
1523
// superclass to our list of unimplementable methods.
1524
ClassDefinition sc = scDecl.getClassDefinition();
1525
Iterator supIter = sc.getPermanentlyAbstractMethods();
1526
while (supIter.hasNext()) {
1527
permanentlyAbstractMethods.add(supIter.next());
1528
}
1529
}
1530
1531
// Now we inherit all of the methods from our interfaces.
1532
1533
//System.out.println("About to start interfaces for " + this);
1534
1535
for (int i = 0; i < interfaces.length; i++) {
1536
collectOneClass(env, interfaces[i],
1537
myMethods, allMethods, mirandaMethods);
1538
}
1539
allMethods.freeze();
1540
1541
// Now we have collected all of our methods from our superclasses
1542
// and interfaces into our `allMethods' member. Good. As a last
1543
// task, we add our collected miranda methods to this class.
1544
//
1545
// If we do not add the mirandas to the class explicitly, there
1546
// will be no code generated for them.
1547
if (mirandaMethods != null && mirandaMethods.size() > 0) {
1548
addMirandaMethods(env, mirandaMethods.iterator());
1549
}
1550
}
1551
1552
////////////////////////////////////////////////////////////
1553
// PCJ 2003-07-30 added this utility method to insulate
1554
// MethodSet additions from the covariant return type
1555
// feature of the 1.5 compiler. When there are multiple
1556
// methods with the same signature and different return
1557
// types to be added, we try to ensure that the one with
1558
// the most specific return type winds up in the MethodSet.
1559
// This logic was not put into MethodSet itself because it
1560
// requires access to an Environment for type relationship
1561
// checking. No error checking is performed here, but that
1562
// should be OK because this code is only still used by
1563
// rmic. See 4892308.
1564
////////////////////////////////////////////////////////////
1565
private static void methodSetAdd(Environment env,
1566
MethodSet methodSet,
1567
MemberDefinition newMethod)
1568
{
1569
MemberDefinition oldMethod = methodSet.lookupSig(newMethod.getName(),
1570
newMethod.getType());
1571
if (oldMethod != null) {
1572
Type oldReturnType = oldMethod.getType().getReturnType();
1573
Type newReturnType = newMethod.getType().getReturnType();
1574
try {
1575
if (env.isMoreSpecific(newReturnType, oldReturnType)) {
1576
methodSet.replace(newMethod);
1577
}
1578
} catch (ClassNotFound ignore) {
1579
}
1580
} else {
1581
methodSet.add(newMethod);
1582
}
1583
}
1584
////////////////////////////////////////////////////////////
1585
1586
/**
1587
* Get an Iterator of all methods which could be accessed in an
1588
* instance of this class.
1589
*/
1590
public Iterator getMethods(Environment env) {
1591
if (allMethods == null) {
1592
collectInheritedMethods(env);
1593
}
1594
return getMethods();
1595
}
1596
1597
/**
1598
* Get an Iterator of all methods which could be accessed in an
1599
* instance of this class. Throw a compiler error if we haven't
1600
* generated this information yet.
1601
*/
1602
public Iterator getMethods() {
1603
if (allMethods == null) {
1604
throw new CompilerError("getMethods: too early");
1605
}
1606
return allMethods.iterator();
1607
}
1608
1609
// In early VM's there was a bug -- the VM didn't walk the interfaces
1610
// of a class looking for a method, they only walked the superclass
1611
// chain. This meant that abstract methods defined only in interfaces
1612
// were not being found. To fix this bug, a counter-bug was introduced
1613
// in the compiler -- the so-called Miranda methods. If a class
1614
// does not provide a definition for an abstract method in one of
1615
// its interfaces then the compiler inserts one in the class artificially.
1616
// That way the VM didn't have to bother looking at the interfaces.
1617
//
1618
// This is a problem. Miranda methods are not part of the specification.
1619
// But they continue to be inserted so that old VM's can run new code.
1620
// Someday, when the old VM's are gone, perhaps classes can be compiled
1621
// without Miranda methods. Towards this end, the compiler has a
1622
// flag, -nomiranda, which can turn off the creation of these methods.
1623
// Eventually that behavior should become the default.
1624
//
1625
// Why are they called Miranda methods? Well the sentence "If the
1626
// class is not able to provide a method, then one will be provided
1627
// by the compiler" is very similar to the sentence "If you cannot
1628
// afford an attorney, one will be provided by the court," -- one
1629
// of the so-called "Miranda" rights in the United States.
1630
1631
/**
1632
* Add a list of methods to this class as miranda methods. This
1633
* gets overridden with a meaningful implementation in SourceClass.
1634
* BinaryClass should not need to do anything -- it should already
1635
* have its miranda methods and, if it doesn't, then that doesn't
1636
* affect our compilation.
1637
*/
1638
protected void addMirandaMethods(Environment env,
1639
Iterator mirandas) {
1640
// do nothing.
1641
}
1642
1643
//---------------------------------------------------------------
1644
1645
public void inlineLocalClass(Environment env) {
1646
}
1647
1648
/**
1649
* We create a stub for this. Source classes do more work.
1650
* Some calls from 'SourceClass.checkSupers' execute this method.
1651
* @see sun.tools.javac.SourceClass#resolveTypeStructure
1652
*/
1653
1654
public void resolveTypeStructure(Environment env) {
1655
}
1656
1657
/**
1658
* Look up an inner class name, from somewhere inside this class.
1659
* Since supers and outers are in scope, search them too.
1660
* <p>
1661
* If no inner class is found, env.resolveName() is then called,
1662
* to interpret the ambient package and import directives.
1663
* <p>
1664
* This routine operates on a "best-efforts" basis. If
1665
* at some point a class is not found, the partially-resolved
1666
* identifier is returned. Eventually, someone else has to
1667
* try to get the ClassDefinition and diagnose the ClassNotFound.
1668
* <p>
1669
* resolveName() looks at surrounding scopes, and hence
1670
* pulling in both inherited and uplevel types. By contrast,
1671
* resolveInnerClass() is intended only for interpreting
1672
* explicitly qualified names, and so look only at inherited
1673
* types. Also, resolveName() looks for package prefixes,
1674
* which appear similar to "very uplevel" outer classes.
1675
* <p>
1676
* A similar (but more complex) name-lookup process happens
1677
* when field and identifier expressions denoting qualified names
1678
* are type-checked. The added complexity comes from the fact
1679
* that variables may occur in such names, and take precedence
1680
* over class and package names.
1681
* <p>
1682
* In the expression type-checker, resolveInnerClass() is paralleled
1683
* by code in FieldExpression.checkAmbigName(), which also calls
1684
* ClassDefinition.getInnerClass() to interpret names of the form
1685
* "OuterClass.Inner" (and also outerObject.Inner). The checking
1686
* of an identifier expression that fails to be a variable is referred
1687
* directly to resolveName().
1688
*/
1689
public Identifier resolveName(Environment env, Identifier name) {
1690
if (tracing) env.dtEvent("ClassDefinition.resolveName: " + name);
1691
// This logic is pretty much exactly parallel to that of
1692
// Environment.resolveName().
1693
if (name.isQualified()) {
1694
// Try to resolve the first identifier component,
1695
// because inner class names take precedence over
1696
// package prefixes. (Cf. Environment.resolveName.)
1697
Identifier rhead = resolveName(env, name.getHead());
1698
1699
if (rhead.hasAmbigPrefix()) {
1700
// The first identifier component refers to an
1701
// ambiguous class. Limp on. We throw away the
1702
// rest of the classname as it is irrelevant.
1703
// (part of solution for 4059855).
1704
return rhead;
1705
}
1706
1707
if (!env.classExists(rhead)) {
1708
return env.resolvePackageQualifiedName(name);
1709
}
1710
try {
1711
return env.getClassDefinition(rhead).
1712
resolveInnerClass(env, name.getTail());
1713
} catch (ClassNotFound ee) {
1714
// return partially-resolved name someone else can fail on
1715
return Identifier.lookupInner(rhead, name.getTail());
1716
}
1717
}
1718
1719
// This method used to fail to look for local classes, thus a
1720
// reference to a local class within, e.g., the type of a member
1721
// declaration, would fail to resolve if the immediately enclosing
1722
// context was an inner class. The code added below is ugly, but
1723
// it works, and is lifted from existing code in 'Context.resolveName'
1724
// and 'Context.getClassCommon'. See the comments there about the design.
1725
// Fixes 4095716.
1726
1727
int ls = -2;
1728
LocalMember lf = null;
1729
if (classContext != null) {
1730
lf = classContext.getLocalClass(name);
1731
if (lf != null) {
1732
ls = lf.getScopeNumber();
1733
}
1734
}
1735
1736
// Look for an unqualified name in enclosing scopes.
1737
for (ClassDefinition c = this; c != null; c = c.outerClass) {
1738
try {
1739
MemberDefinition f = c.getInnerClass(env, name);
1740
if (f != null &&
1741
(lf == null || classContext.getScopeNumber(c) > ls)) {
1742
// An uplevel member was found, and was nested more deeply than
1743
// any enclosing local of the same name.
1744
return f.getInnerClass().getName();
1745
}
1746
} catch (ClassNotFound ee) {
1747
// a missing superclass, or something catastrophic
1748
}
1749
}
1750
1751
// No uplevel member found, so use the enclosing local if one was found.
1752
if (lf != null) {
1753
return lf.getInnerClass().getName();
1754
}
1755
1756
// look in imports, etc.
1757
return env.resolveName(name);
1758
}
1759
1760
/**
1761
* Interpret a qualified class name, which may have further subcomponents..
1762
* Follow inheritance links, as in:
1763
* class C { class N { } } class D extends C { } ... new D.N() ...
1764
* Ignore outer scopes and packages.
1765
* @see resolveName
1766
*/
1767
public Identifier resolveInnerClass(Environment env, Identifier nm) {
1768
if (nm.isInner()) throw new CompilerError("inner");
1769
if (nm.isQualified()) {
1770
Identifier rhead = resolveInnerClass(env, nm.getHead());
1771
try {
1772
return env.getClassDefinition(rhead).
1773
resolveInnerClass(env, nm.getTail());
1774
} catch (ClassNotFound ee) {
1775
// return partially-resolved name someone else can fail on
1776
return Identifier.lookupInner(rhead, nm.getTail());
1777
}
1778
} else {
1779
try {
1780
MemberDefinition f = getInnerClass(env, nm);
1781
if (f != null) {
1782
return f.getInnerClass().getName();
1783
}
1784
} catch (ClassNotFound ee) {
1785
// a missing superclass, or something catastrophic
1786
}
1787
// Fake a good name for a diagnostic.
1788
return Identifier.lookupInner(this.getName(), nm);
1789
}
1790
}
1791
1792
/**
1793
* While resolving import directives, the question has arisen:
1794
* does a given inner class exist? If the top-level class exists,
1795
* we ask it about an inner class via this method.
1796
* This method looks only at the literal name of the class,
1797
* and does not attempt to follow inheritance links.
1798
* This is necessary, since at the time imports are being
1799
* processed, inheritance links have not been resolved yet.
1800
* (Thus, an import directive must always spell a class
1801
* name exactly.)
1802
*/
1803
public boolean innerClassExists(Identifier nm) {
1804
for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {
1805
if (field.isInnerClass()) {
1806
if (field.getInnerClass().isLocal()) {
1807
continue; // ignore this name; it is internally generated
1808
}
1809
return !nm.isQualified() ||
1810
field.getInnerClass().innerClassExists(nm.getTail());
1811
}
1812
}
1813
return false;
1814
}
1815
1816
/**
1817
* Find any method with a given name.
1818
*/
1819
public MemberDefinition findAnyMethod(Environment env, Identifier nm) throws ClassNotFound {
1820
MemberDefinition f;
1821
for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1822
if (f.isMethod()) {
1823
return f;
1824
}
1825
}
1826
1827
// look in the super class
1828
ClassDeclaration sup = getSuperClass();
1829
if (sup == null)
1830
return null;
1831
return sup.getClassDefinition(env).findAnyMethod(env, nm);
1832
}
1833
1834
/**
1835
* Given the fact that this class has no method "nm" matching "argTypes",
1836
* find out if the mismatch can be blamed on a particular actual argument
1837
* which disagrees with all of the overloadings.
1838
* If so, return the code (i<<2)+(castOK<<1)+ambig, where
1839
* "i" is the number of the offending argument, and
1840
* "castOK" is 1 if a cast could fix the problem.
1841
* The target type for the argument is returned in margTypeResult[0].
1842
* If not all methods agree on this type, "ambig" is 1.
1843
* If there is more than one method, the choice of target type is
1844
* arbitrary.<p>
1845
* Return -1 if every argument is acceptable to at least one method.
1846
* Return -2 if there are no methods of the required arity.
1847
* The value "start" gives the index of the first argument to begin
1848
* checking.
1849
*/
1850
public int diagnoseMismatch(Environment env, Identifier nm, Type argTypes[],
1851
int start, Type margTypeResult[]) throws ClassNotFound {
1852
int haveMatch[] = new int[argTypes.length];
1853
Type margType[] = new Type[argTypes.length];
1854
if (!diagnoseMismatch(env, nm, argTypes, start, haveMatch, margType))
1855
return -2;
1856
for (int i = start; i < argTypes.length; i++) {
1857
if (haveMatch[i] < 4) {
1858
margTypeResult[0] = margType[i];
1859
return (i<<2) | haveMatch[i];
1860
}
1861
}
1862
return -1;
1863
}
1864
1865
private boolean diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start,
1866
int haveMatch[], Type margType[]) throws ClassNotFound {
1867
// look in the current class
1868
boolean haveOne = false;
1869
MemberDefinition f;
1870
for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1871
if (!f.isMethod()) {
1872
continue;
1873
}
1874
Type fArgTypes[] = f.getType().getArgumentTypes();
1875
if (fArgTypes.length == argTypes.length) {
1876
haveOne = true;
1877
for (int i = start; i < argTypes.length; i++) {
1878
Type at = argTypes[i];
1879
Type ft = fArgTypes[i];
1880
if (env.implicitCast(at, ft)) {
1881
haveMatch[i] = 4;
1882
continue;
1883
} else if (haveMatch[i] <= 2 && env.explicitCast(at, ft)) {
1884
if (haveMatch[i] < 2) margType[i] = null;
1885
haveMatch[i] = 2;
1886
} else if (haveMatch[i] > 0) {
1887
continue;
1888
}
1889
if (margType[i] == null)
1890
margType[i] = ft;
1891
else if (margType[i] != ft)
1892
haveMatch[i] |= 1;
1893
}
1894
}
1895
}
1896
1897
// constructors are not inherited
1898
if (nm.equals(idInit)) {
1899
return haveOne;
1900
}
1901
1902
// look in the super class
1903
ClassDeclaration sup = getSuperClass();
1904
if (sup != null) {
1905
if (sup.getClassDefinition(env).diagnoseMismatch(env, nm, argTypes, start,
1906
haveMatch, margType))
1907
haveOne = true;
1908
}
1909
return haveOne;
1910
}
1911
1912
/**
1913
* Add a field (no checks)
1914
*/
1915
public void addMember(MemberDefinition field) {
1916
//System.out.println("ADD = " + field);
1917
if (firstMember == null) {
1918
firstMember = lastMember = field;
1919
} else if (field.isSynthetic() && field.isFinal()
1920
&& field.isVariable()) {
1921
// insert this at the front, because of initialization order
1922
field.nextMember = firstMember;
1923
firstMember = field;
1924
field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1925
} else {
1926
lastMember.nextMember = field;
1927
lastMember = field;
1928
field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1929
}
1930
fieldHash.put(field.name, field);
1931
}
1932
1933
/**
1934
* Add a field (subclasses make checks)
1935
*/
1936
public void addMember(Environment env, MemberDefinition field) {
1937
addMember(field);
1938
if (resolved) {
1939
// a late addition
1940
field.resolveTypeStructure(env);
1941
}
1942
}
1943
1944
/**
1945
* Find or create an uplevel reference for the given target.
1946
*/
1947
public UplevelReference getReference(LocalMember target) {
1948
for (UplevelReference r = references; r != null; r = r.getNext()) {
1949
if (r.getTarget() == target) {
1950
return r;
1951
}
1952
}
1953
return addReference(target);
1954
}
1955
1956
protected UplevelReference addReference(LocalMember target) {
1957
if (target.getClassDefinition() == this) {
1958
throw new CompilerError("addReference "+target);
1959
}
1960
referencesMustNotBeFrozen();
1961
UplevelReference r = new UplevelReference(this, target);
1962
references = r.insertInto(references);
1963
return r;
1964
}
1965
1966
/**
1967
* Return the list of all uplevel references.
1968
*/
1969
public UplevelReference getReferences() {
1970
return references;
1971
}
1972
1973
/**
1974
* Return the same value as getReferences.
1975
* Also, mark the set of references frozen.
1976
* After that, it is an error to add new references.
1977
*/
1978
public UplevelReference getReferencesFrozen() {
1979
referencesFrozen = true;
1980
return references;
1981
}
1982
1983
/**
1984
* assertion check
1985
*/
1986
public final void referencesMustNotBeFrozen() {
1987
if (referencesFrozen) {
1988
throw new CompilerError("referencesMustNotBeFrozen "+this);
1989
}
1990
}
1991
1992
/**
1993
* Get helper method for class literal lookup.
1994
*/
1995
public MemberDefinition getClassLiteralLookup(long fwhere) {
1996
throw new CompilerError("binary class");
1997
}
1998
1999
/**
2000
* Add a dependency
2001
*/
2002
public void addDependency(ClassDeclaration c) {
2003
throw new CompilerError("addDependency");
2004
}
2005
2006
/**
2007
* Maintain a hash table of local and anonymous classes
2008
* whose internal names are prefixed by the current class.
2009
* The key is the simple internal name, less the prefix.
2010
*/
2011
2012
public ClassDefinition getLocalClass(String name) {
2013
if (localClasses == null) {
2014
return null;
2015
} else {
2016
return (ClassDefinition)localClasses.get(name);
2017
}
2018
}
2019
2020
public void addLocalClass(ClassDefinition c, String name) {
2021
if (localClasses == null) {
2022
localClasses = new Hashtable(LOCAL_CLASSES_SIZE);
2023
}
2024
localClasses.put(name, c);
2025
}
2026
2027
2028
/**
2029
* Print for debugging
2030
*/
2031
public void print(PrintStream out) {
2032
if (isPublic()) {
2033
out.print("public ");
2034
}
2035
if (isInterface()) {
2036
out.print("interface ");
2037
} else {
2038
out.print("class ");
2039
}
2040
out.print(getName() + " ");
2041
if (getSuperClass() != null) {
2042
out.print("extends " + getSuperClass().getName() + " ");
2043
}
2044
if (interfaces.length > 0) {
2045
out.print("implements ");
2046
for (int i = 0 ; i < interfaces.length ; i++) {
2047
if (i > 0) {
2048
out.print(", ");
2049
}
2050
out.print(interfaces[i].getName());
2051
out.print(" ");
2052
}
2053
}
2054
out.println("{");
2055
2056
for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2057
out.print(" ");
2058
f.print(out);
2059
}
2060
2061
out.println("}");
2062
}
2063
2064
/**
2065
* Convert to String
2066
*/
2067
public String toString() {
2068
return getClassDeclaration().toString();
2069
}
2070
2071
/**
2072
* After the class has been written to disk, try to free up
2073
* some storage.
2074
*/
2075
public void cleanup(Environment env) {
2076
if (env.dump()) {
2077
env.output("[cleanup " + getName() + "]");
2078
}
2079
for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2080
f.cleanup(env);
2081
}
2082
// keep "references" around, for the sake of local subclasses
2083
documentation = null;
2084
}
2085
}
2086
2087