@@ -131,6 +131,40 @@ void translatesDefaultInterfaceMethodImplementations() throws Exception {
131131 "Implementing class should point vtable slot to the interface default method implementation" );
132132 }
133133
134+ @ Test
135+ void translatesDefaultInterfaceMethodOverridesWithSuperCalls () throws Exception {
136+ Parser .cleanup ();
137+
138+ Path baseInterfaceFile = createBaseGreeterInterface ();
139+ Path derivedInterfaceFile = createDerivedGreeterInterface ();
140+ Path implFile = createDerivedGreeterImplementation ();
141+
142+ Parser .parse (baseInterfaceFile .toFile ());
143+ Parser .parse (derivedInterfaceFile .toFile ());
144+ Parser .parse (implFile .toFile ());
145+
146+ ByteCodeClass base = Parser .getClassObject ("com_example_BaseGreeter" );
147+ ByteCodeClass derived = Parser .getClassObject ("com_example_DerivedGreeter" );
148+ ByteCodeClass impl = Parser .getClassObject ("com_example_DerivedGreeterImpl" );
149+
150+ base .setBaseInterfacesObject (Collections .emptyList ());
151+ derived .setBaseInterfacesObject (Collections .singletonList (base ));
152+ impl .setBaseInterfacesObject (Collections .singletonList (derived ));
153+
154+ base .updateAllDependencies ();
155+ derived .updateAllDependencies ();
156+ impl .updateAllDependencies ();
157+
158+ List <ByteCodeClass > classes = Arrays .asList (base , derived , impl );
159+ String derivedCode = derived .generateCCode (classes );
160+ assertTrue (derivedCode .contains ("com_example_BaseGreeter_greet___R_java_lang_String" ),
161+ "Derived default method should invoke base interface default method" );
162+
163+ String implCode = impl .generateCCode (classes );
164+ assertTrue (implCode .contains ("&com_example_DerivedGreeter_greet___R_java_lang_String" ),
165+ "Implementing class should point vtable slot to the derived interface default method implementation" );
166+ }
167+
134168 private ByteCodeField findField (ByteCodeClass cls , String name ) {
135169 return cls .getFields ()
136170 .stream ()
@@ -349,6 +383,74 @@ private Path createGreeterImplementation() throws Exception {
349383 });
350384 }
351385
386+ private Path createBaseGreeterInterface () throws Exception {
387+ return writeClass ("com/example/BaseGreeter" , cw -> {
388+ cw .visit (
389+ Opcodes .V1_8 ,
390+ Opcodes .ACC_PUBLIC | Opcodes .ACC_ABSTRACT | Opcodes .ACC_INTERFACE ,
391+ "com/example/BaseGreeter" ,
392+ null ,
393+ "java/lang/Object" ,
394+ null
395+ );
396+
397+ MethodVisitor greet = cw .visitMethod (Opcodes .ACC_PUBLIC , "greet" , "()Ljava/lang/String;" , null , null );
398+ greet .visitCode ();
399+ greet .visitLdcInsn ("base" );
400+ greet .visitInsn (Opcodes .ARETURN );
401+ greet .visitMaxs (1 , 1 );
402+ greet .visitEnd ();
403+
404+ cw .visitEnd ();
405+ });
406+ }
407+
408+ private Path createDerivedGreeterInterface () throws Exception {
409+ return writeClass ("com/example/DerivedGreeter" , cw -> {
410+ cw .visit (
411+ Opcodes .V1_8 ,
412+ Opcodes .ACC_PUBLIC | Opcodes .ACC_ABSTRACT | Opcodes .ACC_INTERFACE ,
413+ "com/example/DerivedGreeter" ,
414+ null ,
415+ "java/lang/Object" ,
416+ new String []{"com/example/BaseGreeter" }
417+ );
418+
419+ MethodVisitor greet = cw .visitMethod (Opcodes .ACC_PUBLIC , "greet" , "()Ljava/lang/String;" , null , null );
420+ greet .visitCode ();
421+ greet .visitVarInsn (Opcodes .ALOAD , 0 );
422+ greet .visitMethodInsn (Opcodes .INVOKESPECIAL , "com/example/BaseGreeter" , "greet" , "()Ljava/lang/String;" , true );
423+ greet .visitInsn (Opcodes .ARETURN );
424+ greet .visitMaxs (1 , 1 );
425+ greet .visitEnd ();
426+
427+ cw .visitEnd ();
428+ });
429+ }
430+
431+ private Path createDerivedGreeterImplementation () throws Exception {
432+ return writeClass ("com/example/DerivedGreeterImpl" , cw -> {
433+ cw .visit (
434+ Opcodes .V1_8 ,
435+ Opcodes .ACC_PUBLIC | Opcodes .ACC_SUPER ,
436+ "com/example/DerivedGreeterImpl" ,
437+ null ,
438+ "java/lang/Object" ,
439+ new String []{"com/example/DerivedGreeter" }
440+ );
441+
442+ MethodVisitor init = cw .visitMethod (Opcodes .ACC_PUBLIC , "<init>" , "()V" , null , null );
443+ init .visitCode ();
444+ init .visitVarInsn (Opcodes .ALOAD , 0 );
445+ init .visitMethodInsn (Opcodes .INVOKESPECIAL , "java/lang/Object" , "<init>" , "()V" , false );
446+ init .visitInsn (Opcodes .RETURN );
447+ init .visitMaxs (1 , 1 );
448+ init .visitEnd ();
449+
450+ cw .visitEnd ();
451+ });
452+ }
453+
352454 private int enumFieldFlags () {
353455 return Opcodes .ACC_PUBLIC | Opcodes .ACC_STATIC | Opcodes .ACC_FINAL | Opcodes .ACC_ENUM ;
354456 }
0 commit comments