Int/long variable results in "poison" when overflow during compile time on riscv32 architecture

Dear All,

When I compile this code for riscv32 cpu, I got different result between GCC and LLVM.

volatile long c = 0;
#define   _IQ24(A)      (long) ((A) * 16777216.0L)
int main(void)
{
    c = _IQ24(254);
    return 0;
}

When I run the compiled code on an 32-bit RISC-V CPU, the LLVM version results in 0, but Gcc’s 0x7fffffff.
The LLVM IR code is

; ModuleID = '.\test.c'
source_filename = ".\\test.c"
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
target triple = "riscv32-haawking-unknown-elf"

@c = dso_local global i32 0, align 4

; Function Attrs: noinline nounwind optnone
define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store volatile i32 poison, i32* @c, align 4
  ret i32 0
}

attributes #0 = { noinline nounwind optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+a,+c,+m,+relax,-save-restore" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"target-abi", !"ilp32"}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{i32 1, !"SmallDataLimit", i32 8}
!4 = !{!"clang version 13.0.1"}

And when I checkout the disassembly code, I find that it just store “0” to the c variable.

00012180 <main>:
   12180:	0d4002ef          	jal	t0,12254 <__riscv_save_3>
   12184:	1141                	addi	sp,sp,-16
   12186:	1000                	addi	s0,sp,32
   **12188:	4501                	li	a0,0**
**   1218a:	fea42623          	sw	a0,-20(s0)**
   1218e:	0141                	addi	sp,sp,16
   12190:	a0f5                	j	1227c <__riscv_restore_1>

So, I want to know how to fix this error, or where the “0” from?

Signed integer overflow is undefined behavior in C. You can use -fsanitize=undefined to detect these kinds of issues.

If you need to perform overflowing arithmetic, you can use unsigned types. It’s also possible to use -fwrapv to instruct clang to treat signed overflow as well-defined.

Thanks a lot nikic, I can use -fsanitize=undefined, but -fwrapv is not workable, I am using clang 13.0.1.