0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
template_parameter.h
Go to the documentation of this file.
1/**
2 * @file src/common/model/template_parameter.h
3 *
4 * Copyright (c) 2021-2025 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#pragma once
19
20#include "common/model/enums.h"
22#include "common/types.h"
23
24#include <deque>
25#include <optional>
26#include <set>
27#include <string>
28#include <vector>
29
30namespace clang {
31// TODO: This doesn't belong here, find_nested_relationship should not depend
32// on clang::Decl - refactor...
33class Decl;
34}
35
37
39
40/**
41 * Type of template parameter or argument.
42 */
44 template_type, /*!< Template type, e.g. <typename T> */
45 template_template_type, /*!< Template template type, e.g. <typename <> T> */
46 non_type_template, /*!< Non type template parameter, e.g. <int N> */
47 argument, /*!< Template argument, e.g. <int> */
48 concept_constraint, /*!< Concept constraint, e.g. <std::integral T> */
49 empty /*!< Represent empty template specialization */
50};
51
53
54/**
55 * Enum representing type of reference or pointer type qualifier
56 */
57enum class rpqualifier {
58 kLValueReference, /*!< l-value reference (e.g. &) */
59 kRValueReference, /*!< r-value reference (e.g. &&) */
60 kPointer, /*!< pointer (e.g *) */
61 kNone /*!< No qualifier */
62};
63
64/**
65 * This struct manages a single level of template deduced context, e.g.
66 * & or const*
67 */
68struct context {
69 bool is_const{false};
70 bool is_volatile{false};
71 bool is_ref_const{false};
72 bool is_ref_volatile{false};
74
75 std::string to_string() const;
76
77 bool operator==(const context &rhs) const;
78 bool operator!=(const context &rhs) const;
79};
80
81/**
82 * @brief Represents template parameter, template arguments or concept
83 * constraints
84 *
85 * This class can represent both template parameter and template arguments,
86 * including variadic parameters and instantiations with
87 * nested templates
88 */
90public:
91 /**
92 * @brief Build template type parameter
93 *
94 * @param name Name of template parameter (e.g. T)
95 * @param default_value Default value of the parameter if any
96 * @param is_variadic Whether the template parameter is variadic
97 * @return template_parameter instance
98 */
100
101 /**
102 * @brief Build template type parameter
103 *
104 * @param name Name of template parameter (e.g. T)
105 * @param default_value Default value of the parameter if any
106 * @param is_variadic Whether the template parameter is variadic
107 * @return template_parameter instance
108 */
109 static template_parameter make_template_type(const std::string &name,
110 const std::optional<std::string> &default_value = {},
111 bool is_variadic = false);
112
113 /**
114 * @brief Build template template parameter type
115 *
116 * @param name Name of template template parameter
117 * @param default_value Default value of the parameter if any
118 * @param is_variadic Whether the template parameter is variadic
119 * @return template_parameter instance
120 */
122 const std::string &name,
123 const std::optional<std::string> &default_value = {},
124 bool is_variadic = false);
125
126 /**
127 * @brief Build non-type template parameter
128 * @param type Type of non-type parameter (e.g. int)
129 * @param name Name of parameter
130 * @param default_value Default value of the parameter if any
131 * @param is_variadic Whether the template parameter is variadic
132 * @return template_parameter instance
133 */
134 static template_parameter make_non_type_template(const std::string &type,
135 const std::optional<std::string> &name,
136 const std::optional<std::string> &default_value = {},
137 bool is_variadic = false);
138
139 /**
140 * @brief Build template argument
141 *
142 * @param type Type of template argument
143 * @param default_value Default value of the parameter if any
144 * @return template_parameter instance
145 */
146 static template_parameter make_argument(const std::string &type,
147 const std::optional<std::string> &default_value = {});
148
149 /**
150 * @brief Build template argument with unexposed type
151 *
152 * This method is used to build template argument from an unexposed string,
153 * i.e. when Clang just returns a string for the template argument type
154 * instead of actual type AST.
155 *
156 * @param type String representation of the type
157 * @param default_value Default value of the parameter if any
158 * @return template_parameter instance
159 */
160 static template_parameter make_unexposed_argument(const std::string &type,
161 const std::optional<std::string> &default_value = {});
162
163 /**
164 * Set the type of template argument
165 *
166 * @param type Name of the type
167 */
168 void set_type(const std::string &type);
169
170 /**
171 * Get the type of template parameter if any
172 *
173 * @return Optional name of type
174 */
175 std::optional<std::string> type() const;
176
177 /**
178 * Set unique id for the template parameter or argument
179 *
180 * @param id Id of parameter
181 */
182 void set_id(const eid_t &id) { id_ = id; }
183
184 /**
185 * Get id of the template parameter
186 *
187 * @return Id of the template parameter
188 */
189 const std::optional<eid_t> &id() const { return id_; }
190
191 /**
192 * Set the name of the template parameter
193 *
194 * @param name Name of template parameter
195 */
196 void set_name(const std::string &name);
197
198 /**
199 * Get the name of template parameter, if any
200 *
201 * @return Name of template parameter
202 */
203 std::optional<std::string> name() const;
204
205 /**
206 * Set default value for template parameter
207 *
208 * @param value Default value
209 */
210 void set_default_value(const std::string &value);
211
212 /**
213 * Get the template parameters default value if any
214 *
215 * @return Default value
216 */
217 const std::optional<std::string> &default_value() const;
218
219 /**
220 * Set template parameters variadic status.
221 *
222 * @param is_variadic True, if template parameter is variadic
223 */
224 void is_variadic(bool is_variadic) noexcept;
225
226 /**
227 * Check whether template parameter is variadic
228 *
229 * @return True, if template parameter is variadic
230 */
231 bool is_variadic() const noexcept;
232
233 /**
234 * @brief Calculate the match between this and other parameter
235 *
236 * This method calculates to what degree *this matches the
237 * `base_template_parameter` as it's less specific specialization.
238 *
239 * The higher the value, the more likely it is that *this is a
240 * specialization of `base_template_parameter`.
241 *
242 * @todo This is not scientific - there probably is more strict way to
243 * calculate this...
244 *
245 * @see calculate_template_params_specialization_match()
246 *
247 * @param base_template_parameter
248 * @return Specialization match value
249 */
251 const template_parameter &base_template_parameter) const;
252
253 /**
254 * Whether this is a template parameter.
255 *
256 * @return True, if *this is a template parameter
257 */
258 bool is_template_parameter() const;
259
260 /**
261 * Set, whether this is a template parameter.
262 *
263 * @param is_template_parameter Template parameter status
264 */
266
267 /**
268 * Whether this is a template template parameter.
269 *
270 * @return True, if *this is a template template parameter
271 */
273
274 /**
275 * Set, whether this is a template template parameter.
276 *
277 * @param is_template_parameter Template template parameter status
278 */
280
281 bool is_unexposed() const;
282 void set_unexposed(bool unexposed);
283
284 /**
285 * Set, whether this is a function template parameter.
286 *
287 * @param ft Function template parameter status
288 */
289 void is_function_template(bool ft);
290
291 /**
292 * Whether this is a function template parameter.
293 *
294 * @return True, if *this is a function template parameter
295 */
296 bool is_function_template() const;
297
298 /**
299 * Set, whether this is a member pointer template parameter.
300 *
301 * @param m Member pointer template parameter status
302 */
303 void is_member_pointer(bool m);
304
305 /**
306 * Whether this is a member pointer parameter.
307 *
308 * @return True if this is member pointer parameter.
309 */
310 bool is_member_pointer() const;
311
312 /**
313 * Set, whether this is a data template parameter.
314 *
315 * @param m Data pointer parameter status
316 */
317 void is_data_pointer(bool m);
318
319 /**
320 * Whether this is a data pointer parameter.
321 *
322 * @return True, if this is a data pointer parameter.
323 */
324 bool is_data_pointer() const;
325
326 /**
327 * Set, whether this is an array template parameter.
328 *
329 * @param m Array parameter status
330 */
331 void is_array(bool a);
332
333 /**
334 * Whether this is an array template parameter.
335 *
336 * @return True, if this is an array template parameter.
337 */
338 bool is_array() const;
339
340 /**
341 * Add a nested template parameter.
342 *
343 * @param ct Template parameter r-value.
344 */
346
347 /**
348 * Add a nested template parameter.
349 *
350 * @param ct Template parameter l-value.
351 */
353
354 /**
355 * Get the reference to all nested template parameters.
356 *
357 * @return
358 */
359 const std::vector<template_parameter> &template_params() const;
360
361 /**
362 * Erase all nested template parameters.
363 */
364 void clear_params() { template_params_.clear(); }
365
366 /**
367 * Does the template parameters deduced context contain any references
368 * or pointers?
369 *
370 * @return True if any of the deduced context is a reference or pointer.
371 */
372 bool is_association() const;
373
374 /**
375 * Is this template argument or parameter a specialization of some more
376 * generic template.
377 *
378 * @return True, if this is specialization of some more generic template
379 * parameter.
380 */
381 bool is_specialization() const;
382
383 /**
384 * @brief Whether this is the same type of specialization as other.
385 *
386 * This method is used for instance to check if 2 template parameters
387 * are function templates.
388 *
389 * @param other Another template parameter or argument
390 * @return True, if both template parameters are the same type of
391 * specialzations.
392 */
393 bool is_same_specialization(const template_parameter &other) const;
394
395 /**
396 * @brief Find all relationships in this and its nested templates
397 *
398 * @param decl Source declaration where this relationship originates from
399 * @param nested_relationships Output to store found relationships
400 * @param hint Provide hint for the found relationships
401 * @param should_include Functor to determine whether nested template
402 * parameter or argument should be considered
403 * @return
404 */
405 bool find_nested_relationships(const clang::Decl *decl,
406 std::vector<std::tuple<eid_t, common::model::relationship_t,
407 const clang::Decl *>> &nested_relationships,
409 const std::function<bool(const std::string &full_name)> &should_include)
410 const;
411
412 /**
413 * Set the concept constraint for this template parameter
414 *
415 * @param constraint
416 */
417 void set_concept_constraint(std::string constraint);
418
419 /**
420 * Get the name of the concept constraint for this parameter, if any
421 *
422 * @return Optional concept constraint name
423 */
424 const std::optional<std::string> &concept_constraint() const;
425
426 /**
427 * Get the kind of the template parameter or argument
428 * @return Template parameter kind
429 */
431
432 /**
433 * Set the kind of the template parameter or argument.
434 *
435 * @param kind Kind of the template parameter
436 */
438
439 /**
440 * @brief Append a deduced context to the template parameter.
441 *
442 * @param q Deduced context
443 */
444 void push_context(const context &q);
445
446 /**
447 * Get the entire deduce context of the template parameter
448 *
449 * @return Deduced context of this template parameter
450 */
451 const std::deque<context> &deduced_context() const;
452
453 /**
454 * Set the deduced context for the template parameter
455 *
456 * @param c Deduced context.
457 */
458 void deduced_context(std::deque<context> c);
459
460 /**
461 * Set, whether the parameter is an ellipsis (...)
462 *
463 * @param e True, if parameter is an ellipsis
464 */
465 void is_ellipsis(bool e);
466
467 /**
468 * Check whether the parameter is an ellipsis
469 *
470 * @return True if the parameter is an ellipsis
471 */
472 bool is_ellipsis() const;
473
474 /**
475 * @brief Render the template_parameter into string
476 *
477 * This method renders the template parameter along with any of its
478 * nested template parameters
479 * @param using_namespace
480 * @param relative
481 * @param skip_qualifiers
482 * @return
483 */
484 std::string to_string(
485 const clanguml::common::model::namespace_ &using_namespace,
486 bool relative, bool skip_qualifiers = false) const;
487
488private:
489 /**
490 * This class should be only constructed using builder methods.
491 */
493
494 std::string deduced_context_str() const;
495
497
498 /*! Represents the type of non-type template parameters e.g. 'int' or type
499 * of template arguments
500 */
501 std::optional<std::string> type_;
502
503 /*! The name of the parameter (e.g. 'T' or 'N') */
504 std::optional<std::string> name_;
505
506 /*! Default value of the template parameter */
507 std::optional<std::string> default_value_;
508
509 /*! Whether the template parameter is a regular template parameter. When
510 * false, it is a non-type template parameter
511 */
513
514 /*! Whether the template parameter is a template template parameter.
515 * Can only be true when is_template_parameter_ is true
516 */
518
519 /*! Whether template argument is ellipsis (...) */
520 bool is_ellipsis_{false};
521
522 /*! Whether the template parameter is variadic */
523 bool is_variadic_{false};
524
525 /*! Whether the template is a function template (e.g. R(T)) */
527
528 /*! Whether the template */
529 bool is_data_pointer_{false};
530
531 /*! Whether the template is a member pointer (e.g. R(C::*)(int)) */
533
534 /*! Is template argument an array */
535 bool is_array_{false};
536
537 /*! Stores the template parameter/argument deduction context e.g. const& */
538 std::deque<context> context_;
539
540 /*! Stores optional fully qualified name of constraint for this template
541 * parameter
542 */
543 std::optional<std::string> concept_constraint_;
544
545 /*! Nested template parameters. If this is a function template, the first
546 * element is the return type
547 */
548 std::vector<template_parameter> template_params_;
549
550 std::optional<eid_t> id_;
551
552 bool is_unexposed_{false};
553};
554
555/**
556 * @brief Calculate the match between 2 template parameter lists
557 *
558 * The higher the value, the more likely it is that *this is a
559 * specialization of `base_template_parameter`.
560 *
561 * @todo This is not scientific - there probably is more strict way to
562 * calculate this...
563 *
564 * @param base_template_parameter
565 * @return Specialization match value
566 */
568 const std::vector<template_parameter> &specialization,
569 const std::vector<template_parameter> &base_template);
570
571} // namespace clanguml::common::model