Skip to content

Commit d57946b

Browse files
committed
Use clang_analyzer_dump in tests
Note that we need to expect e.g. {{2 S32}} because the pattern {{2}} would match any other 32-bit integer as well. The last two testcases in the file were testing the same thing in different ways, so this commit only keeps the one that used `clang_analyzer_dump` (which was previously an exception).
1 parent 011008b commit d57946b

File tree

1 file changed

+48
-77
lines changed

1 file changed

+48
-77
lines changed

clang/test/Analysis/legacy-inlining-prevention.c

Lines changed: 48 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,55 @@
33

44
int getNum(void); // Get an opaque number.
55

6-
void clang_analyzer_numTimesReached(void);
76
void clang_analyzer_dump(int arg);
87

98
//-----------------------------------------------------------------------------
10-
// Simple case: inlined function never reaches `analyzer-max-loop`.
9+
// Simple case: inlined function never reaches `analyzer-max-loop`, so it is
10+
// always inlined.
1111

12-
int inner_simple(void) {
13-
clang_analyzer_numTimesReached(); // expected-warning {{2}}
12+
int inner_simple(int callIdx) {
13+
clang_analyzer_dump(callIdx); // expected-warning {{1 S32}}
14+
// expected-warning@-1 {{2 S32}}
1415
return 42;
1516
}
1617

1718
int outer_simple(void) {
18-
int x = inner_simple();
19-
int y = inner_simple();
19+
int x = inner_simple(1);
20+
int y = inner_simple(2);
2021
return 53 / (x - y); // expected-warning {{Division by zero}}
2122
}
2223

2324
//-----------------------------------------------------------------------------
24-
// Inlined function always reaches `analyzer-max-loop`.
25+
// Inlined function always reaches `analyzer-max-loop`, which stops the
26+
// analysis on that path and puts the function on the "do not inline" list.
2527

26-
int inner_fixed_loop_1(void) {
28+
int inner_fixed_loop_1(int callIdx) {
2729
int i;
28-
clang_analyzer_numTimesReached(); // expected-warning {{1}}
30+
clang_analyzer_dump(callIdx); // expected-warning {{1 S32}}
2931
for (i = 0; i < 10; i++);
30-
clang_analyzer_numTimesReached(); // no-warning
32+
clang_analyzer_dump(callIdx); // no-warning
3133
return 42;
3234
}
3335

3436
int outer_fixed_loop_1(void) {
35-
int x = inner_fixed_loop_1();
36-
int y = inner_fixed_loop_1();
37+
int x = inner_fixed_loop_1(1);
38+
int y = inner_fixed_loop_1(2);
3739
return 53 / (x - y); // no-warning
3840
}
3941

4042
//-----------------------------------------------------------------------------
4143
// Inlined function always reaches `analyzer-max-loop`; inlining is prevented
4244
// even for different entry points.
43-
// This test uses `clang_analyzer_dump` and distinct `arg` values because
44-
// `clang_analyzer_numTimesReached` only counts the paths reaching that node
45-
// during the analysis of one particular entry point, so it cannot distinguish
46-
// "two entry points reached this, both with one path" (where the two reports
47-
// are unified as duplicates by the generic report postprocessing) and "one
48-
// entry point reached this with one path" (where naturally nothing shows that
49-
// the second entry point _tried_ to reach it).
50-
51-
int inner_fixed_loop_2(int arg) {
45+
// NOTE: the analyzer happens to analyze the entry points in a reversed order,
46+
// so `outer_2_fixed_loop_2` is analyzed first and it will be the one which is
47+
// able to inline the inner function.
48+
49+
int inner_fixed_loop_2(int callIdx) {
5250
// Identical copy of inner_fixed_loop_1
5351
int i;
54-
clang_analyzer_dump(arg); // expected-warning {{2}}
52+
clang_analyzer_dump(callIdx); // expected-warning {{2 S32}}
5553
for (i = 0; i < 10; i++);
56-
clang_analyzer_dump(arg); // no-warning
54+
clang_analyzer_dump(callIdx); // no-warning
5755
return 42;
5856
}
5957

@@ -72,9 +70,10 @@ int outer_2_fixed_loop_2(void) {
7270

7371
int inner_parametrized_loop_1(int count) {
7472
int i;
75-
clang_analyzer_numTimesReached(); // expected-warning {{2}}
73+
clang_analyzer_dump(count); // expected-warning {{2 S32}}
74+
// expected-warning@-1 {{10 S32}}
7675
for (i = 0; i < count; i++);
77-
clang_analyzer_numTimesReached(); // expected-warning {{1}}
76+
clang_analyzer_dump(count); // expected-warning {{2 S32}}
7877
return 42;
7978
}
8079

@@ -90,9 +89,9 @@ int outer_parametrized_loop_1(void) {
9089

9190
int inner_parametrized_loop_2(int count) {
9291
int i;
93-
clang_analyzer_numTimesReached(); // expected-warning {{1}}
92+
clang_analyzer_dump(count); // expected-warning {{10 S32}}
9493
for (i = 0; i < count; i++);
95-
clang_analyzer_numTimesReached(); // no-warning
94+
clang_analyzer_dump(count); // no-warning
9695
return 42;
9796
}
9897

@@ -108,23 +107,28 @@ int outer_parametrized_loop_2(void) {
108107
// cases: the function is placed on the "don't inline" list when any execution
109108
// path reaches `analyzer-max-loop` (even if other execution paths reach the
110109
// end of the function).
110+
// NOTE: This is tested with two separate entry points to ensure that one
111+
// inlined call is fully evaluated before we try to inline the other call.
112+
// NOTE: the analyzer happens to analyze the entry points in a reversed order,
113+
// so `outer_2_conditional_loop` is analyzed first and it will be the one which
114+
// is able to inline the inner function.
111115

112-
int inner_conditional_loop(void) {
116+
int inner_conditional_loop(int callIdx) {
113117
int i;
114-
clang_analyzer_numTimesReached(); // expected-warning {{1}}
118+
clang_analyzer_dump(callIdx); // expected-warning {{2 S32}}
115119
if (getNum() == 777) {
116120
for (i = 0; i < 10; i++);
117121
}
118-
clang_analyzer_numTimesReached(); // expected-warning {{1}}
122+
clang_analyzer_dump(callIdx); // expected-warning {{2 S32}}
119123
return 42;
120124
}
121125

122126
int outer_1_conditional_loop(void) {
123-
return inner_conditional_loop();
127+
return inner_conditional_loop(1);
124128
}
125129

126130
int outer_2_conditional_loop(void) {
127-
return inner_conditional_loop();
131+
return inner_conditional_loop(2);
128132
}
129133

130134
//-----------------------------------------------------------------------------
@@ -142,57 +146,24 @@ int outer_2_conditional_loop(void) {
142146
// option `legacy-inlining-prevention` was introduced and enabled by default to
143147
// suppress the inlining in situations where the "don't assume third iteration"
144148
// logic activates.
145-
// This testcase demonstrate that the inlining is prevented with the default
146-
// `legacy-inlining-prevention=true` config, but is not prevented when this
147-
// option is disabled (set to false).
148-
149-
int inner_opaque_loop_1(void) {
150-
int i;
151-
clang_analyzer_numTimesReached(); // default-warning {{1}} disabled-warning {{2}}
152-
for (i = 0; i < getNum(); i++);
153-
return i;
154-
}
149+
// NOTE: This is tested with two separate entry points to ensure that one
150+
// inlined call is fully evaluated before we try to inline the other call.
151+
// NOTE: the analyzer happens to analyze the entry points in a reversed order,
152+
// so `outer_2_opaque_loop` is analyzed first and it will be the one which is
153+
// able to inline the inner function.
155154

156-
int outer_opaque_loop_1(void) {
157-
int iterCount = inner_opaque_loop_1();
158-
159-
// The first call to `inner_opaque_loop_1()` splits three execution paths that
160-
// differ in the number of performed iterations (0, 1 or 2). The function
161-
// `inner_opaque_loop_1` is added to the "do not inline this" list when the
162-
// path that performed two iterations tries to enter the third iteration (and
163-
// the "don't assume third iteration" logic prevents this) -- but the other
164-
// two paths (which performed 0 and 1 iterations) would reach and inline the
165-
// second `inner_opaque_loop_1()` before this would happen (because the
166-
// default traversal is a complex heuristic that happens to prefer this). The
167-
// following `if` will discard these "early exit" paths to highlight the
168-
// difference between the default and disabled state:
169-
if (iterCount < 2)
170-
return 0;
171-
172-
return inner_opaque_loop_1();
173-
}
174-
175-
//-----------------------------------------------------------------------------
176-
// Another less contrived testcase that demonstrates the difference between the
177-
// enabled (default) and disabled state of `legacy-inlining-prevention`.
178-
// Here the two calls to `inner_opaque_loop_2()` are in different entry points
179-
// so the first call is fully analyzed (and can put the function on the "do
180-
// not inline" list) before reaching the second call.
181-
// This test uses `clang_analyzer_dump` because (as explained in an earlier
182-
// comment block) `clang_analyzer_numTimesReached` is not suitable for counting
183-
// visits from separate entry points.
184-
185-
int inner_opaque_loop_2(int arg) {
155+
int inner_opaque_loop(int callIdx) {
186156
int i;
187-
clang_analyzer_dump(arg); // default-warning {{2}}
188-
// disabled-warning@-1 {{1}} disabled-warning@-1 {{2}}
157+
clang_analyzer_dump(callIdx); // default-warning {{2 S32}}
158+
// disabled-warning@-1 {{1 S32}}
159+
// disabled-warning@-2 {{2 S32}}
189160
for (i = 0; i < getNum(); i++);
190161
return i;
191162
}
192163

193-
int outer_1_opaque_loop_2(void) {
194-
return inner_opaque_loop_2(1);
164+
int outer_1_opaque_loop(void) {
165+
return inner_opaque_loop(1);
195166
}
196167
int outer_2_opaque_loop(void) {
197-
return inner_opaque_loop_2(2);
168+
return inner_opaque_loop(2);
198169
}

0 commit comments

Comments
 (0)