View | Details | Raw Unified | Return to bug 288658 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java (+15 lines)
Lines 439-444 Link Here
439
				inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
439
				inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
440
			}
440
			}
441
		}
441
		}
442
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658
443
		// Generate a bridge method if a public method is inherited from a non-public class into a public class.
444
		if (current == null && this.type.isPublic()) {
445
			int length = inherited.length;
446
			for (int i = 0; i < length; i++) {
447
				MethodBinding inheritedMethod = inherited[i];
448
				if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic())
449
					this.type.addSyntheticBridgeMethod(inheritedMethod);
450
			}
451
		}
442
452
443
		if (current == null && skipInheritedMethods)
453
		if (current == null && skipInheritedMethods)
444
			continue nextSelector;
454
			continue nextSelector;
Lines 473-478 Link Here
473
		for (int i = 0, length = inherited.length; i < length; i++) {
483
		for (int i = 0, length = inherited.length; i < length; i++) {
474
			MethodBinding inheritedMethod = inherited[i];
484
			MethodBinding inheritedMethod = inherited[i];
475
			if (inheritedMethod == null) continue;
485
			if (inheritedMethod == null) continue;
486
			if (current != null && this.type.isPublic()) {
487
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658
488
				if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic())
489
					this.type.addSyntheticBridgeMethod(inheritedMethod);
490
			}
476
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
491
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
477
			// inherited methods of super classes are too. current == null case handled already.
492
			// inherited methods of super classes are too. current == null case handled already.
478
			if (!isOrEnclosedByPrivateType && current != null) {
493
			if (!isOrEnclosedByPrivateType && current != null) {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (+18 lines)
Lines 394-399 Link Here
394
				inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
394
				inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
395
			}
395
			}
396
		}
396
		}
397
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658
398
		// Generate a bridge method if a public method is inherited from a non-public class into a public class.
399
		if (current == null && this.type.isPublic()) {
400
			int length = inherited.length;
401
			for (int i = 0; i < length; i++) {
402
				MethodBinding inheritedMethod = inherited[i];
403
				if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic())
404
					this.type.addSyntheticBridgeMethod(inheritedMethod);
405
			}
406
		}
397
407
398
		if (current == null && skipInheritedMethods)
408
		if (current == null && skipInheritedMethods)
399
			continue nextSelector;
409
			continue nextSelector;
Lines 444-449 Link Here
444
		boolean[] skip = new boolean[inheritedLength];
454
		boolean[] skip = new boolean[inheritedLength];
445
		for (int i = 0; i < inheritedLength; i++) {
455
		for (int i = 0; i < inheritedLength; i++) {
446
			MethodBinding matchMethod = foundMatch[i];
456
			MethodBinding matchMethod = foundMatch[i];
457
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658
458
			if (matchMethod == null && current != null && this.type.isPublic()) { // current == null case handled already.
459
				MethodBinding inheritedMethod = inherited[i];
460
				if (inheritedMethod.isPublic() && !inheritedMethod.declaringClass.isPublic()) {
461
					this.type.addSyntheticBridgeMethod(inheritedMethod);
462
				}
463
				
464
			}
447
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
465
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
448
			// inherited methods of super classes are too. current == null case handled already.
466
			// inherited methods of super classes are too. current == null case handled already.
449
			if (!isOrEnclosedByPrivateType && matchMethod == null && current != null) {
467
			if (!isOrEnclosedByPrivateType && matchMethod == null && current != null) {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (+39 lines)
Lines 537-542 Link Here
537
	}
537
	}
538
	return accessMethod;
538
	return accessMethod;
539
}
539
}
540
/*
541
 * Record the fact that bridge methods need to be generated to override certain inherited methods
542
 */
543
public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
544
	if (isInterface()) return null; // only classes & enums get bridge methods
545
	if (this.synthetics == null)
546
		this.synthetics = new HashMap[MAX_SYNTHETICS];
547
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
548
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
549
	} else {
550
		// check to see if there is another equivalent inheritedMethod already added
551
		Iterator synthMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
552
		while (synthMethods.hasNext()) {
553
			Object synthetic = synthMethods.next();
554
			if (synthetic instanceof MethodBinding) {
555
				MethodBinding method = (MethodBinding) synthetic;
556
				if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
557
					&& inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
558
					&& inheritedMethodToBridge.areParameterErasuresEqual(method)) {
559
						return null;
560
				}
561
			}
562
		}
563
	}
564
565
	SyntheticMethodBinding accessMethod = null;
566
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
567
	if (accessors == null) {
568
		accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, this);
569
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
570
		accessors[1] = accessMethod;
571
	} else {
572
		if ((accessMethod = accessors[1]) == null) {
573
			accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, this);
574
			accessors[1] = accessMethod;
575
		}
576
	}
577
	return accessMethod;
578
}
540
boolean areFieldsInitialized() {
579
boolean areFieldsInitialized() {
541
	return this.fields != Binding.UNINITIALIZED_FIELDS;
580
	return this.fields != Binding.UNINITIALIZED_FIELDS;
542
}
581
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java (-1 / +19 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 265-270 Link Here
265
		}
265
		}
266
	}
