xref: /llvm-project/clang/test/Analysis/plist-macros-with-expansion.cpp (revision 170c67d5b8cc58dd8a4bd0ea7c5ca02290fac39c)
1 // RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core %s  \
2 // RUN:   -analyzer-output=plist -o %t.plist \
3 // RUN:   -analyzer-config expand-macros=true -verify
4 //
5 // RUN: FileCheck --input-file=%t.plist %s
6 
7 void print(const void*);
8 
9 //===----------------------------------------------------------------------===//
10 // Tests for non-function-like macro expansions.
11 //===----------------------------------------------------------------------===//
12 
13 #define SET_PTR_VAR_TO_NULL \
14   ptr = 0
15 
nonFunctionLikeMacroTest()16 void nonFunctionLikeMacroTest() {
17   int *ptr;
18   SET_PTR_VAR_TO_NULL;
19   *ptr = 5; // expected-warning{{Dereference of null pointer}}
20 }
21 
22 // CHECK:      <key>macro_expansions</key>
23 // CHECK-NEXT: <array>
24 // CHECK-NEXT:  <dict>
25 // CHECK-NEXT:   <key>location</key>
26 // CHECK-NEXT:   <dict>
27 // CHECK-NEXT:    <key>line</key><integer>18</integer>
28 // CHECK-NEXT:    <key>col</key><integer>3</integer>
29 // CHECK-NEXT:    <key>file</key><integer>0</integer>
30 // CHECK-NEXT:   </dict>
31 // CHECK-NEXT:   <key>name</key><string>SET_PTR_VAR_TO_NULL</string>
32 // CHECK-NEXT:   <key>expansion</key><string>ptr =0</string>
33 // CHECK-NEXT:  </dict>
34 // CHECK-NEXT: </array>
35 
36 #define NULL 0
37 #define SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO \
38   ptr = NULL
39 
nonFunctionLikeNestedMacroTest()40 void nonFunctionLikeNestedMacroTest() {
41   int *ptr;
42   SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO;
43   *ptr = 5; // expected-warning{{Dereference of null pointer}}
44 }
45 
46 // CHECK:      <key>macro_expansions</key>
47 // CHECK-NEXT: <array>
48 // CHECK-NEXT:  <dict>
49 // CHECK-NEXT:   <key>location</key>
50 // CHECK-NEXT:   <dict>
51 // CHECK-NEXT:    <key>line</key><integer>42</integer>
52 // CHECK-NEXT:    <key>col</key><integer>3</integer>
53 // CHECK-NEXT:    <key>file</key><integer>0</integer>
54 // CHECK-NEXT:   </dict>
55 // CHECK-NEXT:  <key>name</key><string>SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO</string>
56 // CHECK-NEXT:  <key>expansion</key><string>ptr =0</string>
57 // CHECK-NEXT:  </dict>
58 // CHECK-NEXT: </array>
59 
60 //===----------------------------------------------------------------------===//
61 // Tests for function-like macro expansions.
62 //===----------------------------------------------------------------------===//
63 
setToNull(int ** vptr)64 void setToNull(int **vptr) {
65   *vptr = nullptr;
66 }
67 
68 #define TO_NULL(x) \
69   setToNull(x)
70 
functionLikeMacroTest()71 void functionLikeMacroTest() {
72   int *ptr;
73   TO_NULL(&ptr);
74   *ptr = 5; // expected-warning{{Dereference of null pointer}}
75 }
76 
77 // CHECK:      <key>macro_expansions</key>
78 // CHECK-NEXT: <array>
79 // CHECK-NEXT:  <dict>
80 // CHECK-NEXT:   <key>location</key>
81 // CHECK-NEXT:   <dict>
82 // CHECK-NEXT:    <key>line</key><integer>73</integer>
83 // CHECK-NEXT:    <key>col</key><integer>3</integer>
84 // CHECK-NEXT:    <key>file</key><integer>0</integer>
85 // CHECK-NEXT:   </dict>
86 // CHECK-NEXT:  <key>name</key><string>TO_NULL(&amp;ptr)</string>
87 // CHECK-NEXT:  <key>expansion</key><string>setToNull (&amp;ptr )</string>
88 // CHECK-NEXT:  </dict>
89 // CHECK-NEXT: </array>
90 
91 #define DOES_NOTHING(x) \
92   {                     \
93     int b;              \
94     b = 5;              \
95   }                     \
96   print(x)
97 
98 #define DEREF(x)   \
99   DOES_NOTHING(x); \
100   *x
101 
functionLikeNestedMacroTest()102 void functionLikeNestedMacroTest() {
103   int *a;
104   TO_NULL(&a);
105   DEREF(a) = 5; // expected-warning{{Dereference of null pointer}}
106 }
107 
108 // CHECK:      <key>macro_expansions</key>
109 // CHECK-NEXT: <array>
110 // CHECK-NEXT:  <dict>
111 // CHECK-NEXT:   <key>location</key>
112 // CHECK-NEXT:   <dict>
113 // CHECK-NEXT:    <key>line</key><integer>104</integer>
114 // CHECK-NEXT:    <key>col</key><integer>3</integer>
115 // CHECK-NEXT:    <key>file</key><integer>0</integer>
116 // CHECK-NEXT:   </dict>
117 // CHECK-NEXT:   <key>name</key><string>TO_NULL(&amp;a)</string>
118 // CHECK-NEXT:   <key>expansion</key><string>setToNull (&amp;a )</string>
119 // CHECK-NEXT:  </dict>
120 // CHECK-NEXT:  <dict>
121 // CHECK-NEXT:   <key>location</key>
122 // CHECK-NEXT:   <dict>
123 // CHECK-NEXT:    <key>line</key><integer>105</integer>
124 // CHECK-NEXT:    <key>col</key><integer>3</integer>
125 // CHECK-NEXT:    <key>file</key><integer>0</integer>
126 // CHECK-NEXT:   </dict>
127 // CHECK-NEXT:   <key>name</key><string>DEREF(a)</string>
128 // CHECK-NEXT:   <key>expansion</key><string>{int b ;b =5;}print (a );*a </string>
129 // CHECK-NEXT:  </dict>
130 // CHECK-NEXT: </array>
131 
132 //===----------------------------------------------------------------------===//
133 // Tests for undefining and/or redifining macros.
134 //===----------------------------------------------------------------------===//
135 
136 #define WILL_UNDEF_SET_NULL_TO_PTR(ptr) \
137   ptr = nullptr;
138 
undefinedMacroByTheEndOfParsingTest()139 void undefinedMacroByTheEndOfParsingTest() {
140   int *ptr;
141   WILL_UNDEF_SET_NULL_TO_PTR(ptr);
142   *ptr = 5; // expected-warning{{Dereference of null pointer}}
143 }
144 
145 #undef WILL_UNDEF_SET_NULL_TO_PTR
146 
147 // CHECK:      <key>macro_expansions</key>
148 // CHECK-NEXT: <array>
149 // CHECK-NEXT:  <dict>
150 // CHECK-NEXT:   <key>location</key>
151 // CHECK-NEXT:   <dict>
152 // CHECK-NEXT:    <key>line</key><integer>141</integer>
153 // CHECK-NEXT:    <key>col</key><integer>3</integer>
154 // CHECK-NEXT:    <key>file</key><integer>0</integer>
155 // CHECK-NEXT:   </dict>
156 // CHECK-NEXT:   <key>name</key><string>WILL_UNDEF_SET_NULL_TO_PTR(ptr)</string>
157 // CHECK-NEXT:   <key>expansion</key><string>ptr =nullptr ;</string>
158 // CHECK-NEXT:  </dict>
159 // CHECK-NEXT: </array>
160 
161 #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
162   /* Nothing */
163 #undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
164 #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \
165   ptr = nullptr;
166 
macroRedefinedMultipleTimesTest()167 void macroRedefinedMultipleTimesTest() {
168   int *ptr;
169   WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr)
170   *ptr = 5; // expected-warning{{Dereference of null pointer}}
171 }
172 
173 #undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL
174 #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr)                      \
175   print("This string shouldn't be in the plist file at all. Or anywhere, " \
176         "but here.");
177 
178 // CHECK:      <key>macro_expansions</key>
179 // CHECK-NEXT: <array>
180 // CHECK-NEXT:  <dict>
181 // CHECK-NEXT:   <key>location</key>
182 // CHECK-NEXT:   <dict>
183 // CHECK-NEXT:    <key>line</key><integer>169</integer>
184 // CHECK-NEXT:    <key>col</key><integer>3</integer>
185 // CHECK-NEXT:    <key>file</key><integer>0</integer>
186 // CHECK-NEXT:   </dict>
187 // CHECK-NEXT:   <key>name</key><string>WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr)</string>
188 // CHECK-NEXT:   <key>expansion</key><string>ptr =nullptr ;</string>
189 // CHECK-NEXT:  </dict>
190 // CHECK-NEXT: </array>
191 
192 #define WILL_UNDEF_SET_NULL_TO_PTR_2(ptr) \
193   ptr = nullptr;
194 
195 #define PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr) \
196   WILL_UNDEF_SET_NULL_TO_PTR_2(ptr)
197 
undefinedMacroInsideAnotherMacroTest()198 void undefinedMacroInsideAnotherMacroTest() {
199   int *ptr;
200   PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr);
201   *ptr = 5; // expected-warning{{Dereference of null pointer}}
202 }
203 
204 // CHECK:      <key>macro_expansions</key>
205 // CHECK-NEXT: <array>
206 // CHECK-NEXT:  <dict>
207 // CHECK-NEXT:   <key>location</key>
208 // CHECK-NEXT:   <dict>
209 // CHECK-NEXT:    <key>line</key><integer>200</integer>
210 // CHECK-NEXT:    <key>col</key><integer>3</integer>
211 // CHECK-NEXT:    <key>file</key><integer>0</integer>
212 // CHECK-NEXT:   </dict>
213 // CHECK-NEXT:   <key>name</key><string>PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr)</string>
214 // CHECK-NEXT:   <key>expansion</key><string>ptr =nullptr ;</string>
215 // CHECK-NEXT:  </dict>
216 // CHECK-NEXT: </array>
217 
218 #undef WILL_UNDEF_SET_NULL_TO_PTR_2
219 
220 //===----------------------------------------------------------------------===//
221 // Tests for macro arguments containing commas and parantheses.
222 //
223 // As of writing these tests, the algorithm expands macro arguments by lexing
224 // the macro's expansion location, and relies on finding tok::comma and
225 // tok::l_paren/tok::r_paren.
226 //===----------------------------------------------------------------------===//
227 
228 // Note that this commas, parantheses in strings aren't parsed as tok::comma or
229 // tok::l_paren/tok::r_paren, but why not test them.
230 
231 #define TO_NULL_AND_PRINT(x, str) \
232   x = 0; \
233   print(str)
234 
macroArgContainsCommaInStringTest()235 void macroArgContainsCommaInStringTest() {
236   int *a;
237   TO_NULL_AND_PRINT(a, "Will this , cause a crash?");
238   *a = 5; // expected-warning{{Dereference of null pointer}}
239 }
240 
241 // CHECK:      <key>macro_expansions</key>
242 // CHECK-NEXT: <array>
243 // CHECK-NEXT:  <dict>
244 // CHECK-NEXT:   <key>location</key>
245 // CHECK-NEXT:   <dict>
246 // CHECK-NEXT:    <key>line</key><integer>237</integer>
247 // CHECK-NEXT:    <key>col</key><integer>3</integer>
248 // CHECK-NEXT:    <key>file</key><integer>0</integer>
249 // CHECK-NEXT:   </dict>
250 // CHECK-NEXT:   <key>name</key><string>TO_NULL_AND_PRINT(a, &quot;Will this , cause a crash?&quot;)</string>
251 // CHECK-NEXT:   <key>expansion</key><string>a =0;print (&quot;Will this , cause a crash?&quot;)</string>
252 // CHECK-NEXT:  </dict>
253 // CHECK-NEXT: </array>
254 
macroArgContainsLParenInStringTest()255 void macroArgContainsLParenInStringTest() {
256   int *a;
257   TO_NULL_AND_PRINT(a, "Will this ( cause a crash?");
258   *a = 5; // expected-warning{{Dereference of null pointer}}
259 }
260 
261 // CHECK:      <key>macro_expansions</key>
262 // CHECK-NEXT: <array>
263 // CHECK-NEXT:  <dict>
264 // CHECK-NEXT:   <key>location</key>
265 // CHECK-NEXT:   <dict>
266 // CHECK-NEXT:    <key>line</key><integer>257</integer>
267 // CHECK-NEXT:    <key>col</key><integer>3</integer>
268 // CHECK-NEXT:    <key>file</key><integer>0</integer>
269 // CHECK-NEXT:   </dict>
270 // CHECK-NEXT:   <key>name</key><string>TO_NULL_AND_PRINT(a, &quot;Will this ( cause a crash?&quot;)</string>
271 // CHECK-NEXT:   <key>expansion</key><string>a =0;print (&quot;Will this ( cause a crash?&quot;)</string>
272 // CHECK-NEXT:  </dict>
273 // CHECK-NEXT: </array>
274 
macroArgContainsRParenInStringTest()275 void macroArgContainsRParenInStringTest() {
276   int *a;
277   TO_NULL_AND_PRINT(a, "Will this ) cause a crash?");
278   *a = 5; // expected-warning{{Dereference of null pointer}}
279 }
280 
281 // CHECK:      <key>macro_expansions</key>
282 // CHECK-NEXT: <array>
283 // CHECK-NEXT:  <dict>
284 // CHECK-NEXT:   <key>location</key>
285 // CHECK-NEXT:   <dict>
286 // CHECK-NEXT:    <key>line</key><integer>277</integer>
287 // CHECK-NEXT:    <key>col</key><integer>3</integer>
288 // CHECK-NEXT:    <key>file</key><integer>0</integer>
289 // CHECK-NEXT:   </dict>
290 // CHECK-NEXT:   <key>name</key><string>TO_NULL_AND_PRINT(a, &quot;Will this ) cause a crash?&quot;)</string>
291 // CHECK-NEXT:   <key>expansion</key><string>a =0;print (&quot;Will this ) cause a crash?&quot;)</string>
292 // CHECK-NEXT:  </dict>
293 // CHECK-NEXT: </array>
294 
295 #define CALL_FUNCTION(funcCall)   \
296   funcCall
297 
298 // Function calls do contain both tok::comma and tok::l_paren/tok::r_paren.
299 
macroArgContainsLParenRParenTest()300 void macroArgContainsLParenRParenTest() {
301   int *a;
302   CALL_FUNCTION(setToNull(&a));
303   *a = 5; // expected-warning{{Dereference of null pointer}}
304 }
305 
306 // CHECK:      <key>macro_expansions</key>
307 // CHECK-NEXT: <array>
308 // CHECK-NEXT:  <dict>
309 // CHECK-NEXT:   <key>location</key>
310 // CHECK-NEXT:   <dict>
311 // CHECK-NEXT:    <key>line</key><integer>302</integer>
312 // CHECK-NEXT:    <key>col</key><integer>3</integer>
313 // CHECK-NEXT:    <key>file</key><integer>0</integer>
314 // CHECK-NEXT:   </dict>
315 // CHECK-NEXT:   <key>name</key><string>CALL_FUNCTION(setToNull(&amp;a))</string>
316 // CHECK-NEXT:   <key>expansion</key><string>setToNull (&amp;a )</string>
317 // CHECK-NEXT:  </dict>
318 // CHECK-NEXT: </array>
319 
setToNullAndPrint(int ** vptr,const char * str)320 void setToNullAndPrint(int **vptr, const char *str) {
321   setToNull(vptr);
322   print(str);
323 }
324 
macroArgContainsCommaLParenRParenTest()325 void macroArgContainsCommaLParenRParenTest() {
326   int *a;
327   CALL_FUNCTION(setToNullAndPrint(&a, "Hello!"));
328   *a = 5; // expected-warning{{Dereference of null pointer}}
329 }
330 
331 // CHECK:      <key>macro_expansions</key>
332 // CHECK-NEXT: <array>
333 // CHECK-NEXT:  <dict>
334 // CHECK-NEXT:   <key>location</key>
335 // CHECK-NEXT:   <dict>
336 // CHECK-NEXT:    <key>line</key><integer>327</integer>
337 // CHECK-NEXT:    <key>col</key><integer>3</integer>
338 // CHECK-NEXT:    <key>file</key><integer>0</integer>
339 // CHECK-NEXT:   </dict>
340 // CHECK-NEXT:   <key>name</key><string>CALL_FUNCTION(setToNullAndPrint(&amp;a, &quot;Hello!&quot;))</string>
341 // CHECK-NEXT:   <key>expansion</key><string>setToNullAndPrint (&amp;a ,&quot;Hello!&quot;)</string>
342 // CHECK-NEXT:  </dict>
343 // CHECK-NEXT: </array>
344 
345 #define CALL_FUNCTION_WITH_TWO_PARAMS(funcCall, param1, param2) \
346   funcCall(param1, param2)
347 
macroArgContainsCommaLParenRParenTest2()348 void macroArgContainsCommaLParenRParenTest2() {
349   int *a;
350   CALL_FUNCTION_WITH_TWO_PARAMS(setToNullAndPrint, &a, "Hello!");
351   *a = 5; // expected-warning{{Dereference of null pointer}}
352 }
353 
354 // CHECK:      <key>macro_expansions</key>
355 // CHECK-NEXT: <array>
356 // CHECK-NEXT:  <dict>
357 // CHECK-NEXT:   <key>location</key>
358 // CHECK-NEXT:   <dict>
359 // CHECK-NEXT:    <key>line</key><integer>350</integer>
360 // CHECK-NEXT:    <key>col</key><integer>3</integer>
361 // CHECK-NEXT:    <key>file</key><integer>0</integer>
362 // CHECK-NEXT:   </dict>
363 // CHECK-NEXT:   <key>name</key><string>CALL_FUNCTION_WITH_TWO_PARAMS(setToNullAndPrint, &amp;a, &quot;Hello!&quot;)</string>
364 // CHECK-NEXT:   <key>expansion</key><string>setToNullAndPrint (&amp;a ,&quot;Hello!&quot;)</string>
365 // CHECK-NEXT:  </dict>
366 // CHECK-NEXT: </array>
367 
368 #define CALL_LAMBDA(l) \
369   l()
370 
commaInBracketsTest()371 void commaInBracketsTest() {
372   int *ptr;
373   const char str[] = "Hello!";
374   // You need to add parantheses around a lambda expression to compile this,
375   // else the comma in the capture will be parsed as divider of macro args.
376   CALL_LAMBDA(([&ptr, str] () mutable { TO_NULL(&ptr); }));
377   *ptr = 5; // expected-warning{{Dereference of null pointer}}
378 }
379 // FIXME: Why does the expansion appear twice?
380 // CHECK:      <key>macro_expansions</key>
381 // CHECK-NEXT: <array>
382 // CHECK-NEXT:  <dict>
383 // CHECK-NEXT:   <key>location</key>
384 // CHECK-NEXT:   <dict>
385 // CHECK-NEXT:    <key>line</key><integer>376</integer>
386 // CHECK-NEXT:    <key>col</key><integer>3</integer>
387 // CHECK-NEXT:    <key>file</key><integer>0</integer>
388 // CHECK-NEXT:   </dict>
389 // CHECK-NEXT:   <key>name</key><string>CALL_LAMBDA(([&amp;ptr, str] () mutable { TO_NULL(&amp;ptr); }))</string>
390 // CHECK-NEXT:   <key>expansion</key><string>([&amp;ptr ,str ]()mutable {setToNull (&amp;ptr );})()</string>
391 // CHECK-NEXT:  </dict>
392 // CHECK-NEXT:  <dict>
393 // CHECK-NEXT:   <key>location</key>
394 // CHECK-NEXT:   <dict>
395 // CHECK-NEXT:    <key>line</key><integer>376</integer>
396 // CHECK-NEXT:    <key>col</key><integer>3</integer>
397 // CHECK-NEXT:    <key>file</key><integer>0</integer>
398 // CHECK-NEXT:   </dict>
399 // CHECK-NEXT:   <key>name</key><string>CALL_LAMBDA(([&amp;ptr, str] () mutable { TO_NULL(&amp;ptr); }))</string>
400 // CHECK-NEXT:   <key>expansion</key><string>([&amp;ptr ,str ]()mutable {setToNull (&amp;ptr );})()</string>
401 // CHECK-NEXT:  </dict>
402 // CHECK-NEXT: </array>
403 
404 #define PASTE_CODE(code) \
405   code
406 
commaInBracesTest()407 void commaInBracesTest() {
408   PASTE_CODE({ // expected-warning{{Dereference of null pointer}}
409     // NOTE: If we were to add a new variable here after a comma, we'd get a
410     // compilation error, so this test is mainly here to show that this was also
411     // investigated.
412     //
413     // int *ptr = nullptr, a;
414     int *ptr = nullptr;
415     *ptr = 5;
416   })
417 }
418 
419 // CHECK:        <key>macro_expansions</key>
420 // CHECK-NEXT:   <array>
421 // CHECK-NEXT:    <dict>
422 // CHECK-NEXT:     <key>location</key>
423 // CHECK-NEXT:     <dict>
424 // CHECK-NEXT:      <key>line</key><integer>408</integer>
425 // CHECK-NEXT:      <key>col</key><integer>3</integer>
426 // CHECK-NEXT:      <key>file</key><integer>0</integer>
427 // CHECK-NEXT:     </dict>
428 // CHECK-NEXT:     <key>name</key><string>PASTE_CODE({ // expected-
429 // CHECK-NEXT:    // NOTE: If we were to add a new variable here after a comma, we&apos;d get a
430 // CHECK-NEXT:    // compilation error, so this test is mainly here to show that this was also
431 // CHECK-NEXT:    // investigated.
432 // CHECK-NEXT:    //
433 // CHECK-NEXT:    // int *ptr = nullptr, a;
434 // CHECK-NEXT:    int *ptr = nullptr;
435 // CHECK-NEXT:    *ptr = 5;
436 // CHECK-NEXT:  })</string>
437 // CHECK-NEXT:     <key>expansion</key><string>{int *ptr =nullptr ;*ptr =5;}</string>
438 // CHECK-NEXT:    </dict>
439 // CHECK-NEXT:   </array>
440 
441 // Example taken from
442 // https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html#Macro-Arguments.
443 
444 #define POTENTIALLY_EMPTY_PARAM(x, y) \
445   x;                                  \
446   y = nullptr
447 
emptyParamTest()448 void emptyParamTest() {
449   int *ptr;
450 
451   POTENTIALLY_EMPTY_PARAM(,ptr);
452   *ptr = 5; // expected-warning{{Dereference of null pointer}}
453 }
454 
455 // CHECK:      <key>macro_expansions</key>
456 // CHECK-NEXT: <array>
457 // CHECK-NEXT:  <dict>
458 // CHECK-NEXT:   <key>location</key>
459 // CHECK-NEXT:   <dict>
460 // CHECK-NEXT:    <key>line</key><integer>451</integer>
461 // CHECK-NEXT:    <key>col</key><integer>3</integer>
462 // CHECK-NEXT:    <key>file</key><integer>0</integer>
463 // CHECK-NEXT:   </dict>
464 // CHECK-NEXT:   <key>name</key><string>POTENTIALLY_EMPTY_PARAM(,ptr)</string>
465 // CHECK-NEXT:   <key>expansion</key><string>;ptr =nullptr </string>
466 // CHECK-NEXT:  </dict>
467 // CHECK-NEXT: </array>
468 
469 #define NESTED_EMPTY_PARAM(a, b) \
470   POTENTIALLY_EMPTY_PARAM(a, b);
471 
472 
nestedEmptyParamTest()473 void nestedEmptyParamTest() {
474   int *ptr;
475 
476   NESTED_EMPTY_PARAM(, ptr);
477   *ptr = 5; // expected-warning{{Dereference of null pointer}}
478 }
479 
480 // CHECK:      <key>macro_expansions</key>
481 // CHECK-NEXT: <array>
482 // CHECK-NEXT:  <dict>
483 // CHECK-NEXT:   <key>location</key>
484 // CHECK-NEXT:   <dict>
485 // CHECK-NEXT:    <key>line</key><integer>476</integer>
486 // CHECK-NEXT:    <key>col</key><integer>3</integer>
487 // CHECK-NEXT:    <key>file</key><integer>0</integer>
488 // CHECK-NEXT:   </dict>
489 // CHECK-NEXT:   <key>name</key><string>NESTED_EMPTY_PARAM(, ptr)</string>
490 // CHECK-NEXT:   <key>expansion</key><string>;ptr =nullptr ;</string>
491 // CHECK-NEXT:  </dict>
492 // CHECK-NEXT: </array>
493 
494 #define CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(func, param) \
495   CALL_FUNCTION(func(param))
496 
lParenRParenInNestedMacro()497 void lParenRParenInNestedMacro() {
498   int *ptr;
499   CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(setToNull, &ptr);
500   *ptr = 5; // expected-warning{{Dereference of null pointer}}
501 }
502 
503 // CHECK:      <key>macro_expansions</key>
504 // CHECK-NEXT: <array>
505 // CHECK-NEXT:  <dict>
506 // CHECK-NEXT:   <key>location</key>
507 // CHECK-NEXT:   <dict>
508 // CHECK-NEXT:    <key>line</key><integer>499</integer>
509 // CHECK-NEXT:    <key>col</key><integer>3</integer>
510 // CHECK-NEXT:    <key>file</key><integer>0</integer>
511 // CHECK-NEXT:   </dict>
512 // CHECK-NEXT:   <key>name</key><string>CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(setToNull, &amp;ptr)</string>
513 // CHECK-NEXT:   <key>expansion</key><string>setToNull (&amp;ptr )</string>
514 // CHECK-NEXT:  </dict>
515 // CHECK-NEXT: </array>
516 
517 //===----------------------------------------------------------------------===//
518 // Tests for variadic macro arguments.
519 //===----------------------------------------------------------------------===//
520 
521 template <typename ...Args>
522 void variadicFunc(Args ...args);
523 
524 #define VARIADIC_SET_TO_NULL(ptr, ...) \
525   ptr = nullptr;                       \
526   variadicFunc(__VA_ARGS__)
527 
variadicMacroArgumentTest()528 void variadicMacroArgumentTest() {
529   int *ptr;
530   VARIADIC_SET_TO_NULL(ptr, 1, 5, "haha!");
531   *ptr = 5; // expected-warning{{Dereference of null pointer}}
532 }
533 
534 // CHECK:      <key>macro_expansions</key>
535 // CHECK-NEXT: <array>
536 // CHECK-NEXT:  <dict>
537 // CHECK-NEXT:   <key>location</key>
538 // CHECK-NEXT:   <dict>
539 // CHECK-NEXT:    <key>line</key><integer>530</integer>
540 // CHECK-NEXT:    <key>col</key><integer>3</integer>
541 // CHECK-NEXT:    <key>file</key><integer>0</integer>
542 // CHECK-NEXT:   </dict>
543 // CHECK-NEXT:   <key>name</key><string>VARIADIC_SET_TO_NULL(ptr, 1, 5, &quot;haha!&quot;)</string>
544 // CHECK-NEXT:   <key>expansion</key><string>ptr =nullptr ;variadicFunc (1,5,&quot;haha!&quot;)</string>
545 // CHECK-NEXT:  </dict>
546 // CHECK-NEXT: </array>
547 
variadicMacroArgumentWithoutAnyArgumentTest()548 void variadicMacroArgumentWithoutAnyArgumentTest() {
549   int *ptr;
550   // Not adding a single parameter to ... is silly (and also causes a
551   // preprocessor warning), but is not an excuse to crash on it.
552   VARIADIC_SET_TO_NULL(ptr);
553   *ptr = 5; // expected-warning{{Dereference of null pointer}}
554 }
555 
556 // CHECK:      <key>macro_expansions</key>
557 // CHECK-NEXT: <array>
558 // CHECK-NEXT:  <dict>
559 // CHECK-NEXT:   <key>location</key>
560 // CHECK-NEXT:   <dict>
561 // CHECK-NEXT:    <key>line</key><integer>552</integer>
562 // CHECK-NEXT:    <key>col</key><integer>3</integer>
563 // CHECK-NEXT:    <key>file</key><integer>0</integer>
564 // CHECK-NEXT:   </dict>
565 // CHECK-NEXT:   <key>name</key><string>VARIADIC_SET_TO_NULL(ptr)</string>
566 // CHECK-NEXT:   <key>expansion</key><string>ptr =nullptr ;variadicFunc ()</string>
567 // CHECK-NEXT:  </dict>
568 // CHECK-NEXT: </array>
569 
570 //===----------------------------------------------------------------------===//
571 // Tests for # and ##.
572 //===----------------------------------------------------------------------===//
573 
574 #define DECLARE_FUNC_AND_SET_TO_NULL(funcName, ptr) \
575   void generated_##funcName();                      \
576   ptr = nullptr;
577 
hashHashOperatorTest()578 void hashHashOperatorTest() {
579   int *ptr;
580   DECLARE_FUNC_AND_SET_TO_NULL(whatever, ptr);
581   *ptr = 5; // expected-warning{{Dereference of null pointer}}
582 }
583 
584 // CHECK:      <key>macro_expansions</key>
585 // CHECK-NEXT: <array>
586 // CHECK-NEXT:  <dict>
587 // CHECK-NEXT:   <key>location</key>
588 // CHECK-NEXT:   <dict>
589 // CHECK-NEXT:    <key>line</key><integer>580</integer>
590 // CHECK-NEXT:    <key>col</key><integer>3</integer>
591 // CHECK-NEXT:    <key>file</key><integer>0</integer>
592 // CHECK-NEXT:   </dict>
593 // CHECK-NEXT:   <key>name</key><string>DECLARE_FUNC_AND_SET_TO_NULL(whatever, ptr)</string>
594 // CHECK-NEXT:   <key>expansion</key><string>void generated_whatever ();ptr =nullptr ;</string>
595 // CHECK-NEXT:  </dict>
596 // CHECK-NEXT: </array>
597 
macroArgContainsHashHashInStringTest()598 void macroArgContainsHashHashInStringTest() {
599   int *a;
600   TO_NULL_AND_PRINT(a, "Will this ## cause a crash?");
601   *a = 5; // expected-warning{{Dereference of null pointer}}
602 }
603 
604 // CHECK:      <key>macro_expansions</key>
605 // CHECK-NEXT: <array>
606 // CHECK-NEXT:  <dict>
607 // CHECK-NEXT:   <key>location</key>
608 // CHECK-NEXT:   <dict>
609 // CHECK-NEXT:    <key>line</key><integer>600</integer>
610 // CHECK-NEXT:    <key>col</key><integer>3</integer>
611 // CHECK-NEXT:    <key>file</key><integer>0</integer>
612 // CHECK-NEXT:   </dict>
613 // CHECK-NEXT:   <key>name</key><string>TO_NULL_AND_PRINT(a, &quot;Will this ## cause a crash?&quot;)</string>
614 // CHECK-NEXT:   <key>expansion</key><string>a =0;print (&quot;Will this ## cause a crash?&quot;)</string>
615 // CHECK-NEXT:  </dict>
616 // CHECK-NEXT: </array>
617 
618 #define PRINT_STR(str, ptr) \
619   print(#str);              \
620   ptr = nullptr
621 
hashOperatorTest()622 void hashOperatorTest() {
623   int *ptr;
624   PRINT_STR(Hello, ptr);
625   *ptr = 5; // expected-warning{{Dereference of null pointer}}
626 }
627 
628 // CHECK:      <key>macro_expansions</key>
629 // CHECK-NEXT: <array>
630 // CHECK-NEXT:  <dict>
631 // CHECK-NEXT:   <key>location</key>
632 // CHECK-NEXT:   <dict>
633 // CHECK-NEXT:    <key>line</key><integer>624</integer>
634 // CHECK-NEXT:    <key>col</key><integer>3</integer>
635 // CHECK-NEXT:    <key>file</key><integer>0</integer>
636 // CHECK-NEXT:   </dict>
637 // CHECK-NEXT:   <key>name</key><string>PRINT_STR(Hello, ptr)</string>
638 // CHECK-NEXT:   <key>expansion</key><string>print (&quot;Hello&quot;);ptr =nullptr </string>
639 // CHECK-NEXT:  </dict>
640 // CHECK-NEXT: </array>
641 
macroArgContainsHashInStringTest()642 void macroArgContainsHashInStringTest() {
643   int *a;
644   TO_NULL_AND_PRINT(a, "Will this # cause a crash?");
645   *a = 5; // expected-warning{{Dereference of null pointer}}
646 }
647 
648 // CHECK:      <key>macro_expansions</key>
649 // CHECK-NEXT: <array>
650 // CHECK-NEXT:  <dict>
651 // CHECK-NEXT:   <key>location</key>
652 // CHECK-NEXT:   <dict>
653 // CHECK-NEXT:    <key>line</key><integer>644</integer>
654 // CHECK-NEXT:    <key>col</key><integer>3</integer>
655 // CHECK-NEXT:    <key>file</key><integer>0</integer>
656 // CHECK-NEXT:   </dict>
657 // CHECK-NEXT:   <key>name</key><string>TO_NULL_AND_PRINT(a, &quot;Will this # cause a crash?&quot;)</string>
658 // CHECK-NEXT:   <key>expansion</key><string>a =0;print (&quot;Will this # cause a crash?&quot;)</string>
659 // CHECK-NEXT:  </dict>
660 // CHECK-NEXT: </array>
661 
662 //===----------------------------------------------------------------------===//
663 // Tests for more complex macro expansions.
664 //
665 // We won't cover anything that wasn't covered up to this point, but rather
666 // show more complex, macros with deeper nesting, more arguments (some unused)
667 // and so on.
668 //===----------------------------------------------------------------------===//
669 
670 #define IF(Condition) \
671   if ( Condition )
672 
673 #define L_BRACE {
674 #define R_BRACE }
675 #define LESS <
676 #define GREATER >
677 #define EQUALS =
678 #define SEMICOLON ;
679 #define NEGATIVE -
680 #define RETURN return
681 #define ZERO 0
682 
683 #define EUCLIDEAN_ALGORITHM(A, B)                                              \
684   IF(A LESS ZERO) L_BRACE                                                      \
685     A EQUALS NEGATIVE A SEMICOLON                                              \
686   R_BRACE                                                                      \
687   IF(B LESS ZERO) L_BRACE                                                      \
688     B EQUALS NEGATIVE B SEMICOLON                                              \
689   R_BRACE                                                                      \
690                                                                                \
691   /* This is where a while loop would be, but that seems to be too complex */  \
692   /* for the analyzer just yet. Let's just pretend that this algorithm     */  \
693   /* works.                                                                */  \
694                                                                                \
695   RETURN B / (B - B) SEMICOLON
696 
getLowestCommonDenominator(int A,int B)697 int getLowestCommonDenominator(int A, int B) {
698   EUCLIDEAN_ALGORITHM(A, B) // expected-warning{{Division by zero}}
699 }
700 
testVeryComplexAlgorithm()701 void testVeryComplexAlgorithm() {
702   int tmp = 8 / (getLowestCommonDenominator(5, 7) - 1);
703   print(&tmp);
704 }
705 
706 // CHECK:      <key>macro_expansions</key>
707 // CHECK-NEXT: <array>
708 // CHECK-NEXT:  <dict>
709 // CHECK-NEXT:   <key>location</key>
710 // CHECK-NEXT:   <dict>
711 // CHECK-NEXT:    <key>line</key><integer>698</integer>
712 // CHECK-NEXT:    <key>col</key><integer>3</integer>
713 // CHECK-NEXT:    <key>file</key><integer>0</integer>
714 // CHECK-NEXT:   </dict>
715 // CHECK-NEXT:   <key>name</key><string>EUCLIDEAN_ALGORITHM(A, B)</string>
716 // CHECK-NEXT:   <key>expansion</key><string>if (A &lt;0){A =-A ;}if (B &lt;0){B =-B ;}return B /(B -B );</string>
717 // CHECK-NEXT:  </dict>
718 // CHECK-NEXT: </array>
719 
720 #define YET_ANOTHER_SET_TO_NULL(x, y, z)   \
721   print((void *) x);                       \
722   print((void *) y);                       \
723   z = nullptr;
724 
725 #define DO_NOTHING(str) str
726 #define DO_NOTHING2(str2) DO_NOTHING(str2)
727 
test()728 void test() {
729   int *ptr;
730   YET_ANOTHER_SET_TO_NULL(5, DO_NOTHING2("Remember the Vasa"), ptr);
731   *ptr = 5; // expected-warning{{Dereference of null pointer}}
732 }
733 
734 // CHECK:      <key>macro_expansions</key>
735 // CHECK-NEXT: <array>
736 // CHECK-NEXT:  <dict>
737 // CHECK-NEXT:   <key>location</key>
738 // CHECK-NEXT:   <dict>
739 // CHECK-NEXT:    <key>line</key><integer>730</integer>
740 // CHECK-NEXT:    <key>col</key><integer>3</integer>
741 // CHECK-NEXT:    <key>file</key><integer>0</integer>
742 // CHECK-NEXT:   </dict>
743 // CHECK-NEXT:   <key>name</key><string>YET_ANOTHER_SET_TO_NULL(5, DO_NOTHING2(&quot;Remember the Vasa&quot;), ptr)</string>
744 // CHECK-NEXT:   <key>expansion</key><string>print ((void *)5);print ((void *)&quot;Remember the Vasa&quot;);ptr =nullptr ;</string>
745 // CHECK-NEXT:  </dict>
746 // CHECK-NEXT: </array>
747 
748 int garbage_value;
749 
750 #define REC_MACRO_FUNC(REC_MACRO_PARAM) garbage_##REC_MACRO_PARAM
751 #define value REC_MACRO_FUNC(value)
752 
recursiveMacroUser()753 void recursiveMacroUser() {
754   if (value == 0)
755     1 / value; // expected-warning{{Division by zero}}
756                // expected-warning@-1{{expression result unused}}
757 }
758 
759 // CHECK:      <key>macro_expansions</key>
760 // CHECK-NEXT: <array>
761 // CHECK-NEXT:  <dict>
762 // CHECK-NEXT:   <key>location</key>
763 // CHECK-NEXT:   <dict>
764 // CHECK-NEXT:    <key>line</key><integer>754</integer>
765 // CHECK-NEXT:    <key>col</key><integer>7</integer>
766 // CHECK-NEXT:    <key>file</key><integer>0</integer>
767 // CHECK-NEXT:   </dict>
768 // CHECK-NEXT:   <key>name</key><string>value</string>
769 // CHECK-NEXT:   <key>expansion</key><string>garbage_value </string>
770 // CHECK-NEXT:  </dict>
771 // CHECK-NEXT: </array>
772 
773 #define FOO(x) int foo() { return x; }
774 #define APPLY_ZERO1(function) function(0)
775 
APPLY_ZERO1(FOO)776 APPLY_ZERO1(FOO)
777 void useZeroApplier1() { (void)(1 / foo()); } // expected-warning{{Division by zero}}
778 
779 // CHECK:      <key>macro_expansions</key>
780 // CHECK-NEXT: <array>
781 // CHECK-NEXT:  <dict>
782 // CHECK-NEXT:   <key>location</key>
783 // CHECK-NEXT:   <dict>
784 // CHECK-NEXT:    <key>line</key><integer>776</integer>
785 // CHECK-NEXT:    <key>col</key><integer>1</integer>
786 // CHECK-NEXT:    <key>file</key><integer>0</integer>
787 // CHECK-NEXT:   </dict>
788 // CHECK-NEXT:   <key>name</key><string>APPLY_ZERO1(FOO)</string>
789 // CHECK-NEXT:   <key>expansion</key><string>int foo (){return 0;}</string>
790 // CHECK-NEXT:  </dict>
791 // CHECK-NEXT: </array>
792 
793 #define BAR(x) int bar() { return x; }
794 #define APPLY_ZERO2 BAR(0)
795 
796 APPLY_ZERO2
useZeroApplier2()797 void useZeroApplier2() { (void)(1 / bar()); } // expected-warning{{Division by zero}}
798 
799 // CHECK:      <key>macro_expansions</key>
800 // CHECK-NEXT: <array>
801 // CHECK-NEXT:  <dict>
802 // CHECK-NEXT:   <key>location</key>
803 // CHECK-NEXT:   <dict>
804 // CHECK-NEXT:    <key>line</key><integer>796</integer>
805 // CHECK-NEXT:    <key>col</key><integer>1</integer>
806 // CHECK-NEXT:    <key>file</key><integer>0</integer>
807 // CHECK-NEXT:   </dict>
808 // CHECK-NEXT:   <key>name</key><string>APPLY_ZERO2</string>
809 // CHECK-NEXT:   <key>expansion</key><string>int bar (){return 0;}</string>
810 // CHECK-NEXT:  </dict>
811 // CHECK-NEXT: </array>
812 
813 void foo(int &x, const char *str);
814 
815 #define PARAMS_RESOLVE_TO_VA_ARGS(i, fmt) foo(i, fmt); \
816   i = 0;
817 #define DISPATCH(...) PARAMS_RESOLVE_TO_VA_ARGS(__VA_ARGS__);
818 
mulitpleParamsResolveToVA_ARGS(void)819 void mulitpleParamsResolveToVA_ARGS(void) {
820   int x = 1;
821   DISPATCH(x, "LF1M healer");
822   (void)(10 / x); // expected-warning{{Division by zero}}
823 }
824 
825 // CHECK:      <key>macro_expansions</key>
826 // CHECK-NEXT: <array>
827 // CHECK-NEXT:  <dict>
828 // CHECK-NEXT:   <key>location</key>
829 // CHECK-NEXT:   <dict>
830 // CHECK-NEXT:    <key>line</key><integer>821</integer>
831 // CHECK-NEXT:    <key>col</key><integer>3</integer>
832 // CHECK-NEXT:    <key>file</key><integer>0</integer>
833 // CHECK-NEXT:   </dict>
834 // CHECK-NEXT:   <key>name</key><string>DISPATCH(x, &quot;LF1M healer&quot;)</string>
835 // CHECK-NEXT:   <key>expansion</key><string>foo (x ,&quot;LF1M healer&quot;);x =0;;</string>
836 // CHECK-NEXT:  </dict>
837 // CHECK-NEXT: </array>
838 
839 void variadicCFunction(int &x, const char *str, ...);
840 
841 #define CONCAT_VA_ARGS(i, fmt, ...) variadicCFunction(i, fmt, ##__VA_ARGS__); \
842   i = 0;
843 
concatVA_ARGS(void)844 void concatVA_ARGS(void) {
845   int x = 1;
846   CONCAT_VA_ARGS(x, "You need to construct additional pylons.", 'c', 9);
847   (void)(10 / x); // expected-warning{{Division by zero}}
848 }
849 
850 // CHECK:      <key>macro_expansions</key>
851 // CHECK-NEXT: <array>
852 // CHECK-NEXT:  <dict>
853 // CHECK-NEXT:   <key>location</key>
854 // CHECK-NEXT:   <dict>
855 // CHECK-NEXT:    <key>line</key><integer>846</integer>
856 // CHECK-NEXT:    <key>col</key><integer>3</integer>
857 // CHECK-NEXT:    <key>file</key><integer>0</integer>
858 // CHECK-NEXT:   </dict>
859 // CHECK-NEXT:   <key>name</key><string>CONCAT_VA_ARGS(x, &quot;You need to construct additional pylons.&quot;, &apos;c&apos;, 9)</string>
860 // CHECK-NEXT:   <key>expansion</key><string>variadicCFunction (x ,&quot;You need to construct additional pylons.&quot;,&apos;c&apos;,9);x =0;</string>
861 // CHECK-NEXT:  </dict>
862 // CHECK-NEXT: </array>
863 
concatVA_ARGSEmpty(void)864 void concatVA_ARGSEmpty(void) {
865   int x = 1;
866   CONCAT_VA_ARGS(x, "You need to construct");
867   (void)(10 / x); // expected-warning{{Division by zero}}
868 }
869 
870 // CHECK:      <key>macro_expansions</key>
871 // CHECK-NEXT: <array>
872 // CHECK-NEXT:  <dict>
873 // CHECK-NEXT:   <key>location</key>
874 // CHECK-NEXT:   <dict>
875 // CHECK-NEXT:    <key>line</key><integer>866</integer>
876 // CHECK-NEXT:    <key>col</key><integer>3</integer>
877 // CHECK-NEXT:    <key>file</key><integer>0</integer>
878 // CHECK-NEXT:   </dict>
879 // CHECK-NEXT:   <key>name</key><string>CONCAT_VA_ARGS(x, &quot;You need to construct&quot;)</string>
880 // CHECK-NEXT:   <key>expansion</key><string>variadicCFunction (x ,&quot;You need to construct&quot;);x =0;</string>
881 // CHECK-NEXT:  </dict>
882 // CHECK-NEXT: </array>
883 
884 #define STRINGIFIED_VA_ARGS(i, fmt, ...) variadicCFunction(i, fmt, #__VA_ARGS__); \
885   i = 0;
886 
stringifyVA_ARGS(void)887 void stringifyVA_ARGS(void) {
888   int x = 1;
889   STRINGIFIED_VA_ARGS(x, "Additional supply depots required.", 'a', 10);
890   (void)(10 / x); // expected-warning{{Division by zero}}
891 }
892 
893 // CHECK:      <key>macro_expansions</key>
894 // CHECK-NEXT: <array>
895 // CHECK-NEXT:  <dict>
896 // CHECK-NEXT:   <key>location</key>
897 // CHECK-NEXT:   <dict>
898 // CHECK-NEXT:    <key>line</key><integer>889</integer>
899 // CHECK-NEXT:    <key>col</key><integer>3</integer>
900 // CHECK-NEXT:    <key>file</key><integer>0</integer>
901 // CHECK-NEXT:   </dict>
902 // CHECK-NEXT:   <key>name</key><string>STRINGIFIED_VA_ARGS(x, &quot;Additional supply depots required.&quot;, &apos;a&apos;, 10)</string>
903 // CHECK-NEXT:   <key>expansion</key><string>variadicCFunction (x ,&quot;Additional supply depots required.&quot;,&quot;&apos;a&apos;, 10&quot;);x =0;</string>
904 // CHECK-NEXT:  </dict>
905 // CHECK-NEXT: </array>
906 
stringifyVA_ARGSEmpty(void)907 void stringifyVA_ARGSEmpty(void) {
908   int x = 1;
909   STRINGIFIED_VA_ARGS(x, "Additional supply depots required.");
910   (void)(10 / x); // expected-warning{{Division by zero}}
911 }
912 
913 // CHECK:      <key>macro_expansions</key>
914 // CHECK-NEXT: <array>
915 // CHECK-NEXT:  <dict>
916 // CHECK-NEXT:   <key>location</key>
917 // CHECK-NEXT:   <dict>
918 // CHECK-NEXT:    <key>line</key><integer>909</integer>
919 // CHECK-NEXT:    <key>col</key><integer>3</integer>
920 // CHECK-NEXT:    <key>file</key><integer>0</integer>
921 // CHECK-NEXT:   </dict>
922 // CHECK-NEXT:   <key>name</key><string>STRINGIFIED_VA_ARGS(x, &quot;Additional supply depots required.&quot;)</string>
923 // CHECK-NEXT:   <key>expansion</key><string>variadicCFunction (x ,&quot;Additional supply depots required.&quot;,&quot;&quot;);x =0;</string>
924 // CHECK-NEXT:  </dict>
925 // CHECK-NEXT: </array>
926 
927 // bz44493: Support GNU-style named variadic arguments in plister
928 #define BZ44493_GNUVA(i, args...)  --(i);
929 
bz44493(void)930 int bz44493(void) {
931   int a = 2;
932   BZ44493_GNUVA(a);
933   BZ44493_GNUVA(a, "arg2");
934   (void)(10 / a); // expected-warning{{Division by zero}}
935   return 0;
936 }
937 
938 // CHECK:      <key>macro_expansions</key>
939 // CHECK-NEXT: <array>
940 // CHECK-NEXT:  <dict>
941 // CHECK-NEXT:   <key>location</key>
942 // CHECK-NEXT:   <dict>
943 // CHECK-NEXT:    <key>line</key><integer>933</integer>
944 // CHECK-NEXT:    <key>col</key><integer>3</integer>
945 // CHECK-NEXT:    <key>file</key><integer>0</integer>
946 // CHECK-NEXT:   </dict>
947 // CHECK-NEXT:   <key>name</key><string>BZ44493_GNUVA(a, &quot;arg2&quot;)</string>
948 // CHECK-NEXT:   <key>expansion</key><string>--(a );</string>
949 // CHECK-NEXT:  </dict>
950 // CHECK-NEXT: </array>
951