aboutsummaryrefslogtreecommitdiff
path: root/clang/test/Modules/pr93497.cppm
blob: 64a08e2a85e63e20bebf28652eb5ff5ed88308f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t

// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/mod.cppm \
// RUN:     -emit-module-interface -o %t/mod.pcm
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp \
// RUN:     -fmodule-file=mod=%t/mod.pcm -emit-llvm \
// RUN:     -o - | opt -S --passes=simplifycfg | FileCheck %t/use.cpp

//--- mod.cppm
export module mod;

export struct Thing {
    static const Thing One;
    explicit Thing(int raw) :raw(raw) { }
    int raw;
};

const Thing Thing::One = Thing(1);

export struct C {
    int value;
};
export const C ConstantValue = {1};

export const C *ConstantPtr = &ConstantValue;

C NonConstantValue = {1};
export const C &ConstantRef = NonConstantValue;

export struct NonConstexprDtor {
    constexpr NonConstexprDtor(int raw) : raw(raw) {}
    ~NonConstexprDtor();

    int raw;
};

export const NonConstexprDtor NonConstexprDtorValue = {1};

//--- use.cpp
import mod;

int consume(int);
int consumeC(C);

extern "C" __attribute__((noinline)) inline int unneeded() {
    return consume(43);
}

extern "C" __attribute__((noinline)) inline int needed() {
    return consume(43);
}

int use() {
    Thing t1 = Thing::One;
    return consume(t1.raw);
}

int use2() {
    if (ConstantValue.value)
        return consumeC(ConstantValue);
    return unneeded();
}

int use3() {
    auto Ptr = ConstantPtr;
    if (Ptr->value)
        return consumeC(*Ptr);
    return needed();
}

int use4() {
    auto Ref = ConstantRef;
    if (Ref.value)
        return consumeC(Ref);
    return needed();
}

int use5() {
    NonConstexprDtor V = NonConstexprDtorValue;
    if (V.raw)
        return consume(V.raw);
    return needed();
}

// CHECK: @_ZNW3mod5Thing3OneE = external
// CHECK: @_ZW3mod13ConstantValue ={{.*}}available_externally{{.*}} constant 
// CHECK: @_ZW3mod11ConstantPtr = external
// CHECK: @_ZW3mod16NonConstantValue = external
// CHECK: @_ZW3mod21NonConstexprDtorValue = external

// Check that the middle end can optimize the program by the constant information.
// CHECK-NOT: @unneeded(

// Check that the use of ConstantPtr won't get optimized incorrectly.
// CHECK-LABEL: @_Z4use3v(
// CHECK: @needed(

// Check that the use of ConstantRef won't get optimized incorrectly.
// CHECK-LABEL: @_Z4use4v(
// CHECK: @needed(

// Check that the use of NonConstexprDtorValue won't get optimized incorrectly.
// CHECK-LABEL: @_Z4use5v(
// CHECK: @needed(