<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/160527>160527</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [analyzer] Explicit Return and __attribute__((cleanup(..)))
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          PengZheng
      </td>
    </tr>
</table>

<pre>
    Uncommenting the explicit return in `process_data` will trigger the following:

```Bash
peng@hackerlife2:~/Desktop$ /home/peng/Downloads/LLVM-21.1.2-Linux-X64/bin/scan-build /home/peng/Downloads/LLVM-21.1.2-Linux-X64/bin/clang test.c
scan-build: Using '/home/peng/Downloads/LLVM-21.1.2-Linux-X64/bin/clang-21' for static analysis
test.c:30:5: warning: Potential leak of memory pointed to by 'data' [unix.Malloc]
   30 |     return;
      |     ^~~~~~
1 warning generated.
scan-build: Analysis run complete.
scan-build: 1 bug found.
scan-build: Run 'scan-view /tmp/scan-build-2025-09-24-215520-185566-1' to examine bug reports.

```

```C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// This could be unix.Malloc or any other allocation function
void* my_malloc(size_t size) {
    return malloc(size);
}

// The cleanup function.
// IMPORTANT: It takes a pointer to the variable, so char** for a char* variable.
void free_pointer(char **p) {
 printf("Cleanup function called for address: %p\n", (void*)*p);
 free(*p); // Dereference to get the actual pointer and free it.
}

void process_data() {
    // The magic happens here. The variable 'data' is tied to the 'free_pointer' function.
    __attribute__((cleanup(free_pointer))) char *data = my_malloc(100);

    if (!data) {
        perror("Allocation failed");
        return;
    }

    strcpy(data, "Hello, Clang Static Analyzer!");
    printf("Data processed: %s\n", data);

    // Uncommenting the next line will trigger LEAK WARNING
    // return;

 // No need to call free(data) here.
    // The cleanup function is called automatically when process_data() returns.
}

int main() {
 process_data();
    printf("Back in main. Memory should be freed.\n");
 return 0;
}
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJykVk1v4zgS_TXlS8GCRFmWffBBiePdxibZRrZ7ZzAXg5JKEicUKZBUEvehf_uAkuzYTmYuLQiwxY_6eO9VkdxaUSuiDSQ3kGxnvHeNNpuvpOo_GlL1LNflYfNdFbptSTmhanQNIb11UhTCoSHXG4VCISzDzuiCrN2X3HFYhvgqpERnRF2TGbZVWkr9KlQNcQbh8C7D8b3htoEw60jVsAgbXjyTkaIiBnH2E9huS_bZ6Q7YAoHtGt0SsN2wmu22-lVJzUsLbHd___-HOYuCKGDze6H6t_nvywWwXS4UsJ0tuJrnvZDlr1gpJPc4kHVBAWH2bhTiDL9bDxKw9FcdzFkELMVKG7SOO1EgV1werLAQZpPzOItDiLPEO37lRo3Q4lftPFlcoiT-jLrCllptDthpoRyV6DTmBx_kQBVLEZKbXom34IFLqQtIthBmiBiHCOkt-mdkGuKbcQbxNAPJ3U__QJhFxyiwJkWGOyqDDwhlUxpoeoWFbjtJjj4uizDva6x0rz6x8dQrH_4w-CLo1dPp2u6C4jkLWTIP13O2mLMoSVg4j1ZJslzOB2CdRnrjrVA0ODLUaeNscKXLq89b_8FioQrZl4QQ31pXCh00EN99NiVF_ndzRqj6NOend8B2-K0RFgvdyxJzwjNOUBvk6oDaNWRwGOJOaIVVrwr_B8LsRYsSWIbtYd-ORLKVFT9o79D_AFsjpEcCp9K9WAhsPTIM6fYqLMJCEld9d3IYvE9_efj636dv2eM3z80Xh44_k0U-6c14rH39v3AjeC4J2C1ajUXDDbDMR-xVzo8Dp3XBlBNWhmg_GQO28utw3NmdJdUZoVwFbAWM3V4FiwWXksrRUVkastbHCizpILlVwJgPCthqwtAjMVqfJO9DGEwfB3HKfUuGKjKkCvJ51uSGXHnhei5PCHA1ZoHCBef4DuldNE7v45ynMwZaXosCG951pCw2ZCgYxo94nVe0sOjEWOo-HGDpJYjpBY_e0X7PnTMi7x3t90MYq4lyYKvLzevxxSMR3ilCvL1QXhSG73oaXYgKB8PRGOV5mv7pyBhtRgKzM4VzIakcKFqfN6CPTekEq_-wzhTdAdhqdObZZf8mKbX_fzv08P-NjXXoSD98YtG1l3NNbX2WE1dUTvKxZ_KZsrpIeaLvwxGq6M2h9N3n4pi8v8v-g79lT49fHv91aeE8Vz8zDT9qVDTy7CV-1OkR4EEkH5V0XcteLlOF8N7p1sPCpTzga0PqM32O0dgLLQvlsOX-BFtdVOX15s_RveHFs79IeAsBPowHlm2OrdDnVQYnsI9Gpi4WXrStY7eelZu4XMdrPqNNlCarlLFolcyaTcUXhT8LSl4tWZwUi0WxDFfrRVUtWJrEq5nY-MMjXLNFFCdLlgQU52mcRiXlyzTOWQWLkFouZCDlSxtoU8-EtT1tomWYsHQmeU7SDrcqxhS94jDrI0-2M7Pxm-Z5X1tYhFJYZ9_NOOHkcB3jR1EmW7w73reexnR9N_nHcg2CU5HOeiM3jXOdb3ijBGrhmj4PCt0C23nP08-8M_pPKhyw3RCvv6lMCb1s2F8BAAD__8yMGnc">