Skip to content

Commit c0e99d9

Browse files
committed
Merge branch 'mr/thevenoux/langkit-query-language#587' into 'master'
Add detector for KP 20229 Closes #587 See merge request eng/libadalang/langkit-query-language!592
2 parents ec28e53 + 141e1d0 commit c0e99d9

File tree

7 files changed

+159
-3
lines changed

7 files changed

+159
-3
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import stdlib
2+
3+
fun has_clobber(node) =
4+
|" Return whether this call expression is an instance of
5+
|" ``system.machine_code.asm`` that sets the ``clobber`` parameter.
6+
node is CallExpr
7+
when stdlib.any([
8+
p.param.p_canonical_fully_qualified_name()
9+
== "system.machine_code.asm.clobber"
10+
for p in node.f_suffix.p_zip_with_params()
11+
])
12+
13+
fun get_output(node) =
14+
|" If node is an instance of ``system.machine_code.asm`` that defines only
15+
|" one ``Asm_Output`` variable, then return it, null otherwise.
16+
if node is CallExpr
17+
then {
18+
val output = [
19+
p for p in node.f_suffix.p_zip_with_params()
20+
if p.param.p_canonical_fully_qualified_name()
21+
== "system.machine_code.asm.outputs"
22+
]?[1];
23+
24+
if output is not null
25+
and output.actual is not Aggregate
26+
and output.actual.f_name is AttributeRef
27+
and output.actual.f_name.f_attribute.p_name_is("asm_output")
28+
then
29+
# Get the defining name of the output variable (this can't fail
30+
# since this param is synthesized by Libadalang).
31+
[
32+
p for p in output.actual.f_suffix.p_zip_with_params()
33+
if p.param.f_name.p_name_is("value")
34+
][1].actual.p_referenced_defining_name()
35+
else null
36+
}
37+
else null
38+
39+
@check(help="possible occurrence of KP 20229",
40+
message="possible occurrence of KP 20229")
41+
fun kp_20229(node) =
42+
|" Look for single-output extended ``asm`` statements
43+
|" with clobbers followed by ``return`` statements that return
44+
|" the single output from the ``asm`` statement.
45+
node is CallStmt
46+
when has_clobber(node.f_call)
47+
and {
48+
val output = get_output(node.f_call);
49+
50+
if output then
51+
stdlib.any([
52+
from r.ref through parent select first ReturnStmt
53+
for r in output.p_find_all_references(units())
54+
])
55+
else false
56+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
with Ada.Text_IO; use Ada.Text_IO;
2+
with System.Machine_Code; use System.Machine_Code;
3+
4+
procedure Main is
5+
procedure P is null;
6+
7+
-- Flag because it has clobbers, one output variable that is returned.
8+
function F1 (Var_In : Integer) return Integer is
9+
Var_Out : Integer;
10+
begin
11+
Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- FLAG
12+
"movl %0, %1",
13+
Outputs => Integer'Asm_Output ("=a", Var_Out),
14+
Inputs => Integer'Asm_Input ("a", Var_In),
15+
Clobber => "memory");
16+
null;
17+
P;
18+
return Var_Out;
19+
end;
20+
21+
-- Do not flag because it has more than one output.
22+
function F2 (Var_In : Integer) return Integer is
23+
Var_Out1, Var_Out2 : Integer;
24+
begin
25+
Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- NOFLAG
26+
"movl %0, %1",
27+
Outputs => (Integer'Asm_Output ("=a", Var_Out1),
28+
Integer'Asm_Output ("=a", Var_Out2)),
29+
Inputs => Integer'Asm_Input ("a", Var_In),
30+
Clobber => "memory");
31+
return Var_Out1;
32+
end;
33+
34+
-- Do not flag because it has no clobbers
35+
function F3 (Var_In : Integer) return Integer is
36+
Var_Out1, Var_Out2 : Integer;
37+
begin
38+
Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- NOFLAG
39+
"movl %0, %1",
40+
Outputs => Integer'Asm_Output ("=a", Var_Out1),
41+
Inputs => Integer'Asm_Input ("a", Var_In));
42+
return Var_Out1;
43+
end;
44+
45+
-- Do not flag because it doesn't return the sole output variable.
46+
function F4 (Var_In : Integer) return Integer is
47+
Var_Out1, Var_Out2 : Integer;
48+
begin
49+
Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- NOFLAG
50+
"movl %0, %1",
51+
Outputs => Integer'Asm_Output ("=a", Var_Out1),
52+
Inputs => Integer'Asm_Input ("a", Var_In));
53+
return Var_In;
54+
end;
55+
56+
-- Flag because it has clobbers, one output variable that is returned.
57+
function F5 (Var_In : Integer) return Integer is
58+
Var_Out : Integer;
59+
begin
60+
if True
61+
then
62+
Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- FLAG
63+
"movl %0, %1",
64+
Outputs => Integer'Asm_Output ("=a", Var_Out),
65+
Inputs => Integer'Asm_Input ("a", Var_In),
66+
Clobber => "memory");
67+
else
68+
return 4;
69+
end if;
70+
71+
return Var_Out;
72+
end;
73+
begin
74+
Put_Line(F1 (1)'Image);
75+
end;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
project Prj is
2+
end Prj;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
main.adb:11:7: rule violation: possible occurrence of KP 20229
2+
11 | Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- FLAG
3+
| _______^
4+
||
5+
|| ~~~ 3 other lines ~~~
6+
||
7+
15 || Clobber => "memory");
8+
||_______________________________^
9+
10+
main.adb:62:10: rule violation: possible occurrence of KP 20229
11+
62 | Asm("addl $42, %1" & ASCII.LF & ASCII.HT & -- FLAG
12+
| __________^
13+
||
14+
|| ~~~ 3 other lines ~~~
15+
||
16+
66 || Clobber => "memory");
17+
||__________________________________^
18+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
driver: checker
2+
rule_name: kp_20229
3+
project: prj.gpr