266
	}
267
267
268
	public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, SourceTypeBinding declaringClass) {
269
270
	    this.declaringClass = declaringClass;
271
	    this.selector = overridenMethodToBridge.selector;
272
	    // amongst other, clear the AccGenericSignature, so as to ensure no remains of original inherited persist (101794)
273
	    // also use the modifiers from the target method, as opposed to inherited one (147690)
274
	    this.modifiers = (overridenMethodToBridge.modifiers | ClassFileConstants.AccBridge | ClassFileConstants.AccSynthetic) & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccNative  | ClassFileConstants.AccFinal | ExtraCompilerModifiers.AccGenericSignature);
275
		this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
276
	    this.returnType = overridenMethodToBridge.returnType;
277
	    this.parameters = overridenMethodToBridge.parameters;
278
	    this.thrownExceptions = overridenMethodToBridge.thrownExceptions;
279
	    this.targetMethod = overridenMethodToBridge;
280
	    this.purpose = SyntheticMethodBinding.BridgeMethod;
281
		SyntheticMethodBinding[] knownAccessMethods = declaringClass.syntheticMethods();
282
		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
283
		this.index = methodId;
284
	}
285
268
	/**
286
	/**
269
	 * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
287
	 * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
270
	 * collision with an existing constructor, then add again an extra argument (declaringClass again).
288
	 * collision with an existing constructor, then add again an extra argument (declaringClass again).
(-)src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java (+75 lines)
Lines 10832-10835 Link Here
10832
		},
10832
		},
10833
		"class java.lang.Object");
10833
		"class java.lang.Object");
10834
}
10834
}
10835
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658, make sure a bridge method
10836
// is generated when a public method is inherited from a non-public class into a
10837
// public class.
10838
public void test208() {
10839
	this.runConformTest(
10840
		new String[] {
10841
			"Test.java",
10842
			"import java.lang.annotation.Annotation;\n"+ 
10843
			"import java.lang.annotation.Retention;\n"+ 
10844
			"import java.lang.annotation.RetentionPolicy;\n"+ 
10845
			"import java.lang.reflect.Method;\n"+ 
10846
			"\n"+ 
10847
			"public class Test extends Super {\n"+ 
10848
			"    public static void main(String[] args) {\n"+ 
10849
			"        try {\n"+ 
10850
			"            Method m = Test.class.getMethod(\"setFoo\", String.class);\n"+
10851
			"            Annotation a = m.getAnnotation(Anno.class);\n"+ 
10852
			"            System.out.println(\"Annotation was \" + (a == null ? \"not \" : \"\") +\n"+ 
10853
			"\"found\");\n"+ 
10854
			"        } catch (Exception e) {\n"+ 
10855
			"            e.printStackTrace();\n"+ 
10856
			"        }\n"+ 
10857
			"    }\n"+ 
10858
			"}\n"+ 
10859
			"\n"+ 
10860
			"class Super {\n"+ 
10861
			"    @Anno\n"+ 
10862
			"    public void setFoo(String foo) {}\n"+ 
10863
			"}\n"+ 
10864
			"\n"+ 
10865
			"@Retention(RetentionPolicy.RUNTIME)\n"+ 
10866
			"@interface Anno {\n"+ 
10867
			"\n"+ 
10868
			"}\n"
10869
		},
10870
		"Annotation was not found");
10871
}
10872
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658, make sure a bridge method
10873
// is generated when a public method is inherited from a non-public class into a
10874
// public class.
10875
public void test208a() {
10876
	this.runConformTest(
10877
		new String[] {
10878
			"Test.java",
10879
			"import java.lang.annotation.Annotation;\n"+ 
10880
			"import java.lang.annotation.Retention;\n"+ 
10881
			"import java.lang.annotation.RetentionPolicy;\n"+ 
10882
			"import java.lang.reflect.Method;\n"+ 
10883
			"\n"+ 
10884
			"public class Test extends Super {\n"+
10885
			"    public void setFoo() {}\n" +
10886
			"    public static void main(String[] args) {\n"+ 
10887
			"        try {\n"+ 
10888
			"            Method m = Test.class.getMethod(\"setFoo\", String.class);\n"+
10889
			"            Annotation a = m.getAnnotation(Anno.class);\n"+ 
10890
			"            System.out.println(\"Annotation was \" + (a == null ? \"not \" : \"\") +\n"+ 
10891
			"\"found\");\n"+ 
10892
			"        } catch (Exception e) {\n"+ 
10893
			"            e.printStackTrace();\n"+ 
10894
			"        }\n"+ 
10895
			"    }\n"+ 
10896
			"}\n"+ 
10897
			"\n"+ 
10898
			"class Super {\n"+ 
10899
			"    @Anno\n"+ 
10900
			"    public void setFoo(String foo) {}\n"+ 
10901
			"}\n"+ 
10902
			"\n"+ 
10903
			"@Retention(RetentionPolicy.RUNTIME)\n"+ 
10904
			"@interface Anno {\n"+ 
10905
			"\n"+ 
10906
			"}\n"
10907
		},
10908
		"Annotation was not found");
10909
}
10835
}
10910
}

Return to bug 288658