forked from standardese/cppast
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp_type.hpp
More file actions
459 lines (373 loc) · 12.4 KB
/
Copy pathcpp_type.hpp
File metadata and controls
459 lines (373 loc) · 12.4 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
// Copyright (C) 2017-2018 Jonathan Müller <[email protected]>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.
#ifndef CPPAST_CPP_TYPE_HPP_INCLUDED
#define CPPAST_CPP_TYPE_HPP_INCLUDED
#include <atomic>
#include <memory>
#include <cppast/code_generator.hpp>
#include <cppast/cpp_entity_ref.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast
{
/// The kinds of a [cppast::cpp_type]().
enum class cpp_type_kind
{
builtin_t,
user_defined_t,
auto_t,
decltype_t,
decltype_auto_t,
cv_qualified_t,
pointer_t,
reference_t,
array_t,
function_t,
member_function_t,
member_object_t,
template_parameter_t,
template_instantiation_t,
dependent_t,
unexposed_t,
};
/// Base class for all C++ types.
class cpp_type : detail::intrusive_list_node<cpp_type>
{
public:
cpp_type(const cpp_type&) = delete;
cpp_type& operator=(const cpp_type&) = delete;
virtual ~cpp_type() noexcept = default;
/// \returns The [cppast::cpp_type_kind]().
cpp_type_kind kind() const noexcept
{
return do_get_kind();
}
/// \returns The specified user data.
void* user_data() const noexcept
{
return user_data_.load();
}
/// \effects Sets some kind of user data.
///
/// User data is just some kind of pointer, there are no requirements.
/// The class will do no lifetime management.
///
/// User data is useful if you need to store additional data for an entity without the need to
/// maintain a registry.
void set_user_data(void* data) const noexcept
{
user_data_ = data;
}
protected:
cpp_type() noexcept : user_data_(nullptr) {}
private:
/// \returns The [cppast::cpp_type_kind]().
virtual cpp_type_kind do_get_kind() const noexcept = 0;
void on_insert(const cpp_type&) {}
mutable std::atomic<void*> user_data_;
template <typename T>
friend struct detail::intrusive_list_access;
friend detail::intrusive_list_node<cpp_type>;
};
/// An unexposed [cppast::cpp_type]().
///
/// This is one where no further information besides a name is available.
class cpp_unexposed_type final : public cpp_type
{
public:
/// \returns A newly created unexposed type.
static std::unique_ptr<cpp_unexposed_type> build(std::string name)
{
return std::unique_ptr<cpp_unexposed_type>(new cpp_unexposed_type(std::move(name)));
}
/// \returns The name of the type.
const std::string& name() const noexcept
{
return name_;
}
private:
cpp_unexposed_type(std::string name) : name_(std::move(name)) {}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::unexposed_t;
}
std::string name_;
};
/// The C++ builtin types.
enum cpp_builtin_type_kind
{
cpp_void, //< `void`
cpp_bool, //< `bool`
cpp_uchar, //< `unsigned char`
cpp_ushort, //< `unsigned short`
cpp_uint, //< `unsigned int`
cpp_ulong, //< `unsigned long`
cpp_ulonglong, //< `unsigned long long`
cpp_uint128, //< `unsigned __int128`
cpp_schar, //< `signed char`
cpp_short, //< `short`
cpp_int, //< `int`
cpp_long, //< `long`
cpp_longlong, //< `long long`
cpp_int128, //< `__int128`
cpp_float, //< `float`
cpp_double, //< `double`
cpp_longdouble, //< `long double`
cpp_float128, //< `__float128`
cpp_char, //< `char`
cpp_wchar, //< `wchar_t`
cpp_char16, //< `char16_t`
cpp_char32, //< `char32_t`
cpp_nullptr, //< `decltype(nullptr)` aka `std::nullptr_t`
};
/// \returns The string representing the spelling of that type in the source code.
const char* to_string(cpp_builtin_type_kind kind) noexcept;
/// A builtin [cppast::cpp_type]().
///
/// This is one where there is no associated [cppast::cpp_entity]().
class cpp_builtin_type final : public cpp_type
{
public:
/// \returns A newly created builtin type.
static std::unique_ptr<cpp_builtin_type> build(cpp_builtin_type_kind kind)
{
return std::unique_ptr<cpp_builtin_type>(new cpp_builtin_type(kind));
}
/// \returns Which builtin type it is.
cpp_builtin_type_kind builtin_type_kind() const noexcept
{
return kind_;
}
private:
cpp_builtin_type(cpp_builtin_type_kind kind) : kind_(kind) {}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::builtin_t;
}
cpp_builtin_type_kind kind_;
};
/// \exclude
namespace detail
{
struct cpp_type_ref_predicate
{
bool operator()(const cpp_entity& e);
};
} // namespace detail
/// Reference to a [cppast::cpp_entity]() representing a new type.
using cpp_type_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_type_ref_predicate>;
/// A user-defined [cppast::cpp_type]().
///
/// It has an associated [cppast::cpp_entity]().
class cpp_user_defined_type final : public cpp_type
{
public:
/// \returns A newly created user-defined type.
static std::unique_ptr<cpp_user_defined_type> build(cpp_type_ref entity)
{
return std::unique_ptr<cpp_user_defined_type>(new cpp_user_defined_type(std::move(entity)));
}
/// \returns A [cppast::cpp_type_ref]() to the associated [cppast::cpp_entity]() that is the
/// type.
const cpp_type_ref& entity() const noexcept
{
return entity_;
}
private:
cpp_user_defined_type(cpp_type_ref entity) : entity_(std::move(entity)) {}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::user_defined_t;
}
cpp_type_ref entity_;
};
/// A [cppast::cpp_type]() that isn't given but deduced by `auto`.
class cpp_auto_type final : public cpp_type
{
public:
/// \returns A newly created `auto` type.
static std::unique_ptr<cpp_auto_type> build()
{
return std::unique_ptr<cpp_auto_type>(new cpp_auto_type);
}
private:
cpp_auto_type() = default;
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::auto_t;
}
};
class cpp_template_parameter_type;
class cpp_template_instantiation_type;
/// A [cppast::cpp_type]() that depends on another type.
class cpp_dependent_type final : public cpp_type
{
public:
/// \returns A newly created type dependent on a [cppast::cpp_template_parameter_type]().
static std::unique_ptr<cpp_dependent_type> build(
std::string name, std::unique_ptr<cpp_template_parameter_type> dependee);
/// \returns A newly created type dependent on a [cppast::cpp_template_instantiation_type]().
static std::unique_ptr<cpp_dependent_type> build(
std::string name, std::unique_ptr<cpp_template_instantiation_type> dependee);
/// \returns The name of the dependent type.
/// \notes It does not include a scope.
const std::string& name() const noexcept
{
return name_;
}
/// \returns A reference to the [cppast::cpp_type]() it depends one.
/// \notes This is either [cppast::cpp_template_parameter_type]() or
/// [cppast:cpp_template_instantiation_type]().
const cpp_type& dependee() const noexcept
{
return *dependee_;
}
private:
cpp_dependent_type(std::string name, std::unique_ptr<cpp_type> dependee)
: name_(std::move(name)), dependee_(std::move(dependee))
{}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::dependent_t;
}
std::string name_;
std::unique_ptr<cpp_type> dependee_;
};
/// The kinds of C++ cv qualifiers.
enum cpp_cv
{
cpp_cv_none,
cpp_cv_const,
cpp_cv_volatile,
cpp_cv_const_volatile,
};
/// \returns `true` if the qualifier contains `const`.
inline bool is_const(cpp_cv cv) noexcept
{
return cv == cpp_cv_const || cv == cpp_cv_const_volatile;
}
/// \returns `true` if the qualifier contains `volatile`.
inline bool is_volatile(cpp_cv cv) noexcept
{
return cv == cpp_cv_volatile || cv == cpp_cv_const_volatile;
}
/// A [cppast::cpp_cv]() qualified [cppast::cpp_type]().
class cpp_cv_qualified_type final : public cpp_type
{
public:
/// \returns A newly created qualified type.
/// \requires `cv` must not be [cppast::cpp_cv::cpp_cv_none]().
static std::unique_ptr<cpp_cv_qualified_type> build(std::unique_ptr<cpp_type> type, cpp_cv cv)
{
DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{});
return std::unique_ptr<cpp_cv_qualified_type>(
new cpp_cv_qualified_type(std::move(type), cv));
}
/// \returns A reference to the [cppast::cpp_type]() that is qualified.
const cpp_type& type() const noexcept
{
return *type_;
}
/// \returns The [cppast::cpp_cv]() qualifier.
cpp_cv cv_qualifier() const noexcept
{
return cv_;
}
private:
cpp_cv_qualified_type(std::unique_ptr<cpp_type> type, cpp_cv cv)
: type_(std::move(type)), cv_(cv)
{}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::cv_qualified_t;
}
std::unique_ptr<cpp_type> type_;
cpp_cv cv_;
};
/// \returns The type without top-level const/volatile qualifiers.
const cpp_type& remove_cv(const cpp_type& type) noexcept;
/// \returns The type without top-level const qualifiers.
const cpp_type& remove_const(const cpp_type& type) noexcept;
/// \returns The type without top-level volatile qualifiers.
const cpp_type& remove_volatile(const cpp_type& type) noexcept;
/// A pointer to a [cppast::cpp_type]().
class cpp_pointer_type final : public cpp_type
{
public:
/// \returns A newly created pointer type.
static std::unique_ptr<cpp_pointer_type> build(std::unique_ptr<cpp_type> pointee)
{
return std::unique_ptr<cpp_pointer_type>(new cpp_pointer_type(std::move(pointee)));
}
/// \returns A reference to the [cppast::cpp_type]() that is the pointee.
const cpp_type& pointee() const noexcept
{
return *pointee_;
}
private:
cpp_pointer_type(std::unique_ptr<cpp_type> pointee) : pointee_(std::move(pointee)) {}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::pointer_t;
}
std::unique_ptr<cpp_type> pointee_;
};
/// The kinds of C++ references.
enum cpp_reference
{
cpp_ref_none,
cpp_ref_lvalue,
cpp_ref_rvalue,
};
/// A reference to a [cppast::cpp_type]().
class cpp_reference_type final : public cpp_type
{
public:
/// \returns A newly created qualified type.
/// \requires `ref` must not be [cppast::cpp_reference::cpp_ref_none]().
static std::unique_ptr<cpp_reference_type> build(std::unique_ptr<cpp_type> type,
cpp_reference ref)
{
DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{});
return std::unique_ptr<cpp_reference_type>(new cpp_reference_type(std::move(type), ref));
}
/// \returns A reference to the [cppast::cpp_type]() that is referenced.
const cpp_type& referee() const noexcept
{
return *referee_;
}
/// \returns The [cppast::cpp_reference]() type.
cpp_reference reference_kind() const noexcept
{
return ref_;
}
private:
cpp_reference_type(std::unique_ptr<cpp_type> referee, cpp_reference ref)
: referee_(std::move(referee)), ref_(ref)
{}
cpp_type_kind do_get_kind() const noexcept override
{
return cpp_type_kind::reference_t;
}
std::unique_ptr<cpp_type> referee_;
cpp_reference ref_;
};
/// \returns The type as a string representation.
std::string to_string(const cpp_type& type);
/// \exclude
namespace detail
{
// whether or not it requires special treatment when printing it
// i.e. function pointer types are complex as the identifier has to be put inside
bool is_complex_type(const cpp_type& type) noexcept;
// write part of the type that comes before the variable name
void write_type_prefix(code_generator::output& output, const cpp_type& type);
// write part of the type that comes after the name
// for non-complex types, this does nothing
void write_type_suffix(code_generator::output& output, const cpp_type& type);
// write prefix, variadic, name, suffix
void write_type(code_generator::output& output, const cpp_type& type, std::string name,
bool is_variadic = false);
} // namespace detail
} // namespace cppast
#endif // CPPAST_CPP_TYPE_HPP_INCLUDED