|
1 | 1 | import stdlib |
2 | 2 |
|
3 | | -fun is_static_int_attr_ref(expr) = |
4 | | - |" Returns whether the given expression is an attribute reference which |
5 | | - |" value is a static (compilation known) universal integer. |
| 3 | +fun is_static_int_attr(expr) = |
| 4 | + |" Returns whether the given expression is a universal-integer valued |
| 5 | + |" attribute reference known at compile time. |
6 | 6 | expr is AttributeRef |
7 | | - when expr.p_expression_type() == expr.p_universal_int_type() |
8 | | - and expr.p_is_static_expr() |
| 7 | + when expr.p_expression_type() == expr.p_universal_int_type() and |
| 8 | + expr.p_is_static_expr() |
9 | 9 |
|
10 | | -fun is_dynamic_subtype_formal(formal) = |
11 | | - |" Returns whether the given formal parameter DefiningName has a dynamic |
| 10 | +fun is_dynamic_subtyped_entity(name) = |
| 11 | + |" Returns whether the given name is a DefiningName and has a dynamic |
12 | 12 | |" subtype. |
13 | | - formal is DefiningName(p_basic_decl(): decl@BasicDecl) |
14 | | - when decl.f_type_expr is (SubtypeIndication | Name)( |
15 | | - p_is_static_subtype(): false |
16 | | - ) |
| 13 | + { |
| 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 | Name)( |
| 19 | + p_is_static_subtype(): false |
| 20 | + ) |
| 21 | + } |
| 22 | + |
| 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_static_subtype() |
| 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) |
17 | 34 |
|
18 | 35 | @check(help="possible occurrence of KP 19501", |
19 | 36 | message="possible occurrence of KP 19501", |
20 | 37 | impact="7.1.*,7.2.*,7.3.*,7.4.*,17.*,18.*,19.*,20.*,21.*,22.*,23.*,24.*") |
21 | 38 | fun kp_19501(node) = |
22 | | - |" Flag all call expressions which include at least one known problematic |
23 | | - |" formal/actual parameter pair. |
24 | | - node is CallExpr(p_is_call(): true) |
25 | | - when stdlib.any( |
26 | | - [ |
27 | | - is_static_int_attr_ref(p.actual) and |
28 | | - is_dynamic_subtype_formal(p.param) |
| 39 | + |" Flag constructions involving an integer valued attribute reference known |
| 40 | + |" at compile time, when the attribute reference is: |
| 41 | + |" * an actual parameter in a call where the subtype of the corresponding |
| 42 | + |" formal parameter is subject to a constraint |
| 43 | + |" * the expression of an assignment where the subtype of the target object |
| 44 | + |" is subject to a constraint |
| 45 | + |" * the operand of a qualified expression where the subtype mark |
| 46 | + |" denotes a subtype that is subject to a constraint |
| 47 | + |" * an array index value in an indexed component name |
| 48 | + |" |
| 49 | + |" Additionally, at least one of the bounds of the applicable constraint |
| 50 | + |" must be unknown at compile time. |
| 51 | + match node |
| 52 | + | CallExpr(p_is_call(): true) => |
| 53 | + stdlib.any([ |
| 54 | + is_static_int_attr(p.actual) and |
| 55 | + is_dynamic_subtyped_entity(p.param) |
29 | 56 | for p in node.p_call_params() |
30 | | - ] |
31 | | - ) |
| 57 | + ]) |
| 58 | + | CallExpr(p_kind(): "array_index") => |
| 59 | + array_index_has_kp(node, node.f_name.p_referenced_decl(), 1) |
| 60 | + | AssignStmt => |
| 61 | + is_static_int_attr(node.f_expr) and |
| 62 | + is_dynamic_subtyped_entity(node.f_dest) |
| 63 | + | QualExpr(f_suffix: ParenExpr(f_expr: operand)) => |
| 64 | + is_static_int_attr(operand) and |
| 65 | + node.f_prefix is (SubtypeIndication | Name)( |
| 66 | + p_is_static_subtype(): false |
| 67 | + ) |
0 commit comments