2 * ctf-visitor-semantic-validator.c
4 * Common Trace Format Metadata Semantic Validator.
6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define BT_LOG_TAG "PLUGIN-CTF-METADATA-SEMANTIC-VALIDATOR-VISITOR"
34 #include <babeltrace/assert-internal.h>
38 #include <babeltrace/list-internal.h>
43 #define _bt_list_first_entry(ptr, type, member) \
44 bt_list_entry((ptr)->next, type, member)
47 int _ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
);
50 int ctf_visitor_unary_expression(int depth
, struct ctf_node
*node
)
52 struct ctf_node
*iter
;
53 int is_ctf_exp
= 0, is_ctf_exp_left
= 0;
55 switch (node
->parent
->type
) {
56 case NODE_CTF_EXPRESSION
:
58 bt_list_for_each_entry(iter
, &node
->parent
->u
.ctf_expression
.left
,
63 * We are a left child of a ctf expression.
64 * We are only allowed to be a string.
66 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
67 _BT_LOGE_LINENO(node
->lineno
,
68 "Left child of a CTF expression is only allowed to be a string.");
74 /* Right child of a ctf expression can be any type of unary exp. */
76 case NODE_TYPE_DECLARATOR
:
78 * We are the length of a type declarator.
80 switch (node
->u
.unary_expression
.type
) {
81 case UNARY_UNSIGNED_CONSTANT
:
85 _BT_LOGE_LINENO(node
->lineno
,
86 "Children of field class declarator and `enum` can only be unsigned numeric constants or references to fields (e.g., `a.b.c`).");
93 * We are the size of a struct align attribute.
95 switch (node
->u
.unary_expression
.type
) {
96 case UNARY_UNSIGNED_CONSTANT
:
99 _BT_LOGE_LINENO(node
->lineno
,
100 "Structure alignment attribute can only be an unsigned numeric constant.");
105 case NODE_ENUMERATOR
:
106 /* The enumerator's parent has validated its validity already. */
109 case NODE_UNARY_EXPRESSION
:
111 * We disallow nested unary expressions and "sbrac" unary
114 _BT_LOGE_LINENO(node
->lineno
,
115 "Nested unary expressions not allowed (`()` and `[]`).");
126 case NODE_TYPEALIAS_TARGET
:
127 case NODE_TYPEALIAS_ALIAS
:
129 case NODE_TYPE_SPECIFIER
:
131 case NODE_FLOATING_POINT
:
135 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
141 switch (node
->u
.unary_expression
.link
) {
142 case UNARY_LINK_UNKNOWN
:
143 /* We don't allow empty link except on the first node of the list */
144 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
145 &node
->parent
->u
.ctf_expression
.left
:
146 &node
->parent
->u
.ctf_expression
.right
,
149 _BT_LOGE_LINENO(node
->lineno
,
150 "Empty link is not allowed except on first node of unary expression (need to separate nodes with `.` or `->`).");
155 case UNARY_ARROWLINK
:
156 /* We only allow -> and . links between children of ctf_expression. */
157 if (node
->parent
->type
!= NODE_CTF_EXPRESSION
) {
158 _BT_LOGE_LINENO(node
->lineno
,
159 "Links `.` and `->` are only allowed as children of CTF expression.");
163 * Only strings can be separated linked by . or ->.
164 * This includes "", '' and non-quoted identifiers.
166 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
167 _BT_LOGE_LINENO(node
->lineno
,
168 "Links `.` and `->` are only allowed to separate strings and identifiers.");
171 /* We don't allow link on the first node of the list */
172 if (is_ctf_exp
&& _bt_list_first_entry(is_ctf_exp_left
?
173 &node
->parent
->u
.ctf_expression
.left
:
174 &node
->parent
->u
.ctf_expression
.right
,
177 _BT_LOGE_LINENO(node
->lineno
,
178 "Links `.` and `->` are not allowed before first node of the unary expression list.");
182 case UNARY_DOTDOTDOT
:
183 /* We only allow ... link between children of enumerator. */
184 if (node
->parent
->type
!= NODE_ENUMERATOR
) {
185 _BT_LOGE_LINENO(node
->lineno
,
186 "Link `...` is only allowed within enumerator.");
189 /* We don't allow link on the first node of the list */
190 if (_bt_list_first_entry(&node
->parent
->u
.enumerator
.values
,
193 _BT_LOGE_LINENO(node
->lineno
,
194 "Link `...` is not allowed on the first node of the unary expression list.");
199 _BT_LOGE_LINENO(node
->lineno
,
200 "Unknown expression link type: type=%d",
201 node
->u
.unary_expression
.link
);
207 _BT_LOGE_LINENO(node
->lineno
,
208 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
209 node_type(node
), node_type(node
->parent
));
210 return -EINVAL
; /* Incoherent structure */
213 _BT_LOGE_LINENO(node
->lineno
,
214 "Semantic error: node-type=%s, parent-node-type=%s",
215 node_type(node
), node_type(node
->parent
));
216 return -EPERM
; /* Structure not allowed */
220 int ctf_visitor_field_class_specifier_list(int depth
, struct ctf_node
*node
)
222 switch (node
->parent
->type
) {
223 case NODE_CTF_EXPRESSION
:
224 case NODE_TYPE_DECLARATOR
:
226 case NODE_TYPEALIAS_TARGET
:
227 case NODE_TYPEALIAS_ALIAS
:
229 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
239 case NODE_UNARY_EXPRESSION
:
241 case NODE_TYPE_SPECIFIER
:
242 case NODE_TYPE_SPECIFIER_LIST
:
244 case NODE_FLOATING_POINT
:
247 case NODE_ENUMERATOR
:
255 _BT_LOGE_LINENO(node
->lineno
,
256 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
257 node_type(node
), node_type(node
->parent
));
258 return -EINVAL
; /* Incoherent structure */
262 int ctf_visitor_field_class_specifier(int depth
, struct ctf_node
*node
)
264 switch (node
->parent
->type
) {
265 case NODE_TYPE_SPECIFIER_LIST
:
268 case NODE_CTF_EXPRESSION
:
269 case NODE_TYPE_DECLARATOR
:
271 case NODE_TYPEALIAS_TARGET
:
272 case NODE_TYPEALIAS_ALIAS
:
274 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
282 case NODE_UNARY_EXPRESSION
:
284 case NODE_TYPE_SPECIFIER
:
286 case NODE_FLOATING_POINT
:
289 case NODE_ENUMERATOR
:
297 _BT_LOGE_LINENO(node
->lineno
,
298 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
299 node_type(node
), node_type(node
->parent
));
300 return -EINVAL
; /* Incoherent structure */
304 int ctf_visitor_field_class_declarator(int depth
, struct ctf_node
*node
)
307 struct ctf_node
*iter
;
311 switch (node
->parent
->type
) {
312 case NODE_TYPE_DECLARATOR
:
314 * A nested field class declarator is not allowed to
317 if (!bt_list_empty(&node
->u
.field_class_declarator
.pointers
))
320 case NODE_TYPEALIAS_TARGET
:
322 case NODE_TYPEALIAS_ALIAS
:
324 * Only accept alias name containing:
326 * - identifier * (any number of pointers)
327 * NOT accepting alias names containing [] (would otherwise
328 * cause semantic clash for later declarations of
329 * arrays/sequences of elements, where elements could be
330 * arrays/sequences themselves (if allowed in field class alias).
331 * NOT accepting alias with identifier. The declarator should
332 * be either empty or contain pointer(s).
334 if (node
->u
.field_class_declarator
.type
== TYPEDEC_NESTED
)
336 bt_list_for_each_entry(iter
, &node
->parent
->u
.field_class_alias_name
.field_class_specifier_list
->u
.field_class_specifier_list
.head
,
338 switch (iter
->u
.field_class_specifier
.type
) {
339 case TYPESPEC_FLOATING_POINT
:
340 case TYPESPEC_INTEGER
:
341 case TYPESPEC_STRING
:
342 case TYPESPEC_STRUCT
:
343 case TYPESPEC_VARIANT
:
345 if (bt_list_empty(&node
->u
.field_class_declarator
.pointers
))
352 if (node
->u
.field_class_declarator
.type
== TYPEDEC_ID
&&
353 node
->u
.field_class_declarator
.u
.id
!= NULL
)
357 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
367 case NODE_CTF_EXPRESSION
:
368 case NODE_UNARY_EXPRESSION
:
370 case NODE_TYPE_SPECIFIER
:
372 case NODE_FLOATING_POINT
:
375 case NODE_ENUMERATOR
:
383 bt_list_for_each_entry(iter
, &node
->u
.field_class_declarator
.pointers
,
385 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
390 switch (node
->u
.field_class_declarator
.type
) {
395 if (node
->u
.field_class_declarator
.u
.nested
.field_class_declarator
) {
396 ret
= _ctf_visitor_semantic_check(depth
+ 1,
397 node
->u
.field_class_declarator
.u
.nested
.field_class_declarator
);
401 if (!node
->u
.field_class_declarator
.u
.nested
.abstract_array
) {
402 bt_list_for_each_entry(iter
, &node
->u
.field_class_declarator
.u
.nested
.length
,
404 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
405 _BT_LOGE_LINENO(node
->lineno
,
406 "Expecting unary expression as length: node-type=%s",
410 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
415 if (node
->parent
->type
== NODE_TYPEALIAS_TARGET
) {
416 _BT_LOGE_LINENO(node
->lineno
,
417 "Abstract array declarator not permitted as target of field class alias.");
421 if (node
->u
.field_class_declarator
.bitfield_len
) {
422 ret
= _ctf_visitor_semantic_check(depth
+ 1,
423 node
->u
.field_class_declarator
.bitfield_len
);
429 case TYPEDEC_UNKNOWN
:
431 _BT_LOGE_LINENO(node
->lineno
,
432 "Unknown field class declarator: type=%d",
433 node
->u
.field_class_declarator
.type
);
440 _BT_LOGE_LINENO(node
->lineno
,
441 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
442 node_type(node
), node_type(node
->parent
));
443 return -EINVAL
; /* Incoherent structure */
446 _BT_LOGE_LINENO(node
->lineno
,
447 "Semantic error: node-type=%s, parent-node-type=%s",
448 node_type(node
), node_type(node
->parent
));
449 return -EPERM
; /* Structure not allowed */
453 int _ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
)
456 struct ctf_node
*iter
;
461 switch (node
->type
) {
463 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
, siblings
) {
464 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
468 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
469 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
473 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
474 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
478 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
479 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
486 switch (node
->parent
->type
) {
493 bt_list_for_each_entry(iter
, &node
->u
.event
.declaration_list
, siblings
) {
494 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
500 switch (node
->parent
->type
) {
507 bt_list_for_each_entry(iter
, &node
->u
.stream
.declaration_list
, siblings
) {
508 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
514 switch (node
->parent
->type
) {
521 bt_list_for_each_entry(iter
, &node
->u
.env
.declaration_list
, siblings
) {
522 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
528 switch (node
->parent
->type
) {
535 bt_list_for_each_entry(iter
, &node
->u
.trace
.declaration_list
, siblings
) {
536 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
542 switch (node
->parent
->type
) {
549 bt_list_for_each_entry(iter
, &node
->u
.clock
.declaration_list
, siblings
) {
550 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
556 switch (node
->parent
->type
) {
563 bt_list_for_each_entry(iter
, &node
->u
.callsite
.declaration_list
, siblings
) {
564 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
570 case NODE_CTF_EXPRESSION
:
571 switch (node
->parent
->type
) {
579 case NODE_FLOATING_POINT
:
584 case NODE_CTF_EXPRESSION
:
585 case NODE_UNARY_EXPRESSION
:
587 case NODE_TYPEALIAS_TARGET
:
588 case NODE_TYPEALIAS_ALIAS
:
589 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
591 case NODE_TYPE_SPECIFIER
:
592 case NODE_TYPE_SPECIFIER_LIST
:
594 case NODE_TYPE_DECLARATOR
:
595 case NODE_ENUMERATOR
:
604 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.left
, siblings
) {
605 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
609 bt_list_for_each_entry(iter
, &node
->u
.ctf_expression
.right
, siblings
) {
610 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
616 case NODE_UNARY_EXPRESSION
:
617 return ctf_visitor_unary_expression(depth
, node
);
620 switch (node
->parent
->type
) {
629 case NODE_CTF_EXPRESSION
:
630 case NODE_UNARY_EXPRESSION
:
632 case NODE_TYPEALIAS_TARGET
:
633 case NODE_TYPEALIAS_ALIAS
:
635 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
636 case NODE_TYPE_SPECIFIER
:
637 case NODE_TYPE_SPECIFIER_LIST
:
639 case NODE_TYPE_DECLARATOR
:
640 case NODE_FLOATING_POINT
:
643 case NODE_ENUMERATOR
:
653 ret
= _ctf_visitor_semantic_check(depth
+ 1,
654 node
->u
.field_class_def
.field_class_specifier_list
);
657 bt_list_for_each_entry(iter
, &node
->u
.field_class_def
.field_class_declarators
, siblings
) {
658 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
664 case NODE_TYPEALIAS_TARGET
:
668 switch (node
->parent
->type
) {
676 ret
= _ctf_visitor_semantic_check(depth
+ 1,
677 node
->u
.field_class_alias_target
.field_class_specifier_list
);
681 bt_list_for_each_entry(iter
, &node
->u
.field_class_alias_target
.field_class_declarators
, siblings
) {
682 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
687 if (nr_declarators
> 1) {
688 _BT_LOGE_LINENO(node
->lineno
,
689 "Too many declarators in field class alias's name (maximum is 1): count=%d",
696 case NODE_TYPEALIAS_ALIAS
:
700 switch (node
->parent
->type
) {
708 ret
= _ctf_visitor_semantic_check(depth
+ 1,
709 node
->u
.field_class_alias_name
.field_class_specifier_list
);
713 bt_list_for_each_entry(iter
, &node
->u
.field_class_alias_name
.field_class_declarators
, siblings
) {
714 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
719 if (nr_declarators
> 1) {
720 _BT_LOGE_LINENO(node
->lineno
,
721 "Too many declarators in field class alias's name (maximum is 1): count=%d",
729 switch (node
->parent
->type
) {
738 case NODE_CTF_EXPRESSION
:
739 case NODE_UNARY_EXPRESSION
:
741 case NODE_TYPEALIAS_TARGET
:
742 case NODE_TYPEALIAS_ALIAS
:
744 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
745 case NODE_TYPE_SPECIFIER
:
746 case NODE_TYPE_SPECIFIER_LIST
:
748 case NODE_TYPE_DECLARATOR
:
749 case NODE_FLOATING_POINT
:
752 case NODE_ENUMERATOR
:
761 ret
= _ctf_visitor_semantic_check(depth
+ 1, node
->u
.field_class_alias
.target
);
764 ret
= _ctf_visitor_semantic_check(depth
+ 1, node
->u
.field_class_alias
.alias
);
769 case NODE_TYPE_SPECIFIER_LIST
:
770 ret
= ctf_visitor_field_class_specifier_list(depth
, node
);
774 case NODE_TYPE_SPECIFIER
:
775 ret
= ctf_visitor_field_class_specifier(depth
, node
);
780 switch (node
->parent
->type
) {
781 case NODE_TYPE_DECLARATOR
:
787 case NODE_TYPE_DECLARATOR
:
788 ret
= ctf_visitor_field_class_declarator(depth
, node
);
793 case NODE_FLOATING_POINT
:
794 switch (node
->parent
->type
) {
795 case NODE_TYPE_SPECIFIER
:
800 case NODE_UNARY_EXPRESSION
:
803 bt_list_for_each_entry(iter
, &node
->u
.floating_point
.expressions
, siblings
) {
804 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
810 switch (node
->parent
->type
) {
811 case NODE_TYPE_SPECIFIER
:
818 bt_list_for_each_entry(iter
, &node
->u
.integer
.expressions
, siblings
) {
819 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
825 switch (node
->parent
->type
) {
826 case NODE_TYPE_SPECIFIER
:
831 case NODE_UNARY_EXPRESSION
:
835 bt_list_for_each_entry(iter
, &node
->u
.string
.expressions
, siblings
) {
836 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
841 case NODE_ENUMERATOR
:
842 switch (node
->parent
->type
) {
849 * Enumerators are only allows to contain:
850 * numeric unary expression
851 * or num. unary exp. ... num. unary exp
856 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
,
859 case 0: if (iter
->type
!= NODE_UNARY_EXPRESSION
860 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
861 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
862 || iter
->u
.unary_expression
.link
!= UNARY_LINK_UNKNOWN
) {
863 _BT_LOGE_LINENO(iter
->lineno
,
864 "First unary expression of enumerator is unexpected.");
868 case 1: if (iter
->type
!= NODE_UNARY_EXPRESSION
869 || (iter
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
870 && iter
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
)
871 || iter
->u
.unary_expression
.link
!= UNARY_DOTDOTDOT
) {
872 _BT_LOGE_LINENO(iter
->lineno
,
873 "Second unary expression of enumerator is unexpected.");
883 bt_list_for_each_entry(iter
, &node
->u
.enumerator
.values
, siblings
) {
884 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
890 switch (node
->parent
->type
) {
891 case NODE_TYPE_SPECIFIER
:
896 case NODE_UNARY_EXPRESSION
:
901 ret
= _ctf_visitor_semantic_check(depth
+ 1, node
->u
._enum
.container_field_class
);
905 bt_list_for_each_entry(iter
, &node
->u
._enum
.enumerator_list
, siblings
) {
906 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
912 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
913 switch (node
->parent
->type
) {
920 ret
= _ctf_visitor_semantic_check(depth
+ 1,
921 node
->u
.struct_or_variant_declaration
.field_class_specifier_list
);
924 bt_list_for_each_entry(iter
, &node
->u
.struct_or_variant_declaration
.field_class_declarators
, siblings
) {
925 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
931 switch (node
->parent
->type
) {
932 case NODE_TYPE_SPECIFIER
:
937 case NODE_UNARY_EXPRESSION
:
940 bt_list_for_each_entry(iter
, &node
->u
.variant
.declaration_list
, siblings
) {
941 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
948 switch (node
->parent
->type
) {
949 case NODE_TYPE_SPECIFIER
:
954 case NODE_UNARY_EXPRESSION
:
957 bt_list_for_each_entry(iter
, &node
->u
._struct
.declaration_list
, siblings
) {
958 ret
= _ctf_visitor_semantic_check(depth
+ 1, iter
);
966 _BT_LOGE_LINENO(node
->lineno
,
967 "Unknown node type: type=%d", node
->type
);
973 _BT_LOGE_LINENO(node
->lineno
,
974 "Incoherent parent node's type: node-type=%s, parent-node-type=%s",
975 node_type(node
), node_type(node
->parent
));
976 return -EINVAL
; /* Incoherent structure */
979 _BT_LOGE_LINENO(node
->lineno
,
980 "Semantic error: node-type=%s, parent-node-type=%s",
981 node_type(node
), node_type(node
->parent
));
982 return -EPERM
; /* Structure not allowed */
985 int ctf_visitor_semantic_check(int depth
, struct ctf_node
*node
)
990 * First make sure we create the parent links for all children. Let's
991 * take the safe route and recreate them at each validation, just in
992 * case the structure has changed.
994 ret
= ctf_visitor_parent_links(depth
, node
);
996 _BT_LOGE_LINENO(node
->lineno
,
997 "Cannot create parent links in metadata's AST: "
1002 ret
= _ctf_visitor_semantic_check(depth
, node
);
1004 _BT_LOGE_LINENO(node
->lineno
,
1005 "Cannot check metadata's AST semantics: "