When a class contains virtual functions but no data members and has a trivial constructor, global variables of that type are initialized with a vptr. CIR was incorrectly creating the global variable with the type of the vtable (an anonymous record) rather than the class type. When replacing structors with aliases, we were calling a function to update argument types at the call sites, but this was only necessary because we initially generated the call using the same incorrect type that we used for the global. The type correction wasn't implemented because we hadn't encountered a case where it was needed. Having found such a case led me to diagnose the problem as above, and I verified that the same test case compiled without -mconstructor-aliases just failed in the verifier because we never hit the replacement code. I'm now convinced that this argument type fixup isn't necessary, so I replaced the fixup function with an assert. Assisted-by: Cursor / claude-4.6-opus-high
17 lines
867 B
C++
17 lines
867 B
C++
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=gnu++14 -fclangir -emit-cir -o %t.cir %s
|
|
// RUN: FileCheck -check-prefix=CIR --input-file=%t.cir %s
|
|
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=gnu++14 -fclangir -emit-llvm -o %t-cir.ll %s
|
|
// RUN: FileCheck -check-prefix=LLVM --input-file=%t-cir.ll %s
|
|
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=gnu++14 -emit-llvm -o %t.ll %s
|
|
// RUN: FileCheck -check-prefix=OGCG --input-file=%t.ll %s
|
|
|
|
struct B {
|
|
virtual void f() {}
|
|
virtual ~B() {}
|
|
};
|
|
B x;
|
|
|
|
// CIR: cir.global external @x = #cir.const_record<{#cir.global_view<@_ZTV1B, [0 : i32, 2 : i32]> : !cir.vptr}> : !rec_B
|
|
// LLVM: @x = global %struct.B { ptr getelementptr inbounds nuw (i8, ptr @_ZTV1B, i64 16) }, align 8
|
|
// OGCG: @x = global %struct.B { ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) }, align 8
|