testsuite/tests/gnatcheck/xml_help/test.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ testsuite_driver: No output file generated by gnatcheck
102102
<check switch="+Rkp_20113" label="possible occurrence of KP 20113"/>
103103
<check switch="+Rkp_20186" label="possible occurrence of KP 20186"/>
104104
<check switch="+Rkp_20227" label="possible occurrence of KP 20227"/>
105+
<check switch="+Rkp_20229" label="possible occurrence of KP 20229"/>
105106
<check switch="+Rkp_ob03_009" label="possible occurrence of KP OB03-009"/>
106107
<check switch="+Rkp_p226_024" label="possible occurrence of KP P226-024 - global analysis required"/>
107108
<check switch="+Rkp_q309_014" label="possible occurrence of KP Q309-014"/>
@@ -629,6 +630,7 @@ testsuite_driver: No output file generated by gnatcheck
629630
<check switch="+Rkp_20113" label="possible occurrence of KP 20113"/>
630631
<check switch="+Rkp_20186" label="possible occurrence of KP 20186"/>
631632
<check switch="+Rkp_20227" label="possible occurrence of KP 20227"/>
633+
<check switch="+Rkp_20229" label="possible occurrence of KP 20229"/>
632634
<check switch="+Rkp_ob03_009" label="possible occurrence of KP OB03-009"/>
633635
<check switch="+Rkp_p226_024" label="possible occurrence of KP P226-024 - global analysis required"/>
634636
<check switch="+Rkp_q309_014" label="possible occurrence of KP Q309-014"/>

user_manual/generated/std.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Builtin functions
1212

1313
Given a list, return the result of the concatenation of all its elements
1414

15-
.. function:: doc(value)
15+
.. function:: doc(function)
1616

1717
Given any object, return the documentation associated with it
1818

@@ -24,7 +24,7 @@ Builtin functions
2424

2525
Return a string in the RsT format containing documentation for all built-ins
2626

27-
.. function:: help(value)
27+
.. function:: help(function)
2828

2929
Print formatted help for the given object
3030

@@ -48,7 +48,7 @@ Builtin functions
4848

4949
Built-in print function. Prints the argument
5050

51-
.. function:: profile(val)
51+
.. function:: profile(function)
5252

5353
Given any object, if it is a callable, return its profile as text
5454

0 commit comments

Comments
 (0)