From 94ee763bc8bd945a79dcc3aa9330734cde6bc730 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Thu, 13 Nov 2014 08:12:43 -0800 Subject: [PATCH] Fix bytecode generation for SpEL OpPlus Without this change the plus operator would fail to include a CHECKCAST in generated bytecode when it was compiled in cases where one of the operands has a runtime type of String but a statically declared type that was not String (i.e. Object). Issue: SPR-12426 --- .../expression/spel/ast/OpPlus.java | 3 ++ .../spel/SpelCompilationCoverageTests.java | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpPlus.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpPlus.java index 9006d5c555..91fe886756 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpPlus.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpPlus.java @@ -206,6 +206,9 @@ public class OpPlus extends Operator { else { cf.enterCompilationScope(); operand.generateCode(mv,cf); + if (cf.lastDescriptor() != "Ljava/lang/String") { + mv.visitTypeInsn(CHECKCAST, "java/lang/String"); + } cf.exitCompilationScope(); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java index 2d24fceaf9..53193a479a 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java @@ -1683,12 +1683,41 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests { expression = parse("'hello' + 3 + ' spring'"); assertEquals("hello3 spring",expression.getValue(new Greeter())); assertCantCompile(expression); + + expression = parse("object + 'a'"); + assertEquals("objecta",expression.getValue(new Greeter())); + assertCanCompile(expression); + assertEquals("objecta",expression.getValue(new Greeter())); + + expression = parse("'a'+object"); + assertEquals("aobject",expression.getValue(new Greeter())); + assertCanCompile(expression); + assertEquals("aobject",expression.getValue(new Greeter())); + + expression = parse("'a'+object+'a'"); + assertEquals("aobjecta",expression.getValue(new Greeter())); + assertCanCompile(expression); + assertEquals("aobjecta",expression.getValue(new Greeter())); + + expression = parse("object+'a'+object"); + assertEquals("objectaobject",expression.getValue(new Greeter())); + assertCanCompile(expression); + assertEquals("objectaobject",expression.getValue(new Greeter())); + + expression = parse("object+object"); + assertEquals("objectobject",expression.getValue(new Greeter())); + assertCanCompile(expression); + assertEquals("objectobject",expression.getValue(new Greeter())); } public static class Greeter { public String getWorld() { return "world"; } + + public Object getObject() { + return "object"; + } } @Test