Various cast related checks. Args: filename: The name of the current file. clean_lines: A CleansedLines instance containing the file. linenum: The number of the line to check. error: The function to call with any errors found.
(filename, clean_lines, linenum, error)
| 6455 | |
| 6456 | |
| 6457 | def CheckCasts(filename, clean_lines, linenum, error): |
| 6458 | """Various cast related checks. |
| 6459 | |
| 6460 | Args: |
| 6461 | filename: The name of the current file. |
| 6462 | clean_lines: A CleansedLines instance containing the file. |
| 6463 | linenum: The number of the line to check. |
| 6464 | error: The function to call with any errors found. |
| 6465 | """ |
| 6466 | line = clean_lines.elided[linenum] |
| 6467 | |
| 6468 | # Check to see if they're using an conversion function cast. |
| 6469 | # I just try to capture the most common basic types, though there are more. |
| 6470 | # Parameterless conversion functions, such as bool(), are allowed as they are |
| 6471 | # probably a member operator declaration or default constructor. |
| 6472 | match = re.search( |
| 6473 | r"(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b" |
| 6474 | r"(int|float|double|bool|char|int16_t|uint16_t|int32_t|uint32_t|int64_t|uint64_t)" |
| 6475 | r"(\([^)].*)", |
| 6476 | line, |
| 6477 | ) |
| 6478 | expecting_function = ExpectingFunctionArgs(clean_lines, linenum) |
| 6479 | if match and not expecting_function: |
| 6480 | matched_type = match.group(2) |
| 6481 | |
| 6482 | # matched_new_or_template is used to silence two false positives: |
| 6483 | # - New operators |
| 6484 | # - Template arguments with function types |
| 6485 | # |
| 6486 | # For template arguments, we match on types immediately following |
| 6487 | # an opening bracket without any spaces. This is a fast way to |
| 6488 | # silence the common case where the function type is the first |
| 6489 | # template argument. False negative with less-than comparison is |
| 6490 | # avoided because those operators are usually followed by a space. |
| 6491 | # |
| 6492 | # function<double(double)> // bracket + no space = false positive |
| 6493 | # value < double(42) // bracket + space = true positive |
| 6494 | matched_new_or_template = match.group(1) |
| 6495 | |
| 6496 | # Avoid arrays by looking for brackets that come after the closing |
| 6497 | # parenthesis. |
| 6498 | if re.match(r"\([^()]+\)\s*\[", match.group(3)): |
| 6499 | return |
| 6500 | |
| 6501 | # Other things to ignore: |
| 6502 | # - Function pointers |
| 6503 | # - Casts to pointer types |
| 6504 | # - Placement new |
| 6505 | # - Alias declarations |
| 6506 | matched_funcptr = match.group(3) |
| 6507 | if ( |
| 6508 | matched_new_or_template is None |
| 6509 | and not ( |
| 6510 | matched_funcptr |
| 6511 | and ( |
| 6512 | re.match(r"\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(", matched_funcptr) |
| 6513 | or matched_funcptr.startswith("(*)") |
| 6514 | ) |
no test coverage detected