cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / plugins / ctf / common / src / metadata / tsdl / visitor-semantic-validator.cpp
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Common Trace Format Metadata Semantic Validator.
7 */
8
9 #include <errno.h>
10 #include <unistd.h>
11
12 #include "logging.hpp"
13
14 #include "common/list.h"
15
16 #include "ast.hpp"
17
18 #define _bt_list_first_entry(ptr, type, member) bt_list_entry((ptr)->next, type, member)
19
20 static int _ctf_visitor_semantic_check(int depth, struct ctf_node *node,
21 const bt2c::Logger& logger);
22
23 static int ctf_visitor_unary_expression(int, struct ctf_node *node, const bt2c::Logger& logger)
24 {
25 struct ctf_node *iter;
26 int is_ctf_exp = 0, is_ctf_exp_left = 0;
27
28 switch (node->parent->type) {
29 case NODE_CTF_EXPRESSION:
30 is_ctf_exp = 1;
31 bt_list_for_each_entry (iter, &node->parent->u.ctf_expression.left, siblings) {
32 if (iter == node) {
33 is_ctf_exp_left = 1;
34 /*
35 * We are a left child of a ctf expression.
36 * We are only allowed to be a string.
37 */
38 if (node->u.unary_expression.type != UNARY_STRING) {
39 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
40 logger, node->lineno,
41 "Left child of a CTF expression is only allowed to be a string.");
42 goto errperm;
43 }
44 break;
45 }
46 }
47 /* Right child of a ctf expression can be any type of unary exp. */
48 break; /* OK */
49 case NODE_TYPE_DECLARATOR:
50 /*
51 * We are the length of a type declarator.
52 */
53 switch (node->u.unary_expression.type) {
54 case UNARY_UNSIGNED_CONSTANT:
55 case UNARY_STRING:
56 break;
57 default:
58 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
59 logger, node->lineno,
60 "Children of field class declarator and `enum` can only be unsigned numeric constants or references to fields (e.g., `a.b.c`).");
61 goto errperm;
62 }
63 break; /* OK */
64
65 case NODE_STRUCT:
66 /*
67 * We are the size of a struct align attribute.
68 */
69 switch (node->u.unary_expression.type) {
70 case UNARY_UNSIGNED_CONSTANT:
71 break;
72 default:
73 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
74 logger, node->lineno,
75 "Structure alignment attribute can only be an unsigned numeric constant.");
76 goto errperm;
77 }
78 break;
79
80 case NODE_ENUMERATOR:
81 /* The enumerator's parent has validated its validity already. */
82 break; /* OK */
83
84 case NODE_UNARY_EXPRESSION:
85 /*
86 * We disallow nested unary expressions and "sbrac" unary
87 * expressions.
88 */
89 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
90 "Nested unary expressions not allowed (`()` and `[]`).");
91 goto errperm;
92
93 case NODE_ROOT:
94 case NODE_EVENT:
95 case NODE_STREAM:
96 case NODE_ENV:
97 case NODE_TRACE:
98 case NODE_CLOCK:
99 case NODE_CALLSITE:
100 case NODE_TYPEDEF:
101 case NODE_TYPEALIAS_TARGET:
102 case NODE_TYPEALIAS_ALIAS:
103 case NODE_TYPEALIAS:
104 case NODE_TYPE_SPECIFIER:
105 case NODE_POINTER:
106 case NODE_FLOATING_POINT:
107 case NODE_INTEGER:
108 case NODE_STRING:
109 case NODE_ENUM:
110 case NODE_STRUCT_OR_VARIANT_DECLARATION:
111 case NODE_VARIANT:
112 default:
113 goto errinval;
114 }
115
116 switch (node->u.unary_expression.link) {
117 case UNARY_LINK_UNKNOWN:
118 /* We don't allow empty link except on the first node of the list */
119 if (is_ctf_exp &&
120 _bt_list_first_entry(is_ctf_exp_left ? &node->parent->u.ctf_expression.left :
121 &node->parent->u.ctf_expression.right,
122 struct ctf_node, siblings) != node) {
123 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
124 logger, node->lineno,
125 "Empty link is not allowed except on first node of unary expression (need to separate nodes with `.` or `->`).");
126 goto errperm;
127 }
128 break; /* OK */
129 case UNARY_DOTLINK:
130 case UNARY_ARROWLINK:
131 /* We only allow -> and . links between children of ctf_expression. */
132 if (node->parent->type != NODE_CTF_EXPRESSION) {
133 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
134 logger, node->lineno,
135 "Links `.` and `->` are only allowed as children of CTF expression.");
136 goto errperm;
137 }
138 /*
139 * Only strings can be separated linked by . or ->.
140 * This includes "", '' and non-quoted identifiers.
141 */
142 if (node->u.unary_expression.type != UNARY_STRING) {
143 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
144 logger, node->lineno,
145 "Links `.` and `->` are only allowed to separate strings and identifiers.");
146 goto errperm;
147 }
148 /* We don't allow link on the first node of the list */
149 if (is_ctf_exp &&
150 _bt_list_first_entry(is_ctf_exp_left ? &node->parent->u.ctf_expression.left :
151 &node->parent->u.ctf_expression.right,
152 struct ctf_node, siblings) == node) {
153 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
154 logger, node->lineno,
155 "Links `.` and `->` are not allowed before first node of the unary expression list.");
156 goto errperm;
157 }
158 break;
159 case UNARY_DOTDOTDOT:
160 /* We only allow ... link between children of enumerator. */
161 if (node->parent->type != NODE_ENUMERATOR) {
162 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
163 "Link `...` is only allowed within enumerator.");
164 goto errperm;
165 }
166 /* We don't allow link on the first node of the list */
167 if (_bt_list_first_entry(&node->parent->u.enumerator.values, struct ctf_node, siblings) ==
168 node) {
169 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
170 logger, node->lineno,
171 "Link `...` is not allowed on the first node of the unary expression list.");
172 goto errperm;
173 }
174 break;
175 default:
176 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
177 "Unknown expression link type: type={}",
178 (int) node->u.unary_expression.link);
179 return -EINVAL;
180 }
181 return 0;
182
183 errinval:
184 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
185 logger, node->lineno, "Incoherent parent node's type: node-type={}, parent-node-type={}",
186 node_type(node), node_type(node->parent));
187 return -EINVAL; /* Incoherent structure */
188
189 errperm:
190 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
191 "Semantic error: node-type={}, parent-node-type={}",
192 node_type(node), node_type(node->parent));
193 return -EPERM; /* Structure not allowed */
194 }
195
196 static int ctf_visitor_field_class_specifier_list(int, struct ctf_node *node,
197 const bt2c::Logger& logger)
198 {
199 switch (node->parent->type) {
200 case NODE_CTF_EXPRESSION:
201 case NODE_TYPE_DECLARATOR:
202 case NODE_TYPEDEF:
203 case NODE_TYPEALIAS_TARGET:
204 case NODE_TYPEALIAS_ALIAS:
205 case NODE_ENUM:
206 case NODE_STRUCT_OR_VARIANT_DECLARATION:
207 case NODE_ROOT:
208 break; /* OK */
209
210 case NODE_EVENT:
211 case NODE_STREAM:
212 case NODE_ENV:
213 case NODE_TRACE:
214 case NODE_CLOCK:
215 case NODE_CALLSITE:
216 case NODE_UNARY_EXPRESSION:
217 case NODE_TYPEALIAS:
218 case NODE_TYPE_SPECIFIER:
219 case NODE_TYPE_SPECIFIER_LIST:
220 case NODE_POINTER:
221 case NODE_FLOATING_POINT:
222 case NODE_INTEGER:
223 case NODE_STRING:
224 case NODE_ENUMERATOR:
225 case NODE_VARIANT:
226 case NODE_STRUCT:
227 default:
228 goto errinval;
229 }
230 return 0;
231 errinval:
232 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
233 logger, node->lineno, "Incoherent parent node's type: node-type={}, parent-node-type={}",
234 node_type(node), node_type(node->parent));
235 return -EINVAL; /* Incoherent structure */
236 }
237
238 static int ctf_visitor_field_class_specifier(int, struct ctf_node *node, const bt2c::Logger& logger)
239 {
240 switch (node->parent->type) {
241 case NODE_TYPE_SPECIFIER_LIST:
242 break; /* OK */
243
244 case NODE_CTF_EXPRESSION:
245 case NODE_TYPE_DECLARATOR:
246 case NODE_TYPEDEF:
247 case NODE_TYPEALIAS_TARGET:
248 case NODE_TYPEALIAS_ALIAS:
249 case NODE_ENUM:
250 case NODE_STRUCT_OR_VARIANT_DECLARATION:
251 case NODE_ROOT:
252 case NODE_EVENT:
253 case NODE_STREAM:
254 case NODE_ENV:
255 case NODE_TRACE:
256 case NODE_CLOCK:
257 case NODE_CALLSITE:
258 case NODE_UNARY_EXPRESSION:
259 case NODE_TYPEALIAS:
260 case NODE_TYPE_SPECIFIER:
261 case NODE_POINTER:
262 case NODE_FLOATING_POINT:
263 case NODE_INTEGER:
264 case NODE_STRING:
265 case NODE_ENUMERATOR:
266 case NODE_VARIANT:
267 case NODE_STRUCT:
268 default:
269 goto errinval;
270 }
271 return 0;
272 errinval:
273 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
274 logger, node->lineno, "Incoherent parent node's type: node-type={}, parent-node-type={}",
275 node_type(node), node_type(node->parent));
276 return -EINVAL; /* Incoherent structure */
277 }
278
279 static int ctf_visitor_field_class_declarator(int depth, struct ctf_node *node,
280 const bt2c::Logger& logger)
281 {
282 int ret = 0;
283 struct ctf_node *iter;
284
285 depth++;
286
287 switch (node->parent->type) {
288 case NODE_TYPE_DECLARATOR:
289 /*
290 * A nested field class declarator is not allowed to
291 * contain pointers.
292 */
293 if (!bt_list_empty(&node->u.field_class_declarator.pointers))
294 goto errperm;
295 break; /* OK */
296 case NODE_TYPEALIAS_TARGET:
297 break; /* OK */
298 case NODE_TYPEALIAS_ALIAS:
299 /*
300 * Only accept alias name containing:
301 * - identifier
302 * - identifier * (any number of pointers)
303 * NOT accepting alias names containing [] (would otherwise
304 * cause semantic clash for later declarations of
305 * arrays/sequences of elements, where elements could be
306 * arrays/sequences themselves (if allowed in field class alias).
307 * NOT accepting alias with identifier. The declarator should
308 * be either empty or contain pointer(s).
309 */
310 if (node->u.field_class_declarator.type == TYPEDEC_NESTED)
311 goto errperm;
312 bt_list_for_each_entry (iter,
313 &node->parent->u.field_class_alias_name.field_class_specifier_list
314 ->u.field_class_specifier_list.head,
315 siblings) {
316 switch (iter->u.field_class_specifier.type) {
317 case TYPESPEC_FLOATING_POINT:
318 case TYPESPEC_INTEGER:
319 case TYPESPEC_STRING:
320 case TYPESPEC_STRUCT:
321 case TYPESPEC_VARIANT:
322 case TYPESPEC_ENUM:
323 if (bt_list_empty(&node->u.field_class_declarator.pointers))
324 goto errperm;
325 break;
326 default:
327 break;
328 }
329 }
330 if (node->u.field_class_declarator.type == TYPEDEC_ID &&
331 node->u.field_class_declarator.u.id)
332 goto errperm;
333 break; /* OK */
334 case NODE_TYPEDEF:
335 case NODE_STRUCT_OR_VARIANT_DECLARATION:
336 break; /* OK */
337
338 case NODE_ROOT:
339 case NODE_EVENT:
340 case NODE_STREAM:
341 case NODE_ENV:
342 case NODE_TRACE:
343 case NODE_CLOCK:
344 case NODE_CALLSITE:
345 case NODE_CTF_EXPRESSION:
346 case NODE_UNARY_EXPRESSION:
347 case NODE_TYPEALIAS:
348 case NODE_TYPE_SPECIFIER:
349 case NODE_POINTER:
350 case NODE_FLOATING_POINT:
351 case NODE_INTEGER:
352 case NODE_STRING:
353 case NODE_ENUMERATOR:
354 case NODE_ENUM:
355 case NODE_VARIANT:
356 case NODE_STRUCT:
357 default:
358 goto errinval;
359 }
360
361 bt_list_for_each_entry (iter, &node->u.field_class_declarator.pointers, siblings) {
362 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
363 if (ret)
364 return ret;
365 }
366
367 switch (node->u.field_class_declarator.type) {
368 case TYPEDEC_ID:
369 break;
370 case TYPEDEC_NESTED:
371 {
372 if (node->u.field_class_declarator.u.nested.field_class_declarator) {
373 ret = _ctf_visitor_semantic_check(
374 depth + 1, node->u.field_class_declarator.u.nested.field_class_declarator, logger);
375 if (ret)
376 return ret;
377 }
378 if (!node->u.field_class_declarator.u.nested.abstract_array) {
379 bt_list_for_each_entry (iter, &node->u.field_class_declarator.u.nested.length,
380 siblings) {
381 if (iter->type != NODE_UNARY_EXPRESSION) {
382 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
383 logger, node->lineno, "Expecting unary expression as length: node-type={}",
384 node_type(iter));
385 return -EINVAL;
386 }
387 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
388 if (ret)
389 return ret;
390 }
391 } else {
392 if (node->parent->type == NODE_TYPEALIAS_TARGET) {
393 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
394 logger, node->lineno,
395 "Abstract array declarator not permitted as target of field class alias.");
396 return -EINVAL;
397 }
398 }
399 if (node->u.field_class_declarator.bitfield_len) {
400 ret = _ctf_visitor_semantic_check(depth + 1,
401 node->u.field_class_declarator.bitfield_len, logger);
402 if (ret)
403 return ret;
404 }
405 break;
406 }
407 case TYPEDEC_UNKNOWN:
408 default:
409 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
410 "Unknown field class declarator: type={}",
411 (int) node->u.field_class_declarator.type);
412 return -EINVAL;
413 }
414 depth--;
415 return 0;
416
417 errinval:
418 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
419 logger, node->lineno, "Incoherent parent node's type: node-type={}, parent-node-type={}",
420 node_type(node), node_type(node->parent));
421 return -EINVAL; /* Incoherent structure */
422
423 errperm:
424 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
425 "Semantic error: node-type={}, parent-node-type={}",
426 node_type(node), node_type(node->parent));
427 return -EPERM; /* Structure not allowed */
428 }
429
430 static int _ctf_visitor_semantic_check(int depth, struct ctf_node *node, const bt2c::Logger& logger)
431 {
432 int ret = 0;
433 struct ctf_node *iter;
434
435 if (node->visited)
436 return 0;
437
438 switch (node->type) {
439 case NODE_ROOT:
440 bt_list_for_each_entry (iter, &node->u.root.declaration_list, siblings) {
441 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
442 if (ret)
443 return ret;
444 }
445 bt_list_for_each_entry (iter, &node->u.root.trace, siblings) {
446 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
447 if (ret)
448 return ret;
449 }
450 bt_list_for_each_entry (iter, &node->u.root.stream, siblings) {
451 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
452 if (ret)
453 return ret;
454 }
455 bt_list_for_each_entry (iter, &node->u.root.event, siblings) {
456 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
457 if (ret)
458 return ret;
459 }
460 break;
461
462 case NODE_EVENT:
463 switch (node->parent->type) {
464 case NODE_ROOT:
465 break; /* OK */
466 default:
467 goto errinval;
468 }
469
470 bt_list_for_each_entry (iter, &node->u.event.declaration_list, siblings) {
471 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
472 if (ret)
473 return ret;
474 }
475 break;
476 case NODE_STREAM:
477 switch (node->parent->type) {
478 case NODE_ROOT:
479 break; /* OK */
480 default:
481 goto errinval;
482 }
483
484 bt_list_for_each_entry (iter, &node->u.stream.declaration_list, siblings) {
485 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
486 if (ret)
487 return ret;
488 }
489 break;
490 case NODE_ENV:
491 switch (node->parent->type) {
492 case NODE_ROOT:
493 break; /* OK */
494 default:
495 goto errinval;
496 }
497
498 bt_list_for_each_entry (iter, &node->u.env.declaration_list, siblings) {
499 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
500 if (ret)
501 return ret;
502 }
503 break;
504 case NODE_TRACE:
505 switch (node->parent->type) {
506 case NODE_ROOT:
507 break; /* OK */
508 default:
509 goto errinval;
510 }
511
512 bt_list_for_each_entry (iter, &node->u.trace.declaration_list, siblings) {
513 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
514 if (ret)
515 return ret;
516 }
517 break;
518 case NODE_CLOCK:
519 switch (node->parent->type) {
520 case NODE_ROOT:
521 break; /* OK */
522 default:
523 goto errinval;
524 }
525
526 bt_list_for_each_entry (iter, &node->u.clock.declaration_list, siblings) {
527 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
528 if (ret)
529 return ret;
530 }
531 break;
532 case NODE_CALLSITE:
533 switch (node->parent->type) {
534 case NODE_ROOT:
535 break; /* OK */
536 default:
537 goto errinval;
538 }
539
540 bt_list_for_each_entry (iter, &node->u.callsite.declaration_list, siblings) {
541 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
542 if (ret)
543 return ret;
544 }
545 break;
546
547 case NODE_CTF_EXPRESSION:
548 switch (node->parent->type) {
549 case NODE_ROOT:
550 case NODE_EVENT:
551 case NODE_STREAM:
552 case NODE_ENV:
553 case NODE_TRACE:
554 case NODE_CLOCK:
555 case NODE_CALLSITE:
556 case NODE_FLOATING_POINT:
557 case NODE_INTEGER:
558 case NODE_STRING:
559 break; /* OK */
560
561 case NODE_CTF_EXPRESSION:
562 case NODE_UNARY_EXPRESSION:
563 case NODE_TYPEDEF:
564 case NODE_TYPEALIAS_TARGET:
565 case NODE_TYPEALIAS_ALIAS:
566 case NODE_STRUCT_OR_VARIANT_DECLARATION:
567 case NODE_TYPEALIAS:
568 case NODE_TYPE_SPECIFIER:
569 case NODE_TYPE_SPECIFIER_LIST:
570 case NODE_POINTER:
571 case NODE_TYPE_DECLARATOR:
572 case NODE_ENUMERATOR:
573 case NODE_ENUM:
574 case NODE_VARIANT:
575 case NODE_STRUCT:
576 default:
577 goto errinval;
578 }
579
580 depth++;
581 bt_list_for_each_entry (iter, &node->u.ctf_expression.left, siblings) {
582 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
583 if (ret)
584 return ret;
585 }
586 bt_list_for_each_entry (iter, &node->u.ctf_expression.right, siblings) {
587 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
588 if (ret)
589 return ret;
590 }
591 depth--;
592 break;
593 case NODE_UNARY_EXPRESSION:
594 return ctf_visitor_unary_expression(depth, node, logger);
595
596 case NODE_TYPEDEF:
597 switch (node->parent->type) {
598 case NODE_ROOT:
599 case NODE_EVENT:
600 case NODE_STREAM:
601 case NODE_TRACE:
602 case NODE_VARIANT:
603 case NODE_STRUCT:
604 break; /* OK */
605
606 case NODE_CTF_EXPRESSION:
607 case NODE_UNARY_EXPRESSION:
608 case NODE_TYPEDEF:
609 case NODE_TYPEALIAS_TARGET:
610 case NODE_TYPEALIAS_ALIAS:
611 case NODE_TYPEALIAS:
612 case NODE_STRUCT_OR_VARIANT_DECLARATION:
613 case NODE_TYPE_SPECIFIER:
614 case NODE_TYPE_SPECIFIER_LIST:
615 case NODE_POINTER:
616 case NODE_TYPE_DECLARATOR:
617 case NODE_FLOATING_POINT:
618 case NODE_INTEGER:
619 case NODE_STRING:
620 case NODE_ENUMERATOR:
621 case NODE_ENUM:
622 case NODE_CLOCK:
623 case NODE_CALLSITE:
624 case NODE_ENV:
625 default:
626 goto errinval;
627 }
628
629 depth++;
630 ret = _ctf_visitor_semantic_check(
631 depth + 1, node->u.field_class_def.field_class_specifier_list, logger);
632 if (ret)
633 return ret;
634 bt_list_for_each_entry (iter, &node->u.field_class_def.field_class_declarators, siblings) {
635 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
636 if (ret)
637 return ret;
638 }
639 depth--;
640 break;
641 case NODE_TYPEALIAS_TARGET:
642 {
643 int nr_declarators;
644
645 switch (node->parent->type) {
646 case NODE_TYPEALIAS:
647 break; /* OK */
648 default:
649 goto errinval;
650 }
651
652 depth++;
653 ret = _ctf_visitor_semantic_check(
654 depth + 1, node->u.field_class_alias_target.field_class_specifier_list, logger);
655 if (ret)
656 return ret;
657 nr_declarators = 0;
658 bt_list_for_each_entry (iter, &node->u.field_class_alias_target.field_class_declarators,
659 siblings) {
660 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
661 if (ret)
662 return ret;
663 nr_declarators++;
664 }
665 if (nr_declarators > 1) {
666 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
667 logger, node->lineno,
668 "Too many declarators in field class alias's name (maximum is 1): count={}",
669 nr_declarators);
670 return -EINVAL;
671 }
672 depth--;
673 break;
674 }
675 case NODE_TYPEALIAS_ALIAS:
676 {
677 int nr_declarators;
678
679 switch (node->parent->type) {
680 case NODE_TYPEALIAS:
681 break; /* OK */
682 default:
683 goto errinval;
684 }
685
686 depth++;
687 ret = _ctf_visitor_semantic_check(
688 depth + 1, node->u.field_class_alias_name.field_class_specifier_list, logger);
689 if (ret)
690 return ret;
691 nr_declarators = 0;
692 bt_list_for_each_entry (iter, &node->u.field_class_alias_name.field_class_declarators,
693 siblings) {
694 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
695 if (ret)
696 return ret;
697 nr_declarators++;
698 }
699 if (nr_declarators > 1) {
700 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
701 logger, node->lineno,
702 "Too many declarators in field class alias's name (maximum is 1): count={}",
703 nr_declarators);
704 return -EINVAL;
705 }
706 depth--;
707 break;
708 }
709 case NODE_TYPEALIAS:
710 switch (node->parent->type) {
711 case NODE_ROOT:
712 case NODE_EVENT:
713 case NODE_STREAM:
714 case NODE_TRACE:
715 case NODE_VARIANT:
716 case NODE_STRUCT:
717 break; /* OK */
718
719 case NODE_CTF_EXPRESSION:
720 case NODE_UNARY_EXPRESSION:
721 case NODE_TYPEDEF:
722 case NODE_TYPEALIAS_TARGET:
723 case NODE_TYPEALIAS_ALIAS:
724 case NODE_TYPEALIAS:
725 case NODE_STRUCT_OR_VARIANT_DECLARATION:
726 case NODE_TYPE_SPECIFIER:
727 case NODE_TYPE_SPECIFIER_LIST:
728 case NODE_POINTER:
729 case NODE_TYPE_DECLARATOR:
730 case NODE_FLOATING_POINT:
731 case NODE_INTEGER:
732 case NODE_STRING:
733 case NODE_ENUMERATOR:
734 case NODE_ENUM:
735 case NODE_CLOCK:
736 case NODE_CALLSITE:
737 case NODE_ENV:
738 default:
739 goto errinval;
740 }
741
742 ret = _ctf_visitor_semantic_check(depth + 1, node->u.field_class_alias.target, logger);
743 if (ret)
744 return ret;
745 ret = _ctf_visitor_semantic_check(depth + 1, node->u.field_class_alias.alias, logger);
746 if (ret)
747 return ret;
748 break;
749
750 case NODE_TYPE_SPECIFIER_LIST:
751 ret = ctf_visitor_field_class_specifier_list(depth, node, logger);
752 if (ret)
753 return ret;
754 break;
755 case NODE_TYPE_SPECIFIER:
756 ret = ctf_visitor_field_class_specifier(depth, node, logger);
757 if (ret)
758 return ret;
759 break;
760 case NODE_POINTER:
761 switch (node->parent->type) {
762 case NODE_TYPE_DECLARATOR:
763 break; /* OK */
764 default:
765 goto errinval;
766 }
767 break;
768 case NODE_TYPE_DECLARATOR:
769 ret = ctf_visitor_field_class_declarator(depth, node, logger);
770 if (ret)
771 return ret;
772 break;
773
774 case NODE_FLOATING_POINT:
775 switch (node->parent->type) {
776 case NODE_TYPE_SPECIFIER:
777 break; /* OK */
778 default:
779 goto errinval;
780
781 case NODE_UNARY_EXPRESSION:
782 goto errperm;
783 }
784 bt_list_for_each_entry (iter, &node->u.floating_point.expressions, siblings) {
785 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
786 if (ret)
787 return ret;
788 }
789 break;
790 case NODE_INTEGER:
791 switch (node->parent->type) {
792 case NODE_TYPE_SPECIFIER:
793 break; /* OK */
794 default:
795 goto errinval;
796 }
797
798 bt_list_for_each_entry (iter, &node->u.integer.expressions, siblings) {
799 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
800 if (ret)
801 return ret;
802 }
803 break;
804 case NODE_STRING:
805 switch (node->parent->type) {
806 case NODE_TYPE_SPECIFIER:
807 break; /* OK */
808 default:
809 goto errinval;
810
811 case NODE_UNARY_EXPRESSION:
812 goto errperm;
813 }
814
815 bt_list_for_each_entry (iter, &node->u.string.expressions, siblings) {
816 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
817 if (ret)
818 return ret;
819 }
820 break;
821 case NODE_ENUMERATOR:
822 switch (node->parent->type) {
823 case NODE_ENUM:
824 break;
825 default:
826 goto errinval;
827 }
828 /*
829 * Enumerators are only allows to contain:
830 * numeric unary expression
831 * or num. unary exp. ... num. unary exp
832 */
833 {
834 int count = 0;
835
836 bt_list_for_each_entry (iter, &node->u.enumerator.values, siblings) {
837 switch (count++) {
838 case 0:
839 if (iter->type != NODE_UNARY_EXPRESSION ||
840 (iter->u.unary_expression.type != UNARY_SIGNED_CONSTANT &&
841 iter->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) ||
842 iter->u.unary_expression.link != UNARY_LINK_UNKNOWN) {
843 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
844 logger, iter->lineno,
845 "First unary expression of enumerator is unexpected.");
846 goto errperm;
847 }
848 break;
849 case 1:
850 if (iter->type != NODE_UNARY_EXPRESSION ||
851 (iter->u.unary_expression.type != UNARY_SIGNED_CONSTANT &&
852 iter->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) ||
853 iter->u.unary_expression.link != UNARY_DOTDOTDOT) {
854 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
855 logger, iter->lineno,
856 "Second unary expression of enumerator is unexpected.");
857 goto errperm;
858 }
859 break;
860 default:
861 goto errperm;
862 }
863 }
864 }
865
866 bt_list_for_each_entry (iter, &node->u.enumerator.values, siblings) {
867 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
868 if (ret)
869 return ret;
870 }
871 break;
872 case NODE_ENUM:
873 switch (node->parent->type) {
874 case NODE_TYPE_SPECIFIER:
875 break; /* OK */
876 default:
877 goto errinval;
878
879 case NODE_UNARY_EXPRESSION:
880 goto errperm;
881 }
882
883 depth++;
884 ret = _ctf_visitor_semantic_check(depth + 1, node->u._enum.container_field_class, logger);
885 if (ret)
886 return ret;
887
888 bt_list_for_each_entry (iter, &node->u._enum.enumerator_list, siblings) {
889 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
890 if (ret)
891 return ret;
892 }
893 depth--;
894 break;
895 case NODE_STRUCT_OR_VARIANT_DECLARATION:
896 switch (node->parent->type) {
897 case NODE_STRUCT:
898 case NODE_VARIANT:
899 break;
900 default:
901 goto errinval;
902 }
903 ret = _ctf_visitor_semantic_check(
904 depth + 1, node->u.struct_or_variant_declaration.field_class_specifier_list, logger);
905 if (ret)
906 return ret;
907 bt_list_for_each_entry (
908 iter, &node->u.struct_or_variant_declaration.field_class_declarators, siblings) {
909 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
910 if (ret)
911 return ret;
912 }
913 break;
914 case NODE_VARIANT:
915 switch (node->parent->type) {
916 case NODE_TYPE_SPECIFIER:
917 break; /* OK */
918 default:
919 goto errinval;
920
921 case NODE_UNARY_EXPRESSION:
922 goto errperm;
923 }
924 bt_list_for_each_entry (iter, &node->u.variant.declaration_list, siblings) {
925 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
926 if (ret)
927 return ret;
928 }
929 break;
930
931 case NODE_STRUCT:
932 switch (node->parent->type) {
933 case NODE_TYPE_SPECIFIER:
934 break; /* OK */
935 default:
936 goto errinval;
937
938 case NODE_UNARY_EXPRESSION:
939 goto errperm;
940 }
941 bt_list_for_each_entry (iter, &node->u._struct.declaration_list, siblings) {
942 ret = _ctf_visitor_semantic_check(depth + 1, iter, logger);
943 if (ret)
944 return ret;
945 }
946 break;
947
948 case NODE_UNKNOWN:
949 default:
950 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno, "Unknown node type: type={}",
951 (int) node->type);
952 return -EINVAL;
953 }
954 return ret;
955
956 errinval:
957 _BT_CPPLOGE_APPEND_CAUSE_LINENO(
958 logger, node->lineno, "Incoherent parent node's type: node-type={}, parent-node-type={}",
959 node_type(node), node_type(node->parent));
960 return -EINVAL; /* Incoherent structure */
961
962 errperm:
963 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
964 "Semantic error: node-type={}, parent-node-type={}",
965 node_type(node), node_type(node->parent));
966 return -EPERM; /* Structure not allowed */
967 }
968
969 int ctf_visitor_semantic_check(int depth, struct ctf_node *node, const bt2c::Logger& parentLogger)
970 {
971 int ret = 0;
972 bt2c::Logger logger {parentLogger, "PLUGIN/CTF/META/SEMANTIC-VALIDATOR-VISITOR"};
973
974 /*
975 * First make sure we create the parent links for all children. Let's
976 * take the safe route and recreate them at each validation, just in
977 * case the structure has changed.
978 */
979 ret = ctf_visitor_parent_links(depth, node, logger);
980 if (ret) {
981 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
982 "Cannot create parent links in metadata's AST: "
983 "ret={}",
984 ret);
985 goto end;
986 }
987
988 ret = _ctf_visitor_semantic_check(depth, node, logger);
989 if (ret) {
990 _BT_CPPLOGE_APPEND_CAUSE_LINENO(logger, node->lineno,
991 "Cannot check metadata's AST semantics: "
992 "ret={}",
993 ret);
994 goto end;
995 }
996
997 end:
998 return ret;
999 }
This page took 0.082661 seconds and 4 git commands to generate.