llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.8k stars 11.9k forks source link

[Clang15] clang -O stops emitting code for function when indeterminate value encountered in controlling condition of `if` #60974

Open ian-abbott opened 1 year ago

ian-abbott commented 1 year ago

Consider this invalid program using an uninitialized variable:

foo.c

#include <stdio.h>

int main (void)
{
   int garbage; // garbage is indeterminate
   int *addr = &garbage; // address of garbage has been used
   int a = 0;

   puts("Garbage test");
   fflush(stdout);
   if (garbage)
   {
     a = 1;
   }
   printf("a = %d\n", a);
   fflush(stdout);
}

Compiling to assembly language with clang-15 on Debian, with optimizer enabled:

$ clang-15 -O -S foo.c

Details of compiler used:

$ clang-15 --version
Debian clang version 15.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Resulting assembly language:

foo.s

    .text
    .file   "foo.c"
    .globl  main                            # -- Begin function main
    .p2align    4, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# %bb.0:
    pushq   %rax
    .cfi_def_cfa_offset 16
    leaq    .L.str(%rip), %rdi
    callq   puts@PLT
    movq    stdout@GOTPCREL(%rip), %rax
    movq    (%rax), %rdi
    callq   fflush@PLT
.Lfunc_end0:
    .size   main, .Lfunc_end0-main
    .cfi_endproc
                                        # -- End function
    .type   .L.str,@object                  # @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "Garbage test"
    .size   .L.str, 13

    .ident  "Debian clang version 15.0.6"
    .section    ".note.GNU-stack","",@progbits
    .addrsig

Note that no assembly code been emitted for the C code from the line if (garbage) to the end of the function, including any code to return from the function.

Related question by user Lundin (not me) on StackOverflow:

https://stackoverflow.com/q/75533693/5264491

dwblaikie commented 1 year ago

This code has undefined behavior - though there's discussion on other bugs about at least ensuring that functions optimized in this way at least end with a ud2 or other trap instruction.

shafik commented 1 year ago

I know a lot of folks believe that this is not undefined behavior in C but both Zero-initialize objects of automatic storage duration and Uninitialized Reads Understanding the proposed revisions to the C language there is not consensus in this area and it should still be considered UB in C as well as C++.