User:Hanya/Iif Problem

From Apache OpenOffice Wiki
Jump to: navigation, search

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.

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.

Personal tools