diff options
author | Andrew Clement <aclement@vmware.com> | 2025-03-24 16:54:35 -0700 |
---|---|---|
committer | Andrew Clement <aclement@vmware.com> | 2025-03-24 16:54:35 -0700 |
commit | afc327cb06940d4d134ab9e03d93ae2ce3d8ebc9 (patch) | |
tree | f02e76eeaaf252889fde6fbd21cc69fb0b9a332b | |
parent | 30b83b00ebc7f6ed8c568341d1d435c50388dcaa (diff) | |
download | aspectj-afc327cb06940d4d134ab9e03d93ae2ce3d8ebc9.tar.gz aspectj-afc327cb06940d4d134ab9e03d93ae2ce3d8ebc9.zip |
Fixed #327 - Attempt to push null on operand stack
This change adds tests for multiple related scenarios where the code
generation was not including correct variable information, leading
to these 'push null' problems. The new trackers for stack/variable usage
when working with recent versions of Java are more careful in that it is
not possible to manipulate stack/variable entries if they have not been
previously described to the system. The Xwiki issue here uncovered two
but there were a number of routes through the same method that needed
testing and fixing (for example the code takes a different path for
static vs non-static and private vs non-private).
A snapshot build with these changes in seems to pass the Xwiki build
process.
Fixes #327
9 files changed, 137 insertions, 9 deletions
diff --git a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java index 4a67471c1..1fb2c03af 100644 --- a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java +++ b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/AstUtil.java @@ -162,7 +162,7 @@ public class AstUtil { LocalVariableBinding lvb = new LocalVariableBinding(parameterName, param, 0, true); codeStream.record(lvb); lvb.recordInitializationStartPC(codeStream.position); - lvb.resolvedPosition = paramIndex; + lvb.resolvedPosition = varIndex; } paramIndex++; codeStream.load(param, varIndex); diff --git a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java index ea3e58030..e93260847 100644 --- a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java +++ b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeFieldDeclaration.java @@ -454,16 +454,15 @@ public class InterTypeFieldDeclaration extends InterTypeDeclaration { PrivilegedFieldBinding fBinding = (PrivilegedFieldBinding) Scope.findPrivilegedHandler(binding.declaringClass) .getPrivilegedAccessField(field, null); if (field.isStatic()) { + LocalVariableBinding valueVar = createUsedVar(codeStream, "value", field.type, 0); codeStream.load(field.type, 0); codeStream.invoke(Opcodes.OPC_invokestatic,fBinding.writer,null); + valueVar.recordInitializationEndPC(codeStream.position); } else { // Example: // We are generating: public static void ajc$interFieldSetDispatch$PersonAspect$Manager$jobTitle(Manager, java.lang.String) // And it is calling: public static void ajc$set$jobTitle(Manager, java.lang.String) - LocalVariableBinding instanceVar = new LocalVariableBinding("instance".toCharArray(),this.onTypeBinding,Modifier.PUBLIC,true); - codeStream.record(instanceVar); - instanceVar.recordInitializationStartPC(codeStream.position); - instanceVar.resolvedPosition = 0; + LocalVariableBinding instanceVar = createUsedVar(codeStream, "instance", this.onTypeBinding, 0); codeStream.aload_0(); LocalVariableBinding valueVar = new LocalVariableBinding("value".toCharArray(),this.realFieldType,Modifier.PUBLIC,true); codeStream.record(valueVar); @@ -477,15 +476,29 @@ public class InterTypeFieldDeclaration extends InterTypeDeclaration { return; } if (field.isStatic()) { + LocalVariableBinding valueVar = createUsedVar(codeStream, "value", field.type, 0); codeStream.load(field.type, 0); - codeStream.fieldAccess(Opcodes.OPC_putstatic,field,null); + codeStream.fieldAccess(Opcodes.OPC_putstatic, field, null); + valueVar.recordInitializationEndPC(codeStream.position); } else { + LocalVariableBinding instanceVar = createUsedVar(codeStream, "instance", this.onTypeBinding, 0); codeStream.aload_0(); + LocalVariableBinding valueVar = createUsedVar(codeStream, "value", field.type, 1); codeStream.load(field.type, 1); codeStream.fieldAccess(Opcodes.OPC_putfield,field,null); + instanceVar.recordInitializationEndPC(codeStream.position); + valueVar.recordInitializationEndPC(codeStream.position); } } + private LocalVariableBinding createUsedVar(CodeStream codeStream, String name, TypeBinding type, int position) { + LocalVariableBinding instanceVar = new LocalVariableBinding(name.toCharArray(), type, Modifier.PUBLIC,true); + codeStream.record(instanceVar); + instanceVar.recordInitializationStartPC(codeStream.position); + instanceVar.resolvedPosition = position; + return instanceVar; + } + protected Shadow.Kind getShadowKindForBody() { return null; } diff --git a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java index 52fa2d332..83ec388d8 100644 --- a/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java +++ b/org.aspectj.ajdt.core/src/main/java/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java @@ -36,6 +36,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; @@ -259,6 +260,44 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { generateDispatchMethod(classScope, classFile); } + /** + * Generate a dispatch method for the intertype method declaration. + * + * Best illustrated by example, the ITD might be: + * <pre><tt> + * aspect F { + * void C.displaySearch(StringBuffer buffer, String name, String prefix, A criteria,B context) + * } + * </tt></pre> + * In the class representing the aspect F we will generate the dispatcher: + * <pre><tt> + * public static void ajc$interMethodDispatch1$F$C$displaySearch(C, java.lang.StringBuffer, java.lang.String, java.lang.String, A, B) + * </tt></pre> + * and the dispatcher will call the ITD method on the real target: + * <pre><tt> + * instanceOfC.displaySearch(java.lang.StringBuffer, java.lang.String, java.lang.String, A, B) + * </tt></pre> + * + * Example generated code: + * <pre><tt> + * public static void ajc$interMethodDispatch1$F$C$displaySearch(C, java.lang.StringBuffer, java.lang.String, java.lang.String, A, B); + * descriptor: (LC;Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;LA;LB;)V + * flags: (0x1009) ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC + * Code: + * stack=6, locals=6, args_size=6 + * 0: aload_0 + * 1: aload_1 + * 2: aload_2 + * 3: aload_3 + * 4: aload 4 + * 6: aload 5 + * 8: invokeinterface #28, 6 // InterfaceMethod C.displaySearch:(Ljava/lang/StringBuffer;Ljava/lang/String;Ljava/lang/String;LA;LB;)V + * 13: return + * </tt></pre> + * + * @param classScope the aspect containing the ITD + * @param classFile the class file to which the dispatch method is being added + */ public void generateDispatchMethod(ClassScope classScope, ClassFile classFile) { EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope); @@ -288,6 +327,7 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { Argument[] itdArgs = this.arguments; if (itdArgs != null) { + int rp = 0; for (Argument itdArg : itdArgs) { LocalVariableBinding lvb = itdArg.binding; LocalVariableBinding lvbCopy = new LocalVariableBinding(lvb.name, lvb.type, lvb.modifiers, true); @@ -295,7 +335,8 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { lvbCopy.declaration = new LocalDeclaration(itdArg.name, 0, 0); codeStream.record(lvbCopy); lvbCopy.recordInitializationStartPC(0); - lvbCopy.resolvedPosition = lvb.resolvedPosition; + lvbCopy.resolvedPosition = rp; + rp += getSlotSize(itdArg.binding.type.id); } } @@ -341,6 +382,16 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { classFile.completeMethodInfo(binding,methodAttributeOffset, attributeNumber); } + public static int getSlotSize(int typeId) { + switch (typeId) { + case TypeIds.T_double: + case TypeIds.T_long: + return 2; + default: + return 1; + } + } + @Override protected Shadow.Kind getShadowKindForBody() { return Shadow.MethodExecution; diff --git a/tests/bugs1923/gh327/A.aj b/tests/bugs1923/gh327/A.aj index 28a38429f..f829f0ae0 100644 --- a/tests/bugs1923/gh327/A.aj +++ b/tests/bugs1923/gh327/A.aj @@ -1,5 +1,5 @@ privileged public aspect A { - public static final String B.s = C.f.toString(); + public final static String B.s = C.f.toString(); } class B { } diff --git a/tests/bugs1923/gh327/B.aj b/tests/bugs1923/gh327/B.aj new file mode 100644 index 000000000..c7aaddcd1 --- /dev/null +++ b/tests/bugs1923/gh327/B.aj @@ -0,0 +1,10 @@ +privileged public aspect B { + public final String C.s = D.f.toString(); +} + +class C { } + +class D { + public static final D f = new D(); +} + diff --git a/tests/bugs1923/gh327/C.aj b/tests/bugs1923/gh327/C.aj new file mode 100644 index 000000000..16e6bb543 --- /dev/null +++ b/tests/bugs1923/gh327/C.aj @@ -0,0 +1,10 @@ +privileged public aspect C { + private final String D.s = E.f.toString(); +} + +class D { } + +class E { + public static final E f = new E(); +} + diff --git a/tests/bugs1923/gh327/F.aj b/tests/bugs1923/gh327/F.aj new file mode 100644 index 000000000..45d6de0a8 --- /dev/null +++ b/tests/bugs1923/gh327/F.aj @@ -0,0 +1,13 @@ +class A {} + +class B {} + +public abstract aspect F { + @Deprecated + public abstract void C.displaySearch(StringBuffer buffer, String name, String prefix, A criteria, + B context); +} + +interface C { +} + diff --git a/tests/src/test/java/org/aspectj/systemtest/ajc1923/Bugs1923Tests.java b/tests/src/test/java/org/aspectj/systemtest/ajc1923/Bugs1923Tests.java index 1053c9918..dbcb6cf5f 100644 --- a/tests/src/test/java/org/aspectj/systemtest/ajc1923/Bugs1923Tests.java +++ b/tests/src/test/java/org/aspectj/systemtest/ajc1923/Bugs1923Tests.java @@ -23,6 +23,22 @@ public class Bugs1923Tests extends XMLBasedAjcTestCase { runTest("problem with inline accessor generator for around advice"); } + public void testGh327_IntertypeFields_Static() { + runTest("problem with intertype field declaration code generation - static"); + } + + public void testGh327_IntertypeFields_NonStatic() { + runTest("problem with intertype field declaration code generation - nonstatic"); + } + + public void testGh327_IntertypeFields_Private() { + runTest("problem with intertype field declaration code generation - private"); + } + + public void testGh327_IntertypeMethods() { + runTest("problem with intertype method declaration code generation"); + } + @Override protected java.net.URL getSpecFile() { return getClassResource("ajc1923.xml"); diff --git a/tests/src/test/resources/org/aspectj/systemtest/ajc1923/ajc1923.xml b/tests/src/test/resources/org/aspectj/systemtest/ajc1923/ajc1923.xml index f21f16701..4315ac1ad 100644 --- a/tests/src/test/resources/org/aspectj/systemtest/ajc1923/ajc1923.xml +++ b/tests/src/test/resources/org/aspectj/systemtest/ajc1923/ajc1923.xml @@ -51,10 +51,25 @@ </compile> </ajc-test> - <ajc-test dir="bugs1923/gh327" vm="17" title="problem with intertype field declaration code generation"> + <ajc-test dir="bugs1923/gh327" vm="17" title="problem with intertype field declaration code generation - static"> <compile files="A.aj" options="-17"> </compile> </ajc-test> + <ajc-test dir="bugs1923/gh327" vm="17" title="problem with intertype field declaration code generation - nonstatic"> + <compile files="B.aj" options="-17"> + </compile> + </ajc-test> + + <ajc-test dir="new/verifyError" pr="36673" + title="problem with intertype field declaration code generation - private"> + <compile files="Privilege.java" options="-17"/> + <run class="Privilege"/> + </ajc-test> + + <ajc-test dir="bugs1923/gh327" vm="17" title="problem with intertype method declaration code generation"> + <compile files="F.aj" options="-17"> + </compile> + </ajc-test> </suite> |