tcltest::test 15.12.2.2-ambiguous-1 { More than one maximally specific method
        is ambiguous, and illegal.  Here, A.foo(String) and
        T151222a1.foo(Object) are both maximally specific, as the latter
        does not override the former. } {
    compile [saveas T151222a1.java {
interface A {
    void foo(String s);
}
abstract class T151222a1 implements A {
    void foo(Object o) {}
    {
	foo("");
    }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-2 { More than one maximally specific method
        is ambiguous, and illegal.  Here, A.foo(String) and
        B.foo(Object) are both maximally specific, as the latter
        does not override the former. } {
    compile [saveas T151222a2.java {
interface A {
    void foo(String s);
}
interface B {
    void foo(Object o);
}
abstract class T151222a2 implements A, B {
    {
	foo("");
    }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-3 { More than one maximally specific method
        is ambiguous, and illegal.  Here, A.foo(String) and
        T151222a3.foo(Object) are both maximally specific, as the latter
        does not override the former. } {
    compile [saveas T151222a3.java {
class A {
    void foo(String s) {}
}
abstract class T151222a3 extends A {
    void foo(Object o) {}
    {
	foo("");
    }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-4 { When multiple maximally specific methods
        have the same signature, any non-abstract version is chosen } {
    compile [saveas T151222a4a.java {
class T151222a4a {
    public void m() {}
}
interface T151222a4b {
    void m();
}
class T151222a4c extends T151222a4a implements T151222a4b {
    { m(); }
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-5 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a4a.java {
abstract class T151222a5a {
    public abstract void m();
}
interface T151222a5b {
    void m();
}
abstract class T151222a5c extends T151222a5a implements T151222a5b {
    { m(); }
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-6 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a6a.java {
class E1 extends Exception {}
class E2 extends Exception {}
class E3 extends Exception {}
abstract class T151222a6a {
    public abstract void m() throws E1, E2;
}
interface T151222a6b {
    void m() throws E2, E3;
}
abstract class T151222a6c extends T151222a6a implements T151222a6b {
    {
        try {
            m(); // whether a.m() or b.m() is chosen, it cannot throw E1 or E3
        } catch (E2 e2) {
        }
    }
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-7 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a7a.java {
package p1;
public class T151222a7a {
    void m(Object o, String s) {}
}
    }] [saveas T151222a7b.java {
interface T151222a7b {
    void m(String s, Object o);
}
abstract class T151222a7c extends p1.T151222a7a implements T151222a7b {
    { m("", ""); } // only b.m(String, Object) is accessible
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-8 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a8a.java {
package p1;
public class T151222a8a {
    protected void m(Object o, String s) {}
}
    }] [saveas T151222a8b.java {
interface T151222a8b {
    void m(String s, Object o);
}
abstract class T151222a8c extends p1.T151222a8a implements T151222a8b {}
abstract class T151222a8d extends T151222a8c {
    // Even though d inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type d or lower
    void foo(T151222a8c c) {
        c.m("", "");
    } // only b.m(String, Object) is accessible
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-9 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a9a.java {
package p1;
public class T151222a9a {
    protected void m(Object o, String s) {}
}
    }] [saveas T151222a9b.java {
interface T151222a9b {
    void m(String s, Object o);
}
abstract class T151222a9c extends p1.T151222a9a implements T151222a9b {}
abstract class T151222a9d extends T151222a9c {
    // Even though d inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type d or lower
    void foo(T151222a9d d) {
        d.m("", "");
    } // both a.m(Object, String) and b.m(String, Object) are accessible
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-10 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a10a.java {
class E1 extends Exception {}
class E2 extends Exception {}
class E3 extends Exception {}
abstract class T151222a10a {
    public abstract void m() throws E1, E2;
}
interface T151222a10b {
    void m() throws E2, E3;
}
abstract class T151222a10c extends T151222a10a implements T151222a10b {
    {
        try {
            m(); // whether a.m() or b.m() is chosen, it cannot throw E1 or E3
	} catch (E1 e1) {
        } catch (E2 e2) {
        }
    }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-11 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a11a.java {
class E1 extends Exception {}
class E2 extends Exception {}
class E3 extends Exception {}
abstract class T151222a11a {
    public abstract void m() throws E1, E2;
}
interface T151222a11b {
    void m() throws E2, E3;
}
abstract class T151222a11c extends T151222a11a implements T151222a11b {
    {
        try {
            m(); // whether a.m() or b.m() is chosen, it cannot throw E1 or E3
        } catch (E2 e2) {
        } catch (E3 e3) {
        }
    }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-12 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a12a.java {
class E1 extends Exception {}
class E2 extends E1 {}
class E3 extends Exception {}
class E4 extends E3 {}
abstract class T151222a12a {
    public abstract void m() throws E1, E4;
}
interface T151222a12b {
    void m() throws E2, E3;
}
abstract class T151222a12c extends T151222a12a implements T151222a12b {
    {
        try {
            m();
	    // whether a.m() or b.m() is chosen, it cannot throw E1 or E3
	    // directly; but can throw something assignable to E1 or E3
        } catch (E2 e2) {
        } catch (E4 e4) {
        }
    }
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-13 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    compile [saveas T151222a13a.java {
class E1 extends Exception {}
class E2 extends E1 {}
class E3 extends Exception {}
class E4 extends E3 {}
abstract class T151222a13a {
    public abstract void m() throws E1, E4;
}
interface T151222a13b {
    void m() throws E2, E3;
}
abstract class T151222a13c extends T151222a13a implements T151222a13b {
    {
        try {
            m();
	    // whether a.m() or b.m() is chosen, it cannot throw E1 or E3
	    // directly; but can throw something assignable to E1 or E3
        } catch (E1 e1) {
        } catch (E3 e3) {
        }
    }
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-14 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    empty_class T151222a14 {
	class E1 extends Exception {}
	class E2 extends Exception {}
	abstract class C1 {
	    abstract void m() throws E1; // note non-public accessibility
	}
	interface I {
	    void m() throws E2;
	}
	abstract class C2 extends C1 implements I {
	    { m(); }
	}
    }
} PASS

tcltest::test 15.12.2.2-ambiguous-15 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    empty_class T151222a15 {
	class E1 extends Exception {}
	class E2 extends Exception {}
	abstract class C1 {
	    abstract void m() throws E1; // note non-public accessibility
	}
	interface I {
	    void m() throws E2;
	}
	abstract class C2 extends C1 implements I {
	    {
		try {
		    m();
		} catch (E1) {
		}
	    }
	}
    }
} FAIL

tcltest::test 15.12.2.2-ambiguous-16 { When multiple maximally specific methods
        have the same signature, and all are abstract, it is arbitrary which
        is chosen, although the throws clauses are merged } {
    empty_class T151222a16 {
	class E1 extends Exception {}
	class E2 extends Exception {}
	abstract class C1 {
	    abstract void m() throws E1; // note non-public accessibility
	}
	interface I {
	    void m() throws E2;
	}
	abstract class C2 extends C1 implements I {
	    {
		try {
		    m();
		} catch (E2 e) {
		}
	    }
	}
    }
} FAIL

tcltest::test 15.12.2.2-ambiguous-17 { More than one maximally specific method
        is ambiguous, and illegal.  Here, T151222a17a.foo(int) and
        T151222a17b.foo(long) are both maximally specific, as the latter
        does not hide the former. } {
    compile [saveas T151222a17a.java {
class T151222a17a {
    static void foo(int i) {}
}
class T151222a17b extends T151222a17a {
    static void foo(long l) {}
    { foo(0); }
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-18 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a18a.java {
package p1;
public class T151222a18a {
    protected void m(Object o, String s) {}
}
    }] [saveas T151222a18b.java {
interface T151222a18b {
    void m(String s, Object o);
}
abstract class T151222a18c extends p1.T151222a18a implements T151222a18b {}
abstract class T151222a18d extends T151222a18c {
    // Even though d inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type d or lower
    void foo() {
        super.m("", "");
    } // both a.m(Object, String) and b.m(String, Object) are accessible
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-19 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a19a.java {
package p1;
public class T151222a19a {
    protected void m(Object o, String s) {}
    public void m(String s, Object o) {}
}
    }] [saveas T151222a19b.java {
class T151222a19b extends p1.T151222a19a {
    // Even though b inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type b or lower
    void foo() {
        super.m("", "");
    } // both a.m(Object, String) and a.m(String, Object) are accessible
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-20 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a20a.java {
package p1;
public class T151222a20a {
    protected void m(Object o, String s) {}
    public void m(String s, Object o) {}
}
    }] [saveas T151222a20b.java {
class T151222a20b extends p1.T151222a20a {
    // Even though b inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type b or lower
    void foo(T151222a20b t) {
        t.m("", "");
    } // both a.m(Object, String) and a.m(String, Object) are accessible
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-21 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a21a.java {
package p1;
public class T151222a21a {
    protected void m(Object o, String s) {}
    public void m(String s, Object o) {}
}
    }] [saveas T151222a21b.java {
class T151222a21b extends p1.T151222a21a {
    // Even though b inherits two versions of m, the protected a.m
    // is only accessible if the qualifying expression is type b or lower
    void foo(p1.T151222a21a t) {
        t.m("", "");
    } // only a.m(String, Object) is accessible
}
    }]
} PASS

tcltest::test 15.12.2.2-ambiguous-22 { Example where accessibility makes
        what would otherwise be ambiguous maximally specific methods with
        conflicting signatures have a single resolution } {
    compile [saveas p1/T151222a22a.java {
package p1;
public class T151222a22a {
    protected static void m(Object o, String s) {}
    public void m(String s, Object o) {}
}
    }] [saveas T151222a22b.java {
class T151222a22b extends p1.T151222a22a {
    // The protected a.m is accessible since it is static
    void foo(p1.T151222a22a t) {
        t.m("", "");
    } // both a.m(Object, String) and a.m(String, Object) are accessible
}
    }]
} FAIL

tcltest::test 15.12.2.2-ambiguous-23 { The most specific method is chosen,
        regardless of return type or static considerations } {
    empty_class T151222a23 {
	int m(long i) { return 0; }
	long m(int i) { return 0; }
	// long m(int) is chosen and fails, even though int m(long) would work
	int i = m(0);
    }
} FAIL

tcltest::test 15.12.2.2-ambiguous-24 { The most specific method is chosen,
        regardless of return type or static considerations } {
    empty_class T151222a24 {
	static int m(long i) { return 0; }
	int m(int i) { return 0; }
	// int m(int) is chosen and fails, even though int m(long) would work
	static int i = m(0);
    }
} FAIL
