|
1 | 1 | import stdlib |
2 | 2 |
|
3 | | -fun is_static_int_attr(expr) = |
| 3 | +fun is_int_attr(expr) = |
4 | 4 | |" Returns whether the given expression is a universal-integer valued |
5 | | - |" attribute reference known at compile time. |
| 5 | + |" attribute reference. |
6 | 6 | expr is AttributeRef |
7 | | - when expr.p_expression_type() == expr.p_universal_int_type() and |
8 | | - expr.p_is_static_expr() |
| 7 | + when expr.p_expression_type() == expr.p_universal_int_type() |
9 | 8 |
|
10 | | -fun is_dynamic_subtyped_entity(name) = |
11 | | - |" Returns whether the given name is a DefiningName and has a dynamic |
12 | | - |" subtype. |
| 9 | + |
| 10 | +fun is_subtype_indication_constrained(subtype_indication) = |
| 11 | + |" Return whether the provided SubtypeIndication is constrained. |
13 | 12 | { |
14 | | - val decl = match name |
15 | | - | DefiningName => name.p_basic_decl() |
16 | | - | Name => name.p_referenced_decl(); |
17 | | - decl is (ComponentDef | DiscriminantSpec | ObjectDecl | ParamSpec) |
18 | | - when decl.f_type_expr is (SubtypeIndication)( |
19 | | - p_is_statically_constrained(): false |
| 13 | + |
| 14 | + fun is_constrained_subtype(type_decl) = |
| 15 | + |" Returns whether the provided BaseTypeDecl declares a constrained |
| 16 | + |" subtype. |
| 17 | + { |
| 18 | + (type_decl.p_has_aspect("Predicate") |
| 19 | + and not type_decl.p_is_statically_predicated()) |
| 20 | + or type_decl.p_has_aspect("Dynamic_Predicate") |
| 21 | + or type_decl.p_full_view() is BaseTypeDecl when |
| 22 | + match type_decl |
| 23 | + | TypeDecl => ( |
| 24 | + match type_decl.f_type_def |
| 25 | + | ArrayTypeDef(f_indices: ConstrainedArrayIndices) => true |
| 26 | + | d@DerivedTypeDef => |
| 27 | + is_subtype_indication_constrained( |
| 28 | + d.f_subtype_indication |
| 29 | + ) |
| 30 | + | * => false |
| 31 | + ) |
| 32 | + | sd@SubtypeDecl => |
| 33 | + is_subtype_indication_constrained(sd.f_subtype) |
| 34 | + }; |
| 35 | + |
| 36 | + subtype_indication.f_constraint is not null |
| 37 | + or is_constrained_subtype( |
| 38 | + subtype_indication.f_name.p_referenced_decl() |
20 | 39 | ) |
21 | 40 | } |
22 | 41 |
|
23 | | -fun array_index_has_kp(expr, array_decl, child_n) = |
24 | | - |" Returns whether the given array indexing expression contains an index |
25 | | - |" being a reference to the ``Length`` attribute, while dimension bounds |
26 | | - |" aren't static. Recurse on all indexing expr params starting from |
27 | | - |" ``child_n``. |
28 | | - match expr.f_suffix[child_n]?.f_r_expr |
29 | | - | e when is_static_int_attr(e) => |
30 | | - if array_decl.f_type_expr.p_is_statically_constrained() |
31 | | - then array_index_has_kp(expr, array_decl, child_n + 1) |
32 | | - | null => false |
33 | | - | * => array_index_has_kp(expr, array_decl, child_n + 1) |
| 42 | + |
| 43 | +fun is_subject_to_constraint(name) = |
| 44 | + |" Returns whether the given name refers to a subtype subject to a |
| 45 | + |" constraint. |
| 46 | + { |
| 47 | + val decl = match name |
| 48 | + | DefiningName => name.p_basic_decl() |
| 49 | + | Name => name.p_referenced_decl(); |
| 50 | + |
| 51 | + match decl |
| 52 | + | (ComponentDef | DiscriminantSpec | ObjectDecl | ParamSpec) => |
| 53 | + decl.f_type_expr is SubtypeIndication |
| 54 | + and is_subtype_indication_constrained(decl.f_type_expr) |
| 55 | + | SubtypeDecl => is_subtype_indication_constrained(decl.f_subtype) |
| 56 | + } |
| 57 | + |
34 | 58 |
|
35 | 59 | @check(help="possible occurrence of KP 19501", |
36 | 60 | message="possible occurrence of KP 19501") |
37 | 61 | fun kp_19501(node) = |
38 | | - |" Flag constructions involving an integer valued attribute reference known |
39 | | - |" at compile time, when the attribute reference is: |
| 62 | + |" Flag constructions involving an integer valued attribute reference when |
| 63 | + |" the attribute reference is: |
40 | 64 | |" * an actual parameter in a call where the subtype of the corresponding |
41 | 65 | |" formal parameter is subject to a constraint |
42 | 66 | |" * the expression of an assignment where the subtype of the target object |
43 | 67 | |" is subject to a constraint |
44 | 68 | |" * the operand of a qualified expression where the subtype mark |
45 | 69 | |" denotes a subtype that is subject to a constraint |
46 | 70 | |" * an array index value in an indexed component name |
47 | | - |" |
48 | | - |" Additionally, at least one of the bounds of the applicable constraint |
49 | | - |" must be unknown at compile time. |
50 | 71 | match node |
51 | 72 | | CallExpr(p_is_call(): true) => |
52 | 73 | stdlib.any([ |
53 | | - is_static_int_attr(p.actual) and |
54 | | - is_dynamic_subtyped_entity(p.param) |
| 74 | + is_int_attr(p.actual) and is_subject_to_constraint(p.param) |
55 | 75 | for p in node.p_call_params() |
56 | 76 | ]) |
57 | | - | CallExpr(p_kind(): "array_index") => |
58 | | - array_index_has_kp(node, node.f_name.p_referenced_decl(), 1) |
59 | 77 | | AssignStmt => |
60 | | - is_static_int_attr(node.f_expr) and |
61 | | - is_dynamic_subtyped_entity(node.f_dest) |
| 78 | + is_int_attr(node.f_expr) and is_subject_to_constraint(node.f_dest) |
62 | 79 | | QualExpr(f_suffix: ParenExpr(f_expr: operand)) => |
63 | | - is_static_int_attr(operand) and |
64 | | - node.f_prefix is (Name)( |
65 | | - p_name_designated_type(): BaseTypeDecl(p_is_statically_constrained(): false) |
66 | | - ) |
| 80 | + is_int_attr(operand) |
| 81 | + and node.f_prefix is Name |
| 82 | + and is_subject_to_constraint(node.f_prefix) |
| 83 | + | CallExpr(p_kind(): "array_index") => |
| 84 | + stdlib.any([ |
| 85 | + is_int_attr(p.f_r_expr) |
| 86 | + for p in node.f_suffix.children |
| 87 | + ]) |
0 commit comments