Kristof Umann | 7d6d9eb | 2018-10-31 14:54:27 +0000 | [diff] [blame] | 1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s |
| 2 | // |
| 3 | // RUN: %clang_analyze_cc1 -analyzer-checker=core %s \ |
| 4 | // RUN: -analyzer-output=plist -o %t.plist \ |
| 5 | // RUN: -analyzer-config expand-macros=true |
| 6 | // |
| 7 | // Check the actual plist output. |
| 8 | // RUN: cat %t.plist | %diff_plist \ |
George Karpenkov | 363dd8e | 2019-01-10 18:15:44 +0000 | [diff] [blame] | 9 | // RUN: %S/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist - |
Kristof Umann | 7d6d9eb | 2018-10-31 14:54:27 +0000 | [diff] [blame] | 10 | // |
| 11 | // Check the macro expansions from the plist output here, to make the test more |
| 12 | // understandable. |
| 13 | // RUN: FileCheck --input-file=%t.plist %s |
| 14 | |
| 15 | void print(const void*); |
| 16 | |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | // Tests for non-function-like macro expansions. |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | |
| 21 | #define SET_PTR_VAR_TO_NULL \ |
| 22 | ptr = 0 |
| 23 | |
| 24 | void nonFunctionLikeMacroTest() { |
| 25 | int *ptr; |
| 26 | SET_PTR_VAR_TO_NULL; |
| 27 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 28 | } |
| 29 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 30 | // CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL</string> |
| 31 | // CHECK-NEXT: <key>expansion</key><string>ptr = 0</string> |
Kristof Umann | 7d6d9eb | 2018-10-31 14:54:27 +0000 | [diff] [blame] | 32 | |
| 33 | #define NULL 0 |
| 34 | #define SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO \ |
| 35 | ptr = NULL |
| 36 | |
| 37 | void nonFunctionLikeNestedMacroTest() { |
| 38 | int *ptr; |
| 39 | SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO; |
| 40 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 41 | } |
| 42 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 43 | // CHECK: <key>name</key><string>SET_PTR_VAR_TO_NULL_WITH_NESTED_MACRO</string> |
| 44 | // CHECK-NEXT: <key>expansion</key><string>ptr =0</string> |
| 45 | |
| 46 | //===----------------------------------------------------------------------===// |
| 47 | // Tests for function-like macro expansions. |
| 48 | //===----------------------------------------------------------------------===// |
| 49 | |
| 50 | void setToNull(int **vptr) { |
| 51 | *vptr = nullptr; |
| 52 | } |
| 53 | |
| 54 | #define TO_NULL(x) \ |
| 55 | setToNull(x) |
| 56 | |
| 57 | void functionLikeMacroTest() { |
| 58 | int *ptr; |
| 59 | TO_NULL(&ptr); |
| 60 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 61 | } |
| 62 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 63 | // CHECK: <key>name</key><string>TO_NULL</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 64 | // CHECK-NEXT: <key>expansion</key><string>setToNull(&ptr)</string> |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 65 | |
| 66 | #define DOES_NOTHING(x) \ |
| 67 | { \ |
| 68 | int b; \ |
| 69 | b = 5; \ |
| 70 | } \ |
| 71 | print(x) |
| 72 | |
| 73 | #define DEREF(x) \ |
| 74 | DOES_NOTHING(x); \ |
| 75 | *x |
| 76 | |
| 77 | void functionLikeNestedMacroTest() { |
| 78 | int *a; |
| 79 | TO_NULL(&a); |
| 80 | DEREF(a) = 5; // expected-warning{{Dereference of null pointer}} |
| 81 | } |
| 82 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 83 | // CHECK: <key>name</key><string>TO_NULL</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 84 | // CHECK-NEXT: <key>expansion</key><string>setToNull(&a)</string> |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 85 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 86 | // CHECK: <key>name</key><string>DEREF</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 87 | // CHECK-NEXT: <key>expansion</key><string>{ int b; b = 5; } print(a); *a</string> |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 88 | |
| 89 | //===----------------------------------------------------------------------===// |
| 90 | // Tests for undefining and/or redifining macros. |
| 91 | //===----------------------------------------------------------------------===// |
| 92 | |
| 93 | #define WILL_UNDEF_SET_NULL_TO_PTR(ptr) \ |
| 94 | ptr = nullptr; |
| 95 | |
| 96 | void undefinedMacroByTheEndOfParsingTest() { |
| 97 | int *ptr; |
| 98 | WILL_UNDEF_SET_NULL_TO_PTR(ptr); |
| 99 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 100 | } |
| 101 | |
| 102 | #undef WILL_UNDEF_SET_NULL_TO_PTR |
| 103 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 104 | // CHECK: <key>name</key><string>WILL_UNDEF_SET_NULL_TO_PTR</string> |
| 105 | // CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string> |
| 106 | |
| 107 | #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \ |
| 108 | /* Nothing */ |
| 109 | #undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL |
| 110 | #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \ |
| 111 | ptr = nullptr; |
| 112 | |
| 113 | void macroRedefinedMultipleTimesTest() { |
| 114 | int *ptr; |
| 115 | WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) |
| 116 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 117 | } |
| 118 | |
| 119 | #undef WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL |
| 120 | #define WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL(ptr) \ |
| 121 | print("This string shouldn't be in the plist file at all. Or anywhere, " \ |
| 122 | "but here."); |
| 123 | |
Kristof Umann | 3800257 | 2018-11-05 02:14:36 +0000 | [diff] [blame] | 124 | // CHECK: <key>name</key><string>WILL_REDIFINE_MULTIPLE_TIMES_SET_TO_NULL</string> |
| 125 | // CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string> |
| 126 | |
| 127 | #define WILL_UNDEF_SET_NULL_TO_PTR_2(ptr) \ |
| 128 | ptr = nullptr; |
| 129 | |
| 130 | #define PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr) \ |
| 131 | WILL_UNDEF_SET_NULL_TO_PTR_2(ptr) |
| 132 | |
| 133 | void undefinedMacroInsideAnotherMacroTest() { |
| 134 | int *ptr; |
| 135 | PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD(ptr); |
| 136 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 137 | } |
| 138 | |
| 139 | // TODO: Expand arguments. |
| 140 | // CHECK: <key>name</key><string>PASS_PTR_TO_MACRO_THAT_WILL_BE_UNDEFD</string> |
| 141 | // CHECK-NEXT: <key>expansion</key><string>ptr = nullptr;</string> |
| 142 | |
| 143 | #undef WILL_UNDEF_SET_NULL_TO_PTR_2 |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 144 | |
| 145 | //===----------------------------------------------------------------------===// |
| 146 | // Tests for macro arguments containing commas and parantheses. |
| 147 | // |
| 148 | // As of writing these tests, the algorithm expands macro arguments by lexing |
| 149 | // the macro's expansion location, and relies on finding tok::comma and |
| 150 | // tok::l_paren/tok::r_paren. |
| 151 | //===----------------------------------------------------------------------===// |
| 152 | |
| 153 | // Note that this commas, parantheses in strings aren't parsed as tok::comma or |
| 154 | // tok::l_paren/tok::r_paren, but why not test them. |
| 155 | |
| 156 | #define TO_NULL_AND_PRINT(x, str) \ |
| 157 | x = 0; \ |
| 158 | print(str) |
| 159 | |
| 160 | void macroArgContainsCommaInStringTest() { |
| 161 | int *a; |
| 162 | TO_NULL_AND_PRINT(a, "Will this , cause a crash?"); |
| 163 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 164 | } |
| 165 | |
| 166 | // CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string> |
| 167 | // CHECK-NEXT: <key>expansion</key><string>a = 0; print( "Will this , cause a crash?")</string> |
| 168 | |
| 169 | void macroArgContainsLParenInStringTest() { |
| 170 | int *a; |
| 171 | TO_NULL_AND_PRINT(a, "Will this ( cause a crash?"); |
| 172 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 173 | } |
| 174 | |
| 175 | // CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string> |
| 176 | // CHECK-NEXT: <key>expansion</key><string>a = 0; print( "Will this ( cause a crash?")</string> |
| 177 | |
| 178 | void macroArgContainsRParenInStringTest() { |
| 179 | int *a; |
| 180 | TO_NULL_AND_PRINT(a, "Will this ) cause a crash?"); |
| 181 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 182 | } |
| 183 | |
| 184 | // CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string> |
| 185 | // CHECK-NEXT: <key>expansion</key><string>a = 0; print( "Will this ) cause a crash?")</string> |
| 186 | |
| 187 | #define CALL_FUNCTION(funcCall) \ |
| 188 | funcCall |
| 189 | |
| 190 | // Function calls do contain both tok::comma and tok::l_paren/tok::r_paren. |
| 191 | |
| 192 | void macroArgContainsLParenRParenTest() { |
| 193 | int *a; |
| 194 | CALL_FUNCTION(setToNull(&a)); |
| 195 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 196 | } |
| 197 | |
| 198 | // CHECK: <key>name</key><string>CALL_FUNCTION</string> |
| 199 | // CHECK-NEXT: <key>expansion</key><string>setToNull(&a)</string> |
| 200 | |
| 201 | void setToNullAndPrint(int **vptr, const char *str) { |
| 202 | setToNull(vptr); |
| 203 | print(str); |
| 204 | } |
| 205 | |
| 206 | void macroArgContainsCommaLParenRParenTest() { |
| 207 | int *a; |
| 208 | CALL_FUNCTION(setToNullAndPrint(&a, "Hello!")); |
| 209 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 210 | } |
| 211 | |
| 212 | // CHECK: <key>name</key><string>CALL_FUNCTION</string> |
| 213 | // CHECK-NEXT: <key>expansion</key><string>setToNullAndPrint(&a, "Hello!")</string> |
| 214 | |
| 215 | #define CALL_FUNCTION_WITH_TWO_PARAMS(funcCall, param1, param2) \ |
| 216 | funcCall(param1, param2) |
| 217 | |
| 218 | void macroArgContainsCommaLParenRParenTest2() { |
| 219 | int *a; |
| 220 | CALL_FUNCTION_WITH_TWO_PARAMS(setToNullAndPrint, &a, "Hello!"); |
| 221 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 222 | } |
| 223 | |
| 224 | // CHECK: <key>name</key><string>CALL_FUNCTION_WITH_TWO_PARAMS</string> |
| 225 | // CHECK-NEXT: <key>expansion</key><string>setToNullAndPrint( &a, "Hello!")</string> |
| 226 | |
| 227 | #define CALL_LAMBDA(l) \ |
| 228 | l() |
| 229 | |
| 230 | void commaInBracketsTest() { |
| 231 | int *ptr; |
| 232 | const char str[] = "Hello!"; |
| 233 | // You need to add parantheses around a lambda expression to compile this, |
| 234 | // else the comma in the capture will be parsed as divider of macro args. |
| 235 | CALL_LAMBDA(([&ptr, str] () mutable { TO_NULL(&ptr); })); |
| 236 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 237 | } |
| 238 | |
| 239 | // CHECK: <key>name</key><string>CALL_LAMBDA</string> |
| 240 | // CHECK-NEXT: <key>expansion</key><string>([&ptr, str] () mutable { setToNull(&ptr); })()</string> |
| 241 | |
| 242 | #define PASTE_CODE(code) \ |
| 243 | code |
| 244 | |
| 245 | void commaInBracesTest() { |
| 246 | PASTE_CODE({ // expected-warning{{Dereference of null pointer}} |
| 247 | // NOTE: If we were to add a new variable here after a comma, we'd get a |
| 248 | // compilation error, so this test is mainly here to show that this was also |
| 249 | // investigated. |
| 250 | |
| 251 | // int *ptr = nullptr, a; |
| 252 | int *ptr = nullptr; |
| 253 | *ptr = 5; |
| 254 | }) |
| 255 | } |
| 256 | |
| 257 | // CHECK: <key>name</key><string>PASTE_CODE</string> |
| 258 | // CHECK-NEXT: <key>expansion</key><string>{ int *ptr = nullptr; *ptr = 5; }</string> |
| 259 | |
| 260 | // Example taken from |
| 261 | // https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html#Macro-Arguments. |
| 262 | |
| 263 | #define POTENTIALLY_EMPTY_PARAM(x, y) \ |
| 264 | x; \ |
| 265 | y = nullptr |
| 266 | |
| 267 | void emptyParamTest() { |
| 268 | int *ptr; |
| 269 | |
| 270 | POTENTIALLY_EMPTY_PARAM(,ptr); |
| 271 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 272 | } |
| 273 | |
| 274 | // CHECK: <key>name</key><string>POTENTIALLY_EMPTY_PARAM</string> |
| 275 | // CHECK-NEXT: <key>expansion</key><string>;ptr = nullptr</string> |
| 276 | |
| 277 | #define NESTED_EMPTY_PARAM(a, b) \ |
| 278 | POTENTIALLY_EMPTY_PARAM(a, b); |
| 279 | |
| 280 | |
| 281 | void nestedEmptyParamTest() { |
| 282 | int *ptr; |
| 283 | |
| 284 | NESTED_EMPTY_PARAM(, ptr); |
| 285 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 286 | } |
| 287 | |
| 288 | // CHECK: <key>name</key><string>NESTED_EMPTY_PARAM</string> |
| 289 | // CHECK-NEXT: <key>expansion</key><string>; ptr = nullptr;</string> |
| 290 | |
| 291 | #define CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(func, param) \ |
| 292 | CALL_FUNCTION(func(param)) |
| 293 | |
| 294 | void lParenRParenInNestedMacro() { |
| 295 | int *ptr; |
| 296 | CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO(setToNull, &ptr); |
| 297 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 298 | } |
| 299 | |
| 300 | // CHECK: <key>name</key><string>CALL_FUNCTION_WITH_ONE_PARAM_THROUGH_MACRO</string> |
| 301 | // CHECK-NEXT: <key>expansion</key><string>setToNull( &ptr)</string> |
| 302 | |
| 303 | //===----------------------------------------------------------------------===// |
| 304 | // Tests for variadic macro arguments. |
| 305 | //===----------------------------------------------------------------------===// |
| 306 | |
| 307 | template <typename ...Args> |
| 308 | void variadicFunc(Args ...args); |
| 309 | |
| 310 | #define VARIADIC_SET_TO_NULL(ptr, ...) \ |
| 311 | ptr = nullptr; \ |
| 312 | variadicFunc(__VA_ARGS__) |
| 313 | |
| 314 | void variadicMacroArgumentTest() { |
| 315 | int *ptr; |
| 316 | VARIADIC_SET_TO_NULL(ptr, 1, 5, "haha!"); |
| 317 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 318 | } |
| 319 | |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 320 | // CHECK: <key>name</key><string>VARIADIC_SET_TO_NULL</string> |
Kristof Umann | 8de6062 | 2018-11-29 17:09:41 +0000 | [diff] [blame] | 321 | // CHECK-NEXT: <key>expansion</key><string>ptr = nullptr; variadicFunc( 1, 5, "haha!")</string> |
| 322 | |
| 323 | void variadicMacroArgumentWithoutAnyArgumentTest() { |
| 324 | int *ptr; |
| 325 | // Not adding a single parameter to ... is silly (and also causes a |
| 326 | // preprocessor warning), but is not an excuse to crash on it. |
| 327 | VARIADIC_SET_TO_NULL(ptr); |
| 328 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 329 | } |
| 330 | |
| 331 | // CHECK: <key>name</key><string>VARIADIC_SET_TO_NULL</string> |
| 332 | // CHECK-NEXT: <key>expansion</key><string>ptr = nullptr; variadicFunc()</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 333 | |
| 334 | //===----------------------------------------------------------------------===// |
| 335 | // Tests for # and ##. |
| 336 | //===----------------------------------------------------------------------===// |
| 337 | |
| 338 | #define DECLARE_FUNC_AND_SET_TO_NULL(funcName, ptr) \ |
| 339 | void generated_##funcName(); \ |
| 340 | ptr = nullptr; |
| 341 | |
| 342 | void hashHashOperatorTest() { |
| 343 | int *ptr; |
| 344 | DECLARE_FUNC_AND_SET_TO_NULL(whatever, ptr); |
| 345 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 346 | } |
| 347 | |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 348 | // CHECK: <key>name</key><string>DECLARE_FUNC_AND_SET_TO_NULL</string> |
Kristof Umann | 5f9981f | 2018-11-30 19:21:35 +0000 | [diff] [blame] | 349 | // CHECK-NEXT: <key>expansion</key><string>void generated_whatever(); ptr = nullptr;</string> |
| 350 | |
| 351 | void macroArgContainsHashHashInStringTest() { |
| 352 | int *a; |
| 353 | TO_NULL_AND_PRINT(a, "Will this ## cause a crash?"); |
| 354 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 355 | } |
| 356 | |
| 357 | // CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string> |
| 358 | // CHECK-NEXT: <key>expansion</key><string>a = 0; print( "Will this ## cause a crash?")</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 359 | |
| 360 | #define PRINT_STR(str, ptr) \ |
| 361 | print(#str); \ |
| 362 | ptr = nullptr |
| 363 | |
| 364 | void hashOperatorTest() { |
| 365 | int *ptr; |
| 366 | PRINT_STR(Hello, ptr); |
| 367 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 368 | } |
| 369 | |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 370 | // CHECK: <key>name</key><string>PRINT_STR</string> |
Kristof Umann | 5f9981f | 2018-11-30 19:21:35 +0000 | [diff] [blame] | 371 | // CHECK-NEXT: <key>expansion</key><string>print("Hello"); ptr = nullptr</string> |
| 372 | |
| 373 | void macroArgContainsHashInStringTest() { |
| 374 | int *a; |
| 375 | TO_NULL_AND_PRINT(a, "Will this # cause a crash?"); |
| 376 | *a = 5; // expected-warning{{Dereference of null pointer}} |
| 377 | } |
| 378 | |
| 379 | // CHECK: <key>name</key><string>TO_NULL_AND_PRINT</string> |
| 380 | // CHECK-NEXT: <key>expansion</key><string>a = 0; print( "Will this # cause a crash?")</string> |
Kristof Umann | 08d92e4 | 2018-11-27 02:28:23 +0000 | [diff] [blame] | 381 | |
| 382 | //===----------------------------------------------------------------------===// |
| 383 | // Tests for more complex macro expansions. |
| 384 | // |
| 385 | // We won't cover anything that wasn't covered up to this point, but rather |
| 386 | // show more complex, macros with deeper nesting, more arguments (some unused) |
| 387 | // and so on. |
| 388 | //===----------------------------------------------------------------------===// |
| 389 | |
| 390 | #define IF(Condition) \ |
| 391 | if ( Condition ) |
| 392 | |
| 393 | #define L_BRACE { |
| 394 | #define R_BRACE } |
| 395 | #define LESS < |
| 396 | #define GREATER > |
| 397 | #define EQUALS = |
| 398 | #define SEMICOLON ; |
| 399 | #define NEGATIVE - |
| 400 | #define RETURN return |
| 401 | #define ZERO 0 |
| 402 | |
| 403 | #define EUCLIDEAN_ALGORITHM(A, B) \ |
| 404 | IF(A LESS ZERO) L_BRACE \ |
| 405 | A EQUALS NEGATIVE A SEMICOLON \ |
| 406 | R_BRACE \ |
| 407 | IF(B LESS ZERO) L_BRACE \ |
| 408 | B EQUALS NEGATIVE B SEMICOLON \ |
| 409 | R_BRACE \ |
| 410 | \ |
| 411 | /* This is where a while loop would be, but that seems to be too complex */ \ |
| 412 | /* for the analyzer just yet. Let's just pretend that this algorithm */ \ |
| 413 | /* works. */ \ |
| 414 | \ |
| 415 | RETURN B / (B - B) SEMICOLON |
| 416 | |
| 417 | int getLowestCommonDenominator(int A, int B) { |
| 418 | EUCLIDEAN_ALGORITHM(A, B) // expected-warning{{Division by zero}} |
| 419 | } |
| 420 | |
| 421 | void testVeryComplexAlgorithm() { |
| 422 | int tmp = 8 / (getLowestCommonDenominator(5, 7) - 1); |
| 423 | print(&tmp); |
| 424 | } |
| 425 | // CHECK: <key>name</key><string>EUCLIDEAN_ALGORITHM</string> |
| 426 | // CHECK-NEXT: <key>expansion</key><string>if (A<0 ){A=-A;} if ( B<0 ){ B=- B;}return B / ( B - B);</string> |
| 427 | |
| 428 | #define YET_ANOTHER_SET_TO_NULL(x, y, z) \ |
| 429 | print((void *) x); \ |
| 430 | print((void *) y); \ |
| 431 | z = nullptr; |
| 432 | |
| 433 | #define DO_NOTHING(str) str |
| 434 | #define DO_NOTHING2(str2) DO_NOTHING(str2) |
| 435 | |
| 436 | void test() { |
| 437 | int *ptr; |
| 438 | YET_ANOTHER_SET_TO_NULL(5, DO_NOTHING2("Remember the Vasa"), ptr); |
| 439 | *ptr = 5; // expected-warning{{Dereference of null pointer}} |
| 440 | } |
| 441 | // CHECK: <key>name</key><string>YET_ANOTHER_SET_TO_NULL</string> |
| 442 | // CHECK-NEXT: <key>expansion</key><string>print((void *)5); print((void *)"Remember the Vasa"); ptr = nullptr;</string> |