The assembly file has multiple variables which both use the rax register. The decompiler did recognize that at least somewhat, since it did create two variables which use the rax register. However, it did not split up the use of each one properly. Here is the assembly and decompilation, along with a couple comments on what would be a more accurate decompilation.
.text:000000014052DDA0 String__moveTextBackwards proc near
.text:000000014052DDA0 ; CODE XREF: sub_14003E380+86↑p
.text:000000014052DDA0 ; sub_1403CC850+19D2↑p ...
.text:000000014052DDA0 mov rax, [rcx+18h]
.text:000000014052DDA4 movsxd r10, r8d
.text:000000014052DDA7 mov r9, rcx
.text:000000014052DDAA lea r8, [r10+rdx]
.text:000000014052DDAE cmp r8, rax
.text:000000014052DDB1 jnz short loc_14052DDBA
.text:000000014052DDB3 mov rax, [rcx]
.text:000000014052DDB6 jmp qword ptr [rax+20h]
.text:000000014052DDBA ; ---------------------------------------------------------------------------
.text:000000014052DDBA
.text:000000014052DDBA loc_14052DDBA: ; CODE XREF: String__moveTextBackwards+11↑j
.text:000000014052DDBA ja short loc_14052DDDF
.text:000000014052DDBC mov rdx, r10
.text:000000014052DDBF neg rdx
.text:000000014052DDC2
.text:000000014052DDC2 loc_14052DDC2: ; CODE XREF: String__moveTextBackwards+3D↓j
.text:000000014052DDC2 mov rax, [r9+8]
.text:000000014052DDC6 inc r8
.text:000000014052DDC9 lea rcx, [rax+rdx*2]
.text:000000014052DDCD movzx eax, word ptr [rax+r8*2-2]
.text:000000014052DDD3 mov [rcx+r8*2-2], ax
.text:000000014052DDD9 cmp r8, [r9+18h]
.text:000000014052DDDD jbe short loc_14052DDC2
.text:000000014052DDDF
.text:000000014052DDDF loc_14052DDDF: ; CODE XREF: String__moveTextBackwards:loc_14052DDBA↑j
.text:000000014052DDDF sub [r9+18h], r10
.text:000000014052DDE3 retn
.text:000000014052DDE3 String__moveTextBackwards endp
This gets decompiled to
{
wchar_t *stringLength; // rax
__int64 numBytesCopy; // r10
String *thisCopy; // r9
unsigned __int64 v6; // r8
wchar_t *pText; // rax
wchar_t *pMovedText; // rcx
stringLength = (wchar_t *)this->stringLength; // This should really be an __int64, but since the compiler assumed this was the same variable that gets returned, it is forced to a wchar_t*
numBytesCopy = numBytes;
thisCopy = this;
v6 = numBytes + a2;
if ( (wchar_t *)v6 == stringLength )
return (wchar_t *)((__int64 (__fastcall *)(String *, __int64, unsigned __int64, String *))this->vftbl_0_0000000140B4F448->sub_14052DB70)(
this,
a2,
v6,
this);
if ( v6 <= (unsigned __int64)stringLength )
{
do
{
pText = thisCopy->pString;
++v6;
pMovedText = &pText[-numBytesCopy];
stringLength = (wchar_t *)pText[v6 - 1]; // From here until the end, the instances where stringLength is used would better be described as pText. But since both pText and stringLength use rax, it decided to use the wrong one here.
pMovedText[v6 - 1] = (unsigned __int16)stringLength;
}
while ( v6 <= thisCopy->stringLength );
}
thisCopy->stringLength -= numBytesCopy;
return stringLength;
}
Is there a way to change which variable Hex Rays uses in the instances where it chose to use the wrong variable? It has made mistakes similar to this one in other parts of this string class, too.