PR# 19166 Expression of form "n.to_character_32.is_space" not compiling correctly to workbench bytecode
Problem Report Summary
Submitter: finnianr
Category: Compiler
Priority: Medium
Date: 2015/12/07
Class: Bug
Severity: Serious
Number: 19166
Release: 15.01.9.6535
Confidential: No
Status: Analyzed
Responsible:
Environment: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Synopsis: Expression of form "n.to_character_32.is_space" not compiling correctly to workbench bytecode
Description
When recompiling the class, the line of code sandwiched with asterisks in the following code fragment is not being compiled to workbench bytecode correctly. Finalized code does not seem to be affected. class EL_ZSTRING_READABLE feature -- Access leading_white_space: INTEGER local i, l_count: INTEGER; l_area: like area; c_i: CHARACTER do l_area := area; l_count := count from i := 0 until i = l_count loop c_i := l_area [i] -- `Unencoded_character' is space if c_i = Unencoded_character then -- ******************************************************* if unencoded_code (i + 1).to_character_32.is_space then -- ******************************************************* Result := Result + 1 else i := l_count - 1 -- break out of loop end elseif c_i.is_space then Result := Result + 1 else i := l_count - 1 -- break out of loop end i := i + 1 end ensure substring_agrees: across substring (1, Result) as char all char.item.is_space end end
To Reproduce
The first time the code is compiled the expression "unencoded_code (i + 1).to_character_32.is_space" evaluates correctly on execution. (As shown by a test suite) However subsequent recompiles of edits to the class or it's descendants cause the expression in question to evaluate to False when it should evaluate to true, even though the value returned by unencoded_code (i + 1) is exactly the same as before. (NATURAL_32) It can be temporarily fixed by forcing the routine to be recompiled, an operation which involves, commenting out the body of the routine, recompiling, then commenting the lines back in and recompiling. On a hunch I am going to try assigning "unencoded_code (i + 1).to_character_32" to an intermediate variable and see if that helps. Will report what happens.
Problem Report Interactions
This code seems to work as a better workaround for the problem. leading_white_space: INTEGER local i, l_count: INTEGER; l_area: like area; c_i: CHARACTER l_prop: like character_properties do l_area := area; l_count := count; l_prop := character_properties from i := 0 until i = l_count loop c_i := l_area [i] -- `Unencoded_character' is space if c_i = Unencoded_character then if l_prop.is_space (unencoded_item (i + 1)) then Result := Result + 1 else i := l_count - 1 -- break out of loop end elseif c_i.is_space then Result := Result + 1 else i := l_count - 1 -- break out of loop end i := i + 1 end ensure substring_agrees: across substring (1, Result) as char all character_properties.is_space (char.item) end end
Hi Alexander I couldn't find a build for 15.02 to download. I have created a standalone project (attached) to test this issue on version Version 15.01.9. The test fails on a clean build for both the finalized and workbench application, so the issue is even worse then I thought. But if you force a workbench recompile of routines {EL_READABLE_ZSTRING}.leading_white_space {EL_READABLE_ZSTRING}.trailing_white_space the tests will pass for workbench mode. To force a recompile: comment out the assignment below for each routine, recompile, then reintroduce the assignment. The test will then pass. uc_i := unencoded_item (i + 1)
Thank you for your report. So far we were unable to reproduce the issue with the recent version of EiffelStudio. Could you check that it still happens with EiffelStudio 15.12, please? If so, could you provide a self-contained example that demonstrates it?
The problem has happened again, so the supposed workaround does not actually work.
SUMMARY OF PROBLEM 4. This workaround makes the problem go away uc_i := unencoded_code (i + 1).to_character_32 if uc_i.is_space then
SUMMARY OF PROBLEM 1. With a clean build the line below executes correctly: if unencoded_code (i + 1).to_character_32.is_space then 2. F7 recompiles of class edits causes the line to fail to execute corrrectly. 3. Forced recompilation of routine causes the line to execute correctly again.
After doing a class edit that normally causes a problem on recompile, I can confirm that assigning "unencoded_code (i + 1).to_character_32" to an intermediate variable fixes the problem. This should provide a clue as to where exactly the compilation problem is.