Skip to content

Commit 7e740b1

Browse files
committed
Fix exception_propagation_from_callbacks
1 parent f794335 commit 7e740b1

File tree

5 files changed

+88
-24
lines changed

5 files changed

+88
-24
lines changed

lkql_checker/doc/gnatcheck_rm/predefined_rules.rst

+10-10
Original file line numberDiff line numberDiff line change
@@ -2359,24 +2359,19 @@ This rule has no parameters.
23592359

23602360
Flag an ``'Address`` or ``'Access`` attribute if:
23612361

2362-
*
2363-
this attribute is a reference to a subprogram;
2362+
* this attribute is a reference to a subprogram;
23642363

2365-
*
2366-
this subprogram may propagate an exception;
2364+
* this subprogram may propagate an exception;
23672365

2368-
*
2369-
this attribute is an actual parameter of a subprogram call, and both the
2366+
* this attribute is an actual parameter of a subprogram call, and both the
23702367
subprogram called and the corresponding formal parameter are specified by a
23712368
rule parameter.
23722369

23732370
A subprogram is considered as not propagating an exception if:
23742371

2375-
*
2376-
its body has an exception handler with ``others`` exception choice;
2372+
* its body has an exception handler with ``others`` exception choice;
23772373

2378-
*
2379-
no exception handler in the body contains a raise statement nor a call to
2374+
* no exception handler in the body contains a raise statement nor a call to
23802375
``Ada.Exception.Raise_Exception`` or ``Ada.Exception.Reraise_Occurrence``.
23812376

23822377
The rule has an optional parameter for the ``+R`` option:
@@ -2413,6 +2408,11 @@ the subprogram of interest in case if renamings are used for this subprogram.
24132408
Note also, that the rule does not make any overload resolution, so calls to
24142409
all the subprograms corresponding to ``subprogram_name`` are checked.
24152410

2411+
.. note:: Note that you can use both fully qualified names to
2412+
instantiated or non-instantiated generic subprograms, depending on the
2413+
granularity you wish for. However **you cannot use a mix of the two**, so
2414+
the names need to be either fully instantiated or fully uninstantiated.
2415+
24162416

24172417
.. rubric:: Example
24182418

lkql_checker/share/lkql/exception_propagation_from_callbacks.lkql

+22-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313

1414
import stdlib
1515

