blob: ad8bf4b2a736ce827b6b2fd19f28530688c99d1f [file] [log] [blame] [edit]
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -mconstructor-aliases -clangir-disable-emit-cxx-default -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s
typedef enum {
RequestFailed = -2004,
} enumy;
typedef struct {
const void* samples;
int cound;
} buffy;
class C1 {
public:
virtual ~C1();
C1(int i);
struct IE {
bool supported = false;
unsigned version = 0;
};
struct IEs {
IE chain;
};
static IEs availableIEs;
class Layer {
public:
Layer(int d);
virtual ~Layer() {}
};
virtual enumy SetStuff(enumy e, buffy b);
virtual enumy Initialize() = 0;
};
class C2 : public C1 {
public:
C2(
void* p,
int i
);
~C2() override;
class Layer : public C1::Layer {
public:
Layer(int d, const C2* C1);
virtual ~Layer();
protected:
const C2* m_C1;
};
virtual enumy SetStuff(enumy e, buffy b) override;
virtual enumy Initialize() override;
};
class C3 : public C2 {
struct Layer : public C2::Layer {
public:
Layer(int d, const C2* C1);
void Initialize();
};
virtual enumy Initialize() override;
};
void C3::Layer::Initialize() {
if (m_C1 == nullptr) {
return;
}
if (m_C1->availableIEs.chain.supported) {
}
}
// CHECK-DAG: !ty_C23A3ALayer = !cir.struct<class "C2::Layer"
// CHECK-DAG: !ty_C33A3ALayer = !cir.struct<struct "C3::Layer"
// CHECK-DAG: !ty_A = !cir.struct<class "A"
// CHECK-DAG: !ty_A2Ebase = !cir.struct<class "A.base"
// CHECK-DAG: !ty_B = !cir.struct<class "B" {!cir.struct<class "A.base"
// CHECK: cir.func @_ZN2C35Layer10InitializeEv
// CHECK: cir.scope {
// CHECK: %2 = cir.base_class_addr(%1 : !cir.ptr<!ty_C33A3ALayer>) -> !cir.ptr<!ty_C23A3ALayer>
// CHECK: %3 = cir.get_member %2[1] {name = "m_C1"} : !cir.ptr<!ty_C23A3ALayer> -> !cir.ptr<!cir.ptr<!ty_C2_>>
// CHECK: %4 = cir.load %3 : !cir.ptr<!cir.ptr<!ty_C2_>>, !cir.ptr<!ty_C2_>
// CHECK: %5 = cir.const #cir.ptr<null> : !cir.ptr<!ty_C2_>
// CHECK: %6 = cir.cmp(eq, %4, %5) : !cir.ptr<!ty_C2_>, !cir.bool
enumy C3::Initialize() {
return C2::Initialize();
}
// CHECK: cir.func @_ZN2C310InitializeEv(%arg0: !cir.ptr<!ty_C3_>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_C3_>, !cir.ptr<!cir.ptr<!ty_C3_>>, ["this", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_C3_>, !cir.ptr<!cir.ptr<!ty_C3_>>
// CHECK: %2 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_C3_>>, !cir.ptr<!ty_C3_>
// CHECK: %3 = cir.base_class_addr(%2 : !cir.ptr<!ty_C3_>) -> !cir.ptr<!ty_C2_>
// CHECK: %4 = cir.call @_ZN2C210InitializeEv(%3) : (!cir.ptr<!ty_C2_>) -> !s32i
void vcall(C1 &c1) {
buffy b;
enumy e;
c1.SetStuff(e, b);
}
// CHECK: cir.func @_Z5vcallR2C1(%arg0: !cir.ptr<!ty_C1_>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_C1_>, !cir.ptr<!cir.ptr<!ty_C1_>>, ["c1", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !ty_buffy, !cir.ptr<!ty_buffy>, ["b"] {alignment = 8 : i64}
// CHECK: %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64}
// CHECK: %3 = cir.alloca !ty_buffy, !cir.ptr<!ty_buffy>, ["agg.tmp0"] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_C1_>, !cir.ptr<!cir.ptr<!ty_C1_>>
// CHECK: %4 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_C1_>>, !cir.ptr<!ty_C1_>
// CHECK: %5 = cir.load %2 : !cir.ptr<!s32i>, !s32i
// CHECK: cir.call @_ZN5buffyC2ERKS_(%3, %1) : (!cir.ptr<!ty_buffy>, !cir.ptr<!ty_buffy>) -> ()
// CHECK: %6 = cir.load %3 : !cir.ptr<!ty_buffy>, !ty_buffy
// CHECK: %7 = cir.cast(bitcast, %4 : !cir.ptr<!ty_C1_>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>>
// CHECK: %8 = cir.load %7 : !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>>, !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>
// CHECK: %9 = cir.vtable.address_point( %8 : !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>
// CHECK: %10 = cir.load align(8) %9 : !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>>, !cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>
// CHECK: %11 = cir.call %10(%4, %5, %6) : (!cir.ptr<!cir.func<!s32i (!cir.ptr<!ty_C1_>, !s32i, !ty_buffy)>>, !cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i
// CHECK: cir.return
// CHECK: }
class A {
public:
int a;
virtual void foo() {a++;}
};
class B : public A {
public:
int b;
void foo () { static_cast<A>(*this).foo();}
};
// CHECK: cir.func linkonce_odr @_ZN1B3fooEv(%arg0: !cir.ptr<!ty_B>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_B>, !cir.ptr<!cir.ptr<!ty_B>>, ["this", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_B>, !cir.ptr<!cir.ptr<!ty_B>>
// CHECK: %1 = cir.load deref %0 : !cir.ptr<!cir.ptr<!ty_B>>, !cir.ptr<!ty_B>
// CHECK: cir.scope {
// CHECK: %2 = cir.alloca !ty_A, !cir.ptr<!ty_A>, ["ref.tmp0"] {alignment = 8 : i64}
// CHECK: %3 = cir.base_class_addr(%1 : !cir.ptr<!ty_B>) -> !cir.ptr<!ty_A>
// Call @A::A(A const&)
// CHECK: cir.call @_ZN1AC2ERKS_(%2, %3) : (!cir.ptr<!ty_A>, !cir.ptr<!ty_A>) -> ()
// Call @A::foo()
// CHECK: cir.call @_ZN1A3fooEv(%2) : (!cir.ptr<!ty_A>) -> ()
// CHECK: }
// CHECK: cir.return
// CHECK: }
void t() {
B b;
b.foo();
}
struct C : public A {
int& ref;
C(int& x) : ref(x) {}
};
// CHECK: cir.func @_Z8test_refv()
// CHECK: cir.get_member %2[1] {name = "ref"}
int test_ref() {
int x = 42;
C c(x);
return c.ref;
}