-
Notifications
You must be signed in to change notification settings - Fork 156
Closed
Description
Reproducer:
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
struct def;
typedef struct def *decl;
struct def {
int index;
};
struct def d;
int foo(unsigned char cond)
{
if (cond)
goto label;
{
decl b = &d;
label:
return b->index;
}
return 0;
}
The generated CIR looks like:
cir.func @foo(%arg0: !u8i loc(fused[#loc5, #loc6])) -> !s32i extra(#fn_attr) {
%0 = cir.alloca !u8i, !cir.ptr<!u8i>, ["cond", init] {alignment = 1 : i64} loc(#loc25)
%1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64} loc(#loc4)
cir.store %arg0, %0 : !u8i, !cir.ptr<!u8i> loc(#loc7)
cir.scope {
%4 = cir.load %0 : !cir.ptr<!u8i>, !u8i loc(#loc10)
%5 = cir.cast(int_to_bool, %4 : !u8i), !cir.bool loc(#loc10)
cir.if %5 {
cir.goto "label" loc(#loc27)
} loc(#loc27)
} loc(#loc26)
cir.scope {
%4 = cir.alloca !cir.ptr<!ty_def>, !cir.ptr<!cir.ptr<!ty_def>>, ["b", init] {alignment = 8 : i64} loc(#loc29)
%5 = cir.get_global @d : !cir.ptr<!ty_def> loc(#loc23)
cir.store %5, %4 : !cir.ptr<!ty_def>, !cir.ptr<!cir.ptr<!ty_def>> loc(#loc29)
cir.br ^bb1 loc(#loc16)
^bb1: // pred: ^bb0
cir.label "label" loc(#loc16)
%6 = cir.load %4 : !cir.ptr<!cir.ptr<!ty_def>>, !cir.ptr<!ty_def> loc(#loc17)
%7 = cir.get_member %6[0] {name = "index"} : !cir.ptr<!ty_def> -> !cir.ptr<!s32i> loc(#loc18)
%8 = cir.load %7 : !cir.ptr<!s32i>, !s32i loc(#loc19)
cir.store %8, %1 : !s32i, !cir.ptr<!s32i> loc(#loc30)
%9 = cir.load %1 : !cir.ptr<!s32i>, !s32i loc(#loc30)
cir.return %9 : !s32i loc(#loc30)
} loc(#loc28)
%2 = cir.const #cir.int<0> : !s32i loc(#loc21)
cir.store %2, %1 : !s32i, !cir.ptr<!s32i> loc(#loc31)
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i loc(#loc31)
cir.return %3 : !s32i loc(#loc31)
} loc(#loc24)
We can find the def %4
and %5
are defined twice.
FYI, the generated LLVM IR without CIR pipeline is:
define dso_local i32 @foo(i8 noundef zeroext %cond) #0 {
entry:
%cond.addr = alloca i8, align 1
%b = alloca ptr, align 8
store i8 %cond, ptr %cond.addr, align 1
%0 = load i8, ptr %cond.addr, align 1
%tobool = icmp ne i8 %0, 0
br i1 %tobool, label %if.then, label %if.end
if.then: ; preds = %entry
br label %label
if.end: ; preds = %entry
store ptr @d, ptr %b, align 8
br label %label
label: ; preds = %if.end, %if.then
%1 = load ptr, ptr %b, align 8
%index = getelementptr inbounds %struct.def, ptr %1, i32 0, i32 0
%2 = load i32, ptr %index, align 4
ret i32 %2
}
It is a UB if cond
is true. But we should never crash.
Metadata
Metadata
Assignees
Labels
No labels