<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - [windows/arm] extraneous C++ object destructor call added when objects are passed by value"
   href="https://llvm.org/bugs/show_bug.cgi?id=29136">29136</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[windows/arm] extraneous C++ object destructor call added when objects are passed by value
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.8
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Keywords</th>
          <td>miscompilation
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>C++
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>adrien@guinet.me
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dgregor@apple.com, llvm-bugs@lists.llvm.org, szkudl.k@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This is only happening when using Clang under Windows to generate Thumb code.

When a C++ object is passed by value to a function, the temporary object
created by copy is destructed twice, once in the callee function (which is
okay) and once more in the caller function (which should not happen). This
leads to a double free of a C++ object.

Attached is a minimal test case that reproduces the problem (double_free.cpp,
reduced by Kevin Szkudlapski in CC).

Here is the assembler output without any optimisation:

<span class="quote">> clang.exe double_free.cpp -c -o double_free.o --target=armv7-pc-windows-msvc -fmsc-version=1900 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1</span >

(using IDA)
 ; int __cdecl main(int argc, const char **argv, const char **envp)
                 EXPORT main
 main

 var_28          = -0x28
 tmpObject       = -0x24
 var_20          = -0x20
 var_1C          = -0x1C
 var_18          = -0x18
 var_14          = -0x14
 var_10          = -0x10
 var_C           = -0xC

  PUSH.W          {R11,LR}       
  MOV             R11, SP        
  SUB             SP, SP, #0x20  
  MOVS            R0, #0         
  STR             R0, [SP,#0x28+var_C]
  ADD             R1, SP, #0x28+var_10
  STR             R0, [SP,#0x28+var_18]
  MOV             R0, R1         
  STR             R1, [SP,#0x28+var_1C]
  BL              c::c(void)     
  MOV             R0, #`string' ; "f start"
  BL              puts           
  ADD             R1, SP, #0x28+var_14
  STR             R0, [SP,#0x28+var_20]
  MOV             R0, R1         
  LDR.W           LR, [SP,#0x28+var_1C]
  STR             R1, [SP,#0x28+tmpObject]
  MOV             R1, LR         
  BL              c::c(c const &)
  BL              f(c)           
  LDR             R0, [SP,#0x28+tmpObject]
  BL              c::~c(void) ; double free happens here!
  MOV             R0, #`string' ; "f end"
  BL              puts           
  LDR             R1, [SP,#0x28+var_18]
  STR             R1, [SP,#0x28+var_C]
  LDR.W           LR, [SP,#0x28+var_1C]
  STR             R0, [SP,#0x28+var_28]
  MOV             R0, LR         
  BL              c::~c(void)    
  LDR             R0, [SP,#0x28+var_C]
  ADD             SP, SP, #0x20  
  POP.W           {R11,PC} 

And the "f::f" function:
void __cdecl f(class c)                 

var_10          = -0x10        
var_C           = -0xC         

  PUSH.W          {R11,LR}      
  MOV             R11, SP       
  SUB             SP, SP, #8    
  MOV             R0, #`string' ; "f inside"
  BL              puts          
  ADD.W           LR, SP, #0x10+var_C
  STR             R0, [SP,#0x10+var_10]
  MOV             R0, LR        
  BL              c::~c(void) ; this one is okay and destruct the temporary
object
  ADD             SP, SP, #8    
  POP.W           {R11,PC}

The LLVM IR also reflects this issue. The optimized code (-O2) shows three
printf calls with "dtor: %p" as argument (where only two should be present, one
for the original copy and one for the temporary object).

This has been tested using the official clang 3.8.1 release (not the 3.9RC or
trunk).

Let us know if more information are needed!

Thanks!</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>