• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 20764569418

06 Jan 2026 10:50PM UTC coverage: 62.168% (+21.4%) from 40.764%
20764569418

push

github

web-flow
Merge pull request #433 from daisytuner/clang-coverage

updates clang coverage flags

14988 of 24109 relevant lines covered (62.17%)

88.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.2
/src/analysis/type_analysis.cpp
1
#include "sdfg/analysis/type_analysis.h"
2

3
#include "sdfg/analysis/users.h"
4
#include "sdfg/structured_control_flow/control_flow_node.h"
5

6
namespace sdfg {
7
namespace analysis {
8

9
void TypeAnalysis::run(analysis::AnalysisManager& analysis_manager) {
10✔
10
    std::vector<std::string> containers;
10✔
11
    for (auto container : this->sdfg_.containers()) {
19✔
12
        auto& contType = sdfg_.type(container);
19✔
13
        if (contType.type_id() == sdfg::types::TypeID::Pointer) {
19✔
14
            auto pointer_type = static_cast<const sdfg::types::Pointer*>(&sdfg_.type(container));
13✔
15
            if (!pointer_type->has_pointee_type()) {
13✔
16
                containers.push_back(container);
12✔
17
            }
12✔
18
        } else if (contType.type_id() == sdfg::types::TypeID::Structure) { // we model std::shared_ptr as pointer-like
13✔
19
                                                                           // structure
20
            // if we find uses of it AS a pointer those can also be used
21
            auto struct_type = static_cast<const sdfg::types::Structure&>(contType);
×
22
            if (struct_type.is_pointer_like()) {
×
23
                containers.push_back(container);
×
24
            }
×
25
        }
×
26
    }
19✔
27

28
    auto& users = analysis_manager.get<Users>();
10✔
29
    structured_control_flow::ControlFlowNode* node = &sdfg_.root();
10✔
30
    if (node_) {
10✔
31
        node = node_;
×
32
    }
×
33
    UsersView users_view(users, *node);
10✔
34

35
    for (auto container : containers) {
12✔
36
        // iterate over writes
37
        for (auto user : users_view.writes(container)) {
12✔
38
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
4✔
39
            if (access_node == nullptr) {
4✔
40
                continue;
×
41
            }
×
42

43
            for (auto& memlet : access_node->get_parent().in_edges(*access_node)) {
4✔
44
                auto base_type = &memlet.base_type();
4✔
45
                if (base_type->type_id() == types::TypeID::Pointer) {
4✔
46
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
4✔
47
                    if (!pointer_type->has_pointee_type()) {
4✔
48
                        continue;
×
49
                    }
×
50
                } else if (base_type->type_id() == types::TypeID::Structure) { // pointer-likes may also be used raw.
4✔
51
                                                                               // Cannot glean anything from those
52
                                                                               // accesses directly
53
                    continue;
×
54
                }
×
55

56
                if (memlet.type() == data_flow::MemletType::Dereference_Src) {
4✔
57
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
58
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
59
                        base_type = &pointer_type->pointee_type();
×
60

61
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
×
62
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
63
                        base_type = &array_type->element_type();
64
                    } */
65

66
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
67
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
68
                        if (!inner_pointer_type->has_pointee_type()) {
×
69
                            continue;
×
70
                        }
×
71
                    }
×
72
                }
×
73

74
                if (this->type_map_.find(container) == this->type_map_.end()) {
4✔
75
                    this->type_map_.insert({container, {base_type}});
3✔
76
                    continue;
3✔
77
                } else {
3✔
78
                    bool insert = true;
1✔
79
                    for (auto type : this->type_map_.at(container)) {
1✔
80
                        if (*type == *base_type) {
1✔
81
                            insert = false;
×
82
                            break;
×
83
                        }
×
84
                    }
1✔
85
                    if (insert) {
1✔
86
                        this->type_map_.at(container).insert(base_type);
1✔
87
                    }
1✔
88
                }
1✔
89
            }
4✔
90
        }
4✔
91

92
        // iterate over reads
93
        for (auto user : users_view.reads(container)) {
12✔
94
            // Pointers may be used in symbolic conditions
95
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
5✔
96
            if (access_node == nullptr) {
5✔
97
                continue;
×
98
            }
×
99

100
            for (auto& memlet : access_node->get_parent().out_edges(*access_node)) {
5✔
101
                auto base_type = &memlet.base_type();
5✔
102
                if (base_type->type_id() == types::TypeID::Pointer) {
5✔
103
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
5✔
104
                    if (!pointer_type->has_pointee_type()) {
5✔
105
                        continue;
×
106
                    }
×
107
                } else if (base_type->type_id() == types::TypeID::Structure) { // pointer-likes may also be used raw.
5✔
108
                                                                               // Cannot glean anything from those
109
                                                                               // accesses directly
110
                    continue;
×
111
                }
×
112

113
                if (memlet.type() == data_flow::MemletType::Dereference_Dst) {
5✔
114
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
115
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
116
                        base_type = &pointer_type->pointee_type();
×
117

118
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
×
119
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
120
                        base_type = &array_type->element_type();
121
                    } */
122

123
                    if (base_type->type_id() == types::TypeID::Pointer) {
×
124
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
×
125
                        if (!inner_pointer_type->has_pointee_type()) {
×
126
                            continue;
×
127
                        }
×
128
                    }
×
129
                }
×
130
                if (this->type_map_.find(container) == this->type_map_.end()) {
5✔
131
                    this->type_map_.insert({container, {base_type}});
4✔
132
                    continue;
4✔
133
                } else {
4✔
134
                    bool insert = true;
1✔
135
                    for (auto type : this->type_map_.at(container)) {
1✔
136
                        if (*type == *base_type) {
1✔
137
                            insert = false;
×
138
                            break;
×
139
                        }
×
140
                    }
1✔
141
                    if (insert) {
1✔
142
                        this->type_map_.at(container).insert(base_type);
1✔
143
                    }
1✔
144
                }
1✔
145
            }
5✔
146
        }
5✔
147

148
        // iterate over views
149
        for (auto user : users_view.views(container)) {
12✔
150
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
151
            if (access_node == nullptr) {
3✔
152
                continue;
×
153
            }
×
154
            for (auto& memlet : access_node->get_parent().out_edges(*access_node)) {
3✔
155
                auto base_type = &memlet.base_type();
3✔
156
                if (base_type->type_id() == types::TypeID::Pointer) {
3✔
157
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
3✔
158
                    if (!pointer_type->has_pointee_type()) {
3✔
159
                        continue;
×
160
                    }
×
161
                } else if (base_type->type_id() == types::TypeID::Structure) { // pointer-likes may also be used raw.
3✔
162
                                                                               // Cannot glean anything from those
163
                                                                               // accesses directly
164
                    continue;
×
165
                }
×
166

167
                if (memlet.type() == data_flow::MemletType::Dereference_Dst) {
3✔
168
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
169
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
170
                        base_type = &pointer_type->pointee_type();
2✔
171

172
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
2✔
173
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
174
                        base_type = &array_type->element_type();
175
                    } */
176

177
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
178
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
179
                        if (!inner_pointer_type->has_pointee_type()) {
2✔
180
                            continue;
×
181
                        }
×
182
                    }
2✔
183
                }
2✔
184
                if (this->type_map_.find(container) == this->type_map_.end()) {
3✔
185
                    this->type_map_.insert({container, {base_type}});
3✔
186
                    continue;
3✔
187
                } else {
3✔
188
                    bool insert = true;
×
189
                    for (auto type : this->type_map_.at(container)) {
×
190
                        if (*type == *base_type) {
×
191
                            insert = false;
×
192
                            break;
×
193
                        }
×
194
                    }
×
195
                    if (insert) {
×
196
                        this->type_map_.at(container).insert(base_type);
×
197
                    }
×
198
                }
×
199
            }