16+
fun get_uninstantiated_subp(subp) =
17+
|" Works around an inconsistency in LAL's API wrt. generic subprograms
18+
|" TODO: Fix when eng/libadalang/libadalang/-/issues/1127 is fixed
19+
match subp
20+
| GenericSubpInstantiation(f_generic_subp_name is s@*) =>
21+
s.p_referenced_decl().p_get_uninstantiated_node()
22+
| AdaNode => subp.p_get_uninstantiated_node()
23+
| * => null
24+
25+
1626
@check(help="callback may propagate exceptions (global analysis required)",
1727
message="callback may propagate exceptions",
1828
category="Style", subcategory="Programming Practice")
@@ -26,10 +36,18 @@ fun exception_propagation_from_callbacks(node, callbacks=[]) =
2636
when (from node through parent
2737
select first CallExpr(p_is_call() is true)) is call@CallExpr
2838
when {
29-
val n = call.f_name.p_referenced_decl()?.
30-
p_canonical_fully_qualified_name?();
31-
val name = if n == () then "" else n;
32-
val params = [c[2] for c in callbacks if c[1] == name].to_list;
39+
val uninst_subp_name = get_uninstantiated_subp(
40+
call.f_name.p_referenced_decl()
41+
)?.p_canonical_fully_qualified_name?();
42+
43+
val subp_name = call.f_name.p_referenced_decl()
44+
?.p_canonical_fully_qualified_name?();
45+
46+
val params = [
47+
c[2] for c in callbacks
48+
if c[1] == uninst_subp_name
49+
or c[1] == subp_name
50+
].to_list;
3351

3452
params.length != 0 and
3553
[p for p in call.p_call_params()

testsuite/tests/checks/exception_propagation_from_callbacks/p.adb

+30-3
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,40 @@ package body P is
3737
procedure P3 is new P3_G;
3838

3939
generic procedure Take_Cb_G (I : Integer; Param : access procedure);
40-
procedure Take_Cb_G (I : Integer; Param : access procedure) is null;
40+
generic procedure Take_Cb_G_2 (I : Integer; Param : access procedure);
41+
42+
generic package Gen_Pkg is
43+
procedure Take_Cb (I : Integer; Param : access procedure);
44+
end Gen_Pkg;
45+
46+
package Pkg_Inst is new Gen_Pkg;
47+
4148
procedure Take_Cb_I is new Take_Cb_G;
49+
procedure Take_Cb_I_2 is new Take_Cb_G_2;
50+
51+
generic package Gen_Pkg_2 is
52+
generic procedure Gen_Cb (I : Integer; Param : access procedure);
53+
end Gen_Pkg_2;
54+
55+
package Pkg_2_Inst is new Gen_Pkg_2;
56+
57+
procedure Cb_Inst is new Pkg_2_Inst.Gen_Cb;
4258

4359
procedure Calls2 is
4460
begin
45-
Take_Cb (1, P3'Access); -- FLAG
46-
Take_Cb_I (1, P1'Access); -- FLAG
61+
Take_Cb (1, P3'Access); -- FLAG
62+
63+
-- Check that we can flag a generic subp via its instantiated name
64+
Take_Cb_I (1, P1'Access); -- FLAG
65+
66+
-- Check that we can flag a generic subp via its uninstantiated name
67+
Take_Cb_I_2 (1, P1'Access); -- FLAG
68+
69+
-- Check that we can flag a subp in a generic pkg via its uninstantiated
70+
-- name
71+
Pkg_Inst.Take_Cb (1, P1'Access); -- FLAG
72+
73+
Cb_Inst (1, P1'Access); -- FLAG
4774
end Calls2;
4875

4976
-- Tests on subunits

testsuite/tests/checks/exception_propagation_from_callbacks/test.out

+18-6
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,27 @@ p.adb:22:25: rule violation: callback may propagate exceptions
22
22 | Take_Cb (Param => P1'Access, I => 1); -- FLAG
33
| ^^^^^^^^^
44

5-
p.adb:45:19: rule violation: callback may propagate exceptions
6-
45 | Take_Cb (1, P3'Access); -- FLAG
5+
p.adb:61:19: rule violation: callback may propagate exceptions
6+
61 | Take_Cb (1, P3'Access); -- FLAG
77
| ^^^^^^^^^
88

9-
p.adb:46:21: rule violation: callback may propagate exceptions
10-
46 | Take_Cb_I (1, P1'Access); -- FLAG
9+
p.adb:64:21: rule violation: callback may propagate exceptions
10+
64 | Take_Cb_I (1, P1'Access); -- FLAG
1111
| ^^^^^^^^^
1212

13-
p.adb:55:19: rule violation: callback may propagate exceptions
14-
55 | Take_Cb (1, Sep'Access); -- FLAG
13+
p.adb:67:23: rule violation: callback may propagate exceptions
14+
67 | Take_Cb_I_2 (1, P1'Access); -- FLAG
15+
| ^^^^^^^^^
16+
17+
p.adb:71:28: rule violation: callback may propagate exceptions
18+
71 | Pkg_Inst.Take_Cb (1, P1'Access); -- FLAG
19+
| ^^^^^^^^^
20+
21+
p.adb:73:19: rule violation: callback may propagate exceptions
22+
73 | Cb_Inst (1, P1'Access); -- FLAG
23+
| ^^^^^^^^^
24+
25+
p.adb:82:19: rule violation: callback may propagate exceptions
26+
82 | Take_Cb (1, Sep'Access); -- FLAG
1527
| ^^^^^^^^^^
1628

testsuite/tests/checks/exception_propagation_from_callbacks/test.yaml

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@ driver: 'checker'
22
rule_name: Exception_Propagation_From_Callbacks
33
project: 'prj.gpr'
44
rule_arguments:
5-
exception_propagation_from_callbacks.callbacks: '[("p.take_cb", "Param"),("p.take_cb_i", "Param")]'
5+
exception_propagation_from_callbacks.callbacks: |
6+
[
7+
("p.take_cb", "Param"),
8+
("p.take_cb_i", "Param"),
9+
("p.take_cb_g_2", "Param"),
10+
("p.gen_pkg.take_cb", "Param"),
11+
("p.gen_pkg_2.gen_cb", "Param")
12+
]

0 commit comments

Comments
 (0)