Difference between revisions of "User:Hanya/Iif Problem"
(→Differences: Add some description with code location) |
(Add the way to obtain disassembled code) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
Error code 87302 is produced when some code is modified contains Iif runtime function. | Error code 87302 is produced when some code is modified contains Iif runtime function. | ||
+ | |||
+ | == How to Obtain Disassembled Code == | ||
+ | The compile for Basic contains the code to write disassembled code into a file. Change some part like the following and recompile it. | ||
+ | Change aFile variable to match with your desired location to store the result. If this code is enabled, you get disassembled code every compilation. | ||
+ | |||
+ | <pre> | ||
+ | Index: basic/source/comp/sbcomp.cxx | ||
+ | =================================================================== | ||
+ | --- basic/source/comp/sbcomp.cxx (Revision 1634275) | ||
+ | +++ basic/source/comp/sbcomp.cxx (Working Copy) | ||
+ | @@ -908,7 +908,7 @@ | ||
+ | |||
+ | //========================================================================== | ||
+ | // For debugging only | ||
+ | -//#define DBG_SAVE_DISASSEMBLY | ||
+ | +#define DBG_SAVE_DISASSEMBLY | ||
+ | |||
+ | #ifdef DBG_SAVE_DISASSEMBLY | ||
+ | static bool dbg_bDisassemble = true; | ||
+ | @@ -920,7 +920,7 @@ | ||
+ | #include <com/sun/star/io/XActiveDataSource.hpp> | ||
+ | |||
+ | using namespace comphelper; | ||
+ | -using namespace rtl; | ||
+ | +//using namespace rtl; | ||
+ | using namespace com::sun::star::uno; | ||
+ | using namespace com::sun::star::lang; | ||
+ | using namespace com::sun::star::ucb; | ||
+ | @@ -931,7 +931,7 @@ | ||
+ | bool bDisassemble = dbg_bDisassemble; | ||
+ | if( bDisassemble ) | ||
+ | { | ||
+ | - Reference< XSimpleFileAccess3 > xSFI; | ||
+ | + //Reference< XSimpleFileAccess3 > xSFI; | ||
+ | Reference< XTextOutputStream > xTextOut; | ||
+ | Reference< XOutputStream > xOut; | ||
+ | Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); | ||
+ | @@ -938,10 +938,10 @@ | ||
+ | if( xSMgr.is() ) | ||
+ | { | ||
+ | Reference< XSimpleFileAccess3 > xSFI = Reference< XSimpleFileAccess3 >( xSMgr->createInstance | ||
+ | - ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); | ||
+ | + ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); | ||
+ | if( xSFI.is() ) | ||
+ | { | ||
+ | - String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/zBasic.Asm/Asm_") ); | ||
+ | + String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///home/foo/a") ); | ||
+ | StarBASIC* pBasic = (StarBASIC*)pModule->GetParent(); | ||
+ | if( pBasic ) | ||
+ | { | ||
+ | @@ -955,7 +955,7 @@ | ||
+ | if( xSFI->exists( aFile ) ) | ||
+ | xSFI->kill( aFile ); | ||
+ | xOut = xSFI->openFileWrite( aFile ); | ||
+ | - Reference< XInterface > x = xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); | ||
+ | + Reference< XInterface > x = xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); | ||
+ | Reference< XActiveDataSource > xADS( x, UNO_QUERY ); | ||
+ | xADS->setOutputStream( xOut ); | ||
+ | xTextOut = Reference< XTextOutputStream >( x, UNO_QUERY ); | ||
+ | </pre> | ||
== Disassembled Original == | == Disassembled Original == | ||
Line 141: | Line 201: | ||
</pre> | </pre> | ||
− | In SbiParser::CheckRTLForSym method, pVar->GetType() call should return SbxEMPTY for rSym == "IIf". But SbxINTEGER is returned when the problem was happen. The return value of the function, instance of SbiSymDef gets wrong type. | + | In SbiParser::CheckRTLForSym method, pVar->GetType() call should return SbxEMPTY for rSym == "IIf". But SbxINTEGER is returned when the problem was happen. The return value of the function, instance of SbiSymDef gets wrong type. The return type depends on the arguments of the Iif function that called first time. |
Then the wrong type is passed to new SbiExprNode instance in SbiExpression::Term method. | Then the wrong type is passed to new SbiExprNode instance in SbiExpression::Term method. | ||
+ | When I change the second argument from "" to false, I got SbxSTRING for the type. | ||
+ | |||
+ | While first compilation, SbxObject::Find( rName, t ) returns NULL in SbiStdObject::Find method for rName = "IIf". | ||
+ | IIf function was found in pMethods in SbxObject::Find at second compilation. When the function is registerd in SbxObject::pMethods variable of runtime. The method instance is registerd by SbxObject::Make method called in SbiStdObject::Find method after searching the runtime function in the table. | ||
+ | |||
+ | The type of return value is set at first execution of the runtime function. Iif is defined as RTLFUNC(Iif) (SbRtl_Iif function is generated by the macro) in basic/source/runtime/methods1.cxx file. | ||
+ | If Iif is called like: Iif(true, 1, ""), the return type is going to be SbxINTEGER from the second argument in *rPar.Get(0) = *rPar.Get(2); line. In SbxValue::operator= function called at assignment of the return value, last Put method call set the type of return value of the function. | ||
+ | |||
+ | After the first execution of the code that contains Iif function call, the method instance having return type is used to obtain the return type while the second compilation. The type of return value of Iif function depends on each function call and cause type miss match. |
Latest revision as of 08:48, 22 December 2014
Issue: https://issues.apache.org/ooo/show_bug.cgi?id=63614
Error code 87302 is produced when some code is modified contains Iif runtime function.
Contents
How to Obtain Disassembled Code
The compile for Basic contains the code to write disassembled code into a file. Change some part like the following and recompile it. Change aFile variable to match with your desired location to store the result. If this code is enabled, you get disassembled code every compilation.
Index: basic/source/comp/sbcomp.cxx =================================================================== --- basic/source/comp/sbcomp.cxx (Revision 1634275) +++ basic/source/comp/sbcomp.cxx (Working Copy) @@ -908,7 +908,7 @@ //========================================================================== // For debugging only -//#define DBG_SAVE_DISASSEMBLY +#define DBG_SAVE_DISASSEMBLY #ifdef DBG_SAVE_DISASSEMBLY static bool dbg_bDisassemble = true; @@ -920,7 +920,7 @@ #include <com/sun/star/io/XActiveDataSource.hpp> using namespace comphelper; -using namespace rtl; +//using namespace rtl; using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::ucb; @@ -931,7 +931,7 @@ bool bDisassemble = dbg_bDisassemble; if( bDisassemble ) { - Reference< XSimpleFileAccess3 > xSFI; + //Reference< XSimpleFileAccess3 > xSFI; Reference< XTextOutputStream > xTextOut; Reference< XOutputStream > xOut; Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory(); @@ -938,10 +938,10 @@ if( xSMgr.is() ) { Reference< XSimpleFileAccess3 > xSFI = Reference< XSimpleFileAccess3 >( xSMgr->createInstance - ( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); + ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY ); if( xSFI.is() ) { - String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///d:/zBasic.Asm/Asm_") ); + String aFile( RTL_CONSTASCII_USTRINGPARAM("file:///home/foo/a") ); StarBASIC* pBasic = (StarBASIC*)pModule->GetParent(); if( pBasic ) { @@ -955,7 +955,7 @@ if( xSFI->exists( aFile ) ) xSFI->kill( aFile ); xOut = xSFI->openFileWrite( aFile ); - Reference< XInterface > x = xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); + Reference< XInterface > x = xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ) ); Reference< XActiveDataSource > xADS( x, UNO_QUERY ); xADS->setOutputStream( xOut ); xTextOut = Reference< XTextOutputStream >( x, UNO_QUERY );
Disassembled Original
Sub Main IIf(true, 1.0, "") End Sub
Position Op Op1 Op2 OpStr ----------------------------------------- 00000000 Lbl00000000: 00000000 45 00000000 JUMP Lbl0000 // Label ; Sub Main 00000005 Main: 00000005 87 00000003 00000000 STMNT 3,0 (For-Level: 0) ; IIf(true, 1.0, "") 0000000E 87 00000004 00000000 STMNT 4,0 (For-Level: 0) 00000017 18 ARGC // new argv 00000018 80 00000002 0000000C RTL true ; Variant 00000021 19 ARGV 00000022 40 00000004 NUMBER "1" 00000027 19 ARGV 00000028 41 00000005 STRING "" 0000002D 19 ARGV 0000002E 80 00008003 00000000 RTL IIf ; Empty, Args 00000037 1C GET ; End Sub 00000038 87 00000005 00000000 STMNT 5,0 (For-Level: 0) 00000041 2B LEAVE
Disassembled with Problem
Second argument for IIf function is changed from 1.0 to "". Execute the code after the change -> strange error.
Sub Main IIf(true, "", "") End Sub
00000000 Lbl00000000: 00000000 45 00000000 JUMP Lbl0000 ; Sub Main 00000005 Main: 00000005 87 00000003 00000000 STMNT 3,0 (For-Level: 0) ; IIf(true, "", "") 0000000E 87 00000004 00000000 STMNT 4,0 (For-Level: 0) 00000017 18 ARGC 00000018 80 00000002 0000000C RTL true ; Variant 00000021 19 ARGV 00000022 41 00000004 STRING "" 00000027 19 ARGV 00000028 41 00000004 STRING "" 0000002D 19 ARGV 0000002E 80 00008003 00000002 RTL IIf ; Integer, Args 00000037 1C GET ; End Sub 00000038 87 00000005 00000000 STMNT 5,0 (For-Level: 0) 00000041 2B LEAVE
Disassembled without Problem after Restarting
After the modification and error mentioned above, restart the office. And then execute the code, no error.
00000000 Lbl00000000: 00000000 45 00000000 JUMP Lbl0000 ; Sub Main 00000005 Main: 00000005 87 00000003 00000000 STMNT 3,0 (For-Level: 0) ; IIf(true, "", "") 0000000E 87 00000004 00000000 STMNT 4,0 (For-Level: 0) 00000017 18 ARGC 00000018 80 00000002 0000000C RTL true ; Variant 00000021 19 ARGV 00000022 41 00000004 STRING "" 00000027 19 ARGV 00000028 41 00000004 STRING "" 0000002D 19 ARGV 0000002E 80 00008003 00000000 RTL IIf ; Empty, Args 00000037 1C GET ; End Sub 00000038 87 00000005 00000000 STMNT 5,0 (For-Level: 0) 00000041 2B LEAVE
Differences
With the same code, different operation codes are generated for IIf function.
Position Op Op1 Op2 OpStr ----------------------------------------- // with problem 0000002E 80 00008003 00000002 RTL IIf ; Integer, Args // restarted 0000002E 80 00008003 00000000 RTL IIf ; Empty, Args
Op2 is type for this OpCode:
// SbiDisas::TypeOp pTypes[][13] = { "Empty","Null","Integer","Long","Single","Double", "Currency","Date","String","Object","Error","Boolean", "Variant" };
The error code 87302 is set in SbxValue::SetType (t is not equal to aData.eType) method. Therefore the problem is caused by the wrong compilation when the code is modified.
Code
00000000 Lbl00000000: 00000000 45 00000000 JUMP Lbl0000 ; Sub Main 00000005 Main: 00000005 87 00000003 00000000 STMNT 3,0 (For-Level: 0) ; IIf(true, "", "") 0000000E 87 00000004 00000000 STMNT 4,0 (For-Level: 0) 00000017 18 ARGC // SbiExprList::Gen in exprgen.cxx 00000018 80 00000002 0000000C RTL true ; Variant 00000021 19 ARGV // SbiExprList::Gen in exprgen.cxx 00000022 41 00000004 STRING "" 00000027 19 ARGV 00000028 41 00000004 STRING "" 0000002D 19 ARGV // SbiExprNode::GenElement in exprgen.cxx 0000002E 80 00008003 00000000 RTL IIf ; Empty, Args 00000037 1C GET // SbiParser::Symbol in parser.cxx ; End Sub 00000038 87 00000005 00000000 STMNT 5,0 (For-Level: 0) 00000041 2B LEAVE // SbiParser::DefProc in dim.cxx
In SbiParser::CheckRTLForSym method, pVar->GetType() call should return SbxEMPTY for rSym == "IIf". But SbxINTEGER is returned when the problem was happen. The return value of the function, instance of SbiSymDef gets wrong type. The return type depends on the arguments of the Iif function that called first time. Then the wrong type is passed to new SbiExprNode instance in SbiExpression::Term method. When I change the second argument from "" to false, I got SbxSTRING for the type.
While first compilation, SbxObject::Find( rName, t ) returns NULL in SbiStdObject::Find method for rName = "IIf". IIf function was found in pMethods in SbxObject::Find at second compilation. When the function is registerd in SbxObject::pMethods variable of runtime. The method instance is registerd by SbxObject::Make method called in SbiStdObject::Find method after searching the runtime function in the table.
The type of return value is set at first execution of the runtime function. Iif is defined as RTLFUNC(Iif) (SbRtl_Iif function is generated by the macro) in basic/source/runtime/methods1.cxx file. If Iif is called like: Iif(true, 1, ""), the return type is going to be SbxINTEGER from the second argument in *rPar.Get(0) = *rPar.Get(2); line. In SbxValue::operator= function called at assignment of the return value, last Put method call set the type of return value of the function.
After the first execution of the code that contains Iif function call, the method instance having return type is used to obtain the return type while the second compilation. The type of return value of Iif function depends on each function call and cause type miss match.