3✔
200
        }
3✔
201

202
        // iterate over moves
203
        for (auto user : users_view.moves(container)) {
12✔
204
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
205
            if (access_node == nullptr) {
3✔
206
                continue;
×
207
            }
×
208
            for (auto& memlet : access_node->get_parent().in_edges(*access_node)) {
4✔
209
                auto base_type = &memlet.base_type();
4✔
210
                if (base_type->type_id() == types::TypeID::Pointer) {
4✔
211
                    auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
4✔
212
                    if (!pointer_type->has_pointee_type()) {
4✔
213
                        continue;
×
214
                    }
×
215
                } else if (base_type->type_id() == types::TypeID::Structure) {
4✔
216
                    continue;
×
217
                }
×
218

219
                if (memlet.type() == data_flow::MemletType::Dereference_Src) {
4✔
220
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
221
                        auto pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
222
                        base_type = &pointer_type->pointee_type();
2✔
223

224
                    } /* else if (base_type->type_id() == types::TypeID::Array) {
2✔
225
                        auto array_type = dynamic_cast<const types::Array*>(base_type);
226
                        base_type = &array_type->element_type();
227
                    } */
228

229
                    if (base_type->type_id() == types::TypeID::Pointer) {
2✔
230
                        auto inner_pointer_type = dynamic_cast<const types::Pointer*>(base_type);
2✔
231
                        if (!inner_pointer_type->has_pointee_type()) {
2✔
232
                            continue;
×
233
                        }
×
234
                    }
2✔
235
                }
2✔
236
                if (this->type_map_.find(container) == this->type_map_.end()) {
4✔
237
                    this->type_map_.insert({container, {base_type}});
2✔
238
                    continue;
2✔
239
                } else {
2✔
240
                    bool insert = true;
2✔
241
                    for (auto type : this->type_map_.at(container)) {
2✔
242
                        if (*type == *base_type) {
2✔
243
                            insert = false;
2✔
244
                            break;
2✔
245
                        }
2✔
246
                    }
2✔
247
                    if (insert) {
2✔
248
                        this->type_map_.at(container).insert(base_type);
×
249
                    }
×
250
                }
2✔
251
            }
4✔
252
        }
3✔
253
    }
12✔
254
}
10✔
255

256
TypeAnalysis::TypeAnalysis(StructuredSDFG& sdfg) : Analysis(sdfg), node_(nullptr) {}
10✔
257

258
TypeAnalysis::TypeAnalysis(
259
    StructuredSDFG& sdfg, structured_control_flow::ControlFlowNode* node, AnalysisManager& analysis_manager
260
)
261
    : Analysis(sdfg), node_(node) {
×
262
    run(analysis_manager);
×
263
}
×
264

265
const sdfg::types::IType* TypeAnalysis::get_outer_type(const std::string& container) const {
34✔
266
    auto& contType = sdfg_.type(container);
34✔
267
    if (contType.type_id() == sdfg::types::TypeID::Pointer) {
34✔
268
        auto pointer_type = static_cast<const sdfg::types::Pointer*>(&contType);
24✔
269
        if (pointer_type->has_pointee_type()) {
24✔
270
            return pointer_type;
2✔
271
        }
2✔
272
    } else if (contType.type_id() == sdfg::types::TypeID::Structure &&
24✔
273
               static_cast<const types::Structure&>(contType).is_pointer_like()) {
10✔
274
    } else {
10✔
275
        return &contType;
10✔
276
    }
10✔
277

278
    auto it = type_map_.find(container);
22✔
279
    if (it != type_map_.end()) {
22✔
280
        if (it->second.size() == 1) {
22✔
281
            for (auto i : it->second) {
20✔
282
                return i;
20✔
283
            }
20✔
284
        }
20✔
285
    }
22✔
286
    return nullptr;
2✔
287
}
22✔
288

289
} // namespace analysis
290
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc