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

rieske / trans / 28460339749

30 Jun 2026 04:35PM UTC coverage: 90.401% (-0.1%) from 90.53%
28460339749

Pull #44

github

rieske
Simplify struct field codegen to FieldAddress only

Drop FieldLoad/FieldStore; materialize the field address then reuse
Dereference for reads and LvalueAssign for writes. Keep a single
baseIsPointer flag on FieldAddress for dot vs arrow.
Pull Request #44: Implement C structs with member access

236 of 282 new or added lines in 12 files covered. (83.69%)

7 existing lines in 2 files now uncovered.

5349 of 5917 relevant lines covered (90.4%)

235740.3 hits per line

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

89.47
/src/types/Type.cpp
1
#include "Type.h"
2

3
#include <stdexcept>
4
#include <algorithm>
5
#include <sstream>
6

7
namespace type {
8

9
static const int POINTER_SIZE {8};
10

11
Type voidType() {
48✔
12
    return Type{{}};
48✔
13
}
14

15
Type primitive(const Primitive& primitive, const std::vector<Qualifier>& qualifiers) {
4,554✔
16
    return Type{primitive, qualifiers};
4,554✔
17
}
18

19
Type pointer(const Type& pointsTo, const std::vector<Qualifier>& qualifiers) {
1,246✔
20
    auto p = Type{pointsTo};
1,246✔
21
    p._indirection = pointsTo._indirection+1;
1,246✔
22
    return p;
1,246✔
23
}
24

25
Type function(const Type& returnType, const std::vector<Type>& arguments) {
2,104✔
26
    return Type{returnType, arguments};
2,104✔
27
}
28

29
Type signedCharacter(const std::vector<Qualifier>& qualifiers) {
828✔
30
    return primitive(Primitive::signedCharacter(), qualifiers);
828✔
31
}
32
Type unsignedCharacter(const std::vector<Qualifier>& qualifiers) {
4✔
33
    return primitive(Primitive::unsignedCharacter(), qualifiers);
4✔
34
}
35

36
Type signedInteger(const std::vector<Qualifier>& qualifiers) {
3,706✔
37
    return primitive(Primitive::signedInteger(), qualifiers);
3,706✔
38
}
39

40
Type unsignedInteger(const std::vector<Qualifier>& qualifiers) {
4✔
41
    return primitive(Primitive::unsignedInteger(), qualifiers);
4✔
42
}
43

44
Type signedLong(const std::vector<Qualifier>& qualifiers) {
2✔
45
    return primitive(Primitive::signedLong(), qualifiers);
2✔
46
}
47

48
Type unsignedLong(const std::vector<Qualifier>& qualifiers) {
4✔
49
    return primitive(Primitive::unsignedLong(), qualifiers);
4✔
50
}
51

52
Type floating(const std::vector<Qualifier>& qualifiers) {
2✔
53
    return primitive(Primitive::floating(), qualifiers);
2✔
54
}
55

56
Type doubleFloating(const std::vector<Qualifier>& qualifiers) {
2✔
57
    return primitive(Primitive::doubleFloating(), qualifiers);
2✔
58
}
59

60
Type longDoubleFloating(const std::vector<Qualifier>& qualifiers) {
2✔
61
    return primitive(Primitive::longDoubleFloating(), qualifiers);
2✔
62
}
63

64
Type::Type(std::vector<Qualifier> qualifiers) {
4,608✔
65
    for (const auto& qualifier: qualifiers) {
4,616✔
66
        switch(qualifier) {
8✔
67
            case Qualifier::CONST:
4✔
68
                this->_const = true;
4✔
69
                break;
4✔
70
            case Qualifier::VOLATILE:
4✔
71
                this->_volatile = true;
4✔
72
                break;
4✔
73
            default:
×
74
                throw std::invalid_argument{"Unsupported type qualifier"};
×
75
        }
76
    }
77
}
4,608✔
78

79
Type::Type(const Primitive& primitive, std::vector<Qualifier> qualifiers):
4,554✔
80
    Type{qualifiers}
4,554✔
81
{
82
    _primitive = primitive;
4,554✔
83
}
4,554✔
84

85
Type::Type(const Type& returnType, const std::vector<Type>& arguments) {
2,104✔
86
    std::vector<std::unique_ptr<Type>> args;
2,104✔
87
    for (const auto& arg : arguments) {
2,448✔
88
        args.push_back(std::make_unique<Type>(arg));
344✔
89
    }
90
    _function = Function{std::make_unique<Type>(returnType), std::move(args)};
2,104✔
91
}
2,104✔
92

93
int Type::getSize() const {
4,732✔
94
    if (isPointer()) {
4,732✔
95
        return POINTER_SIZE;
1,314✔
96
    }
97
    if (isPrimitive()) {
3,418✔
98
        return _primitive->getSize();
3,402✔
99
    }
100

101
    return _size;
16✔
102
}
103

104
bool Type::canAssignFrom(const Type& other) const {
992✔
105
    // TODO:
106
    return true;
992✔
107
}
108

109
bool Type::isVoid() const {
9,924✔
110
    return !isPrimitive() && !isFunction() && !isPointer() && !isStructure();
9,924✔
111
}
112

113
bool Type::isPrimitive() const {
19,368✔
114
    return _primitive.has_value();
19,368✔
115
}
116

117
Primitive Type::getPrimitive() const {
60✔
118
    return *_primitive;
60✔
119
}
120

121
bool Type::isConst() const {
5,992✔
122
    return _const;
5,992✔
123
}
124

125
bool Type::isVolatile() const {
5,992✔
126
    return _volatile;
5,992✔
127
}
128

129
bool Type::isPointer() const {
13,602✔
130
    return _indirection;
13,602✔
131
}
132

133
bool Type::isFunction() const {
78✔
134
    return _function.has_value();
78✔
135
}
136

137
Function Type::getFunction() const {
1,266✔
138
    return *_function;
1,266✔
139
}
140

141

142
Type Type::dereference() const {
1,424✔
143
    if (!isPointer()) {
1,424✔
UNCOV
144
        throw std::domain_error{"can not dereference non-pointer type"};
×
145
    }
146
    Type pointsTo = Type{*this};
1,424✔
147
    --pointsTo._indirection;
1,424✔
148
    return pointsTo;
1,424✔
149
}
150

151
std::string Type::to_string() const {
7,312✔
152
    if (isVoid()) {
7,312✔
153
        return "void";
20✔
154
    }
155
    if (isPointer()) {
7,302✔
156
        return dereference().to_string() + "*";
1,322✔
157
    }
158
    if (isPrimitive()) {
5,980✔
159
        std::stringstream str;
5,964✔
160
        if (isConst()) {
5,964✔
161
            str << "const ";
4✔
162
        }
163
        if (isVolatile()) {
5,964✔
164
            str << "volatile ";
4✔
165
        }
166
        str << _primitive->to_string();
5,964✔
167
        return str.str();
5,964✔
168
    }
5,964✔
169
    if (isFunction()) {
16✔
170
        return _function->to_string();
8✔
171
    }
172
    return "unknown type";
16✔
173
}
174

175
Type::Member::Member(std::string n, Type t, int off) :
12✔
176
        name { std::move(n) },
12✔
177
        type { std::make_unique<Type>(std::move(t)) },
12✔
178
        offsetBytes { off }
12✔
179
{
180
}
12✔
181

182
Type::Member::Member(const Member& other) :
1,000✔
183
        name { other.name },
1,000✔
184
        type { other.type ? std::make_unique<Type>(*other.type) : nullptr },
1,000✔
185
        offsetBytes { other.offsetBytes }
1,000✔
186
{
187
}
1,000✔
188

NEW
189
Type::Member& Type::Member::operator=(const Member& other) {
×
NEW
190
    if (this != &other) {
×
NEW
191
        name = other.name;
×
NEW
192
        type = other.type ? std::make_unique<Type>(*other.type) : nullptr;
×
NEW
193
        offsetBytes = other.offsetBytes;
×
194
    }
NEW
195
    return *this;
×
196
}
197

198
namespace {
199
constexpr int WORD_ALIGN = 8;
200

201
int alignUp(int value, int alignment) {
30✔
202
    return (value + alignment - 1) / alignment * alignment;
30✔
203
}
204

205
int memberStride(const Type& memberType) {
12✔
206
    int size = memberType.getSize();
12✔
207
    if (size < 1) {
12✔
NEW
208
        size = 1;
×
209
    }
210
    return alignUp(size, WORD_ALIGN);
12✔
211
}
212
} // namespace
213

214
Type structure(std::vector<std::pair<std::string, Type>> members) {
6✔
215
    Type result { std::vector<Qualifier> {} };
6✔
216
    std::vector<Type::Member> laidOut;
6✔
217
    int offset = 0;
6✔
218
    for (auto& entry : members) {
18✔
219
        offset = alignUp(offset, WORD_ALIGN);
12✔
220
        laidOut.emplace_back(entry.first, entry.second, offset);
12✔
221
        offset += memberStride(entry.second);
12✔
222
    }
223
    result._size = alignUp(offset, WORD_ALIGN);
6✔
224
    result._structure = std::move(laidOut);
6✔
225
    return result;
12✔
226
}
6✔
227

228
bool Type::isStructure() const {
56✔
229
    return _structure.has_value();
56✔
230
}
231

NEW
232
const std::vector<Type::Member>& Type::getStructMembers() const {
×
NEW
233
    return *_structure;
×
234
}
235

236
bool Type::memberOffset(const std::string& memberName, int& offsetBytes) const {
24✔
237
    if (!_structure) {
24✔
NEW
238
        return false;
×
239
    }
240
    for (const auto& member : *_structure) {
36✔
241
        if (member.name == memberName) {
36✔
242
            offsetBytes = member.offsetBytes;
24✔
243
            return true;
24✔
244
        }
245
    }
NEW
246
    return false;
×
247
}
248

249
bool Type::memberType(const std::string& memberName, Type& outType) const {
24✔
250
    if (!_structure) {
24✔
NEW
251
        return false;
×
252
    }
253
    for (const auto& member : *_structure) {
36✔
254
        if (member.name == memberName) {
36✔
255
            outType = *member.type;
24✔
256
            return true;
24✔
257
        }
258
    }
NEW
259
    return false;
×
260
}
261

262
} // namespace type
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