https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/212723
None >From 53af2e4bbcf2bef3db83ebe75c0b15528deecc9d Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Wed, 29 Jul 2026 17:18:10 +0800 Subject: [PATCH] [clang-tidy] Rewrite remaining bugprone check docs to Markdown [1/N] --- .../checks/bugprone/argument-comment.rst | 331 +++++++------- .../checks/bugprone/assert-side-effect.rst | 55 ++- .../assignment-in-selection-statement.rst | 74 ++- .../checks/bugprone/bitwise-pointer-cast.rst | 60 +-- .../checks/bugprone/branch-clone.rst | 152 ++++--- .../capturing-this-in-member-variable.rst | 78 ++-- .../checks/bugprone/casting-through-void.rst | 50 +-- .../checks/bugprone/chained-comparison.rst | 98 ++-- ...are-pointer-to-member-virtual-function.rst | 62 ++- .../checks/bugprone/copy-constructor-init.rst | 50 +-- .../crtp-constructor-accessibility.rst | 93 ++-- .../checks/bugprone/dangling-handle.rst | 75 ++-- .../derived-method-shadowing-base-method.rst | 36 +- .../bugprone/easily-swappable-parameters.rst | 420 +++++++++--------- .../checks/bugprone/empty-catch.rst | 156 ++++--- .../exception-copy-constructor-throws.rst | 34 +- .../checks/bugprone/exception-escape.rst | 151 ++++--- .../checks/bugprone/fold-init-type.rst | 50 +-- .../forwarding-reference-overload.rst | 68 ++- ...icit-widening-of-multiplication-result.rst | 82 ++-- 20 files changed, 1071 insertions(+), 1104 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst index a5863ab32c41f..68f7a6eb7a260 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst @@ -1,275 +1,274 @@ -.. title:: clang-tidy - bugprone-argument-comment +```{title} clang-tidy - bugprone-argument-comment +``` -bugprone-argument-comment -========================= +# bugprone-argument-comment Checks that argument comments match parameter names and can optionally add missing comments for literals, init-lists, and constructed temporaries. -The check understands argument comments in the form ``/*parameter_name=*/`` +The check understands argument comments in the form `/*parameter_name=*/` that are placed right before the argument. -.. code-block:: c++ +```c++ +void f(bool foo); - void f(bool foo); +... - ... - - f(/*bar=*/true); - // warning: argument name 'bar' in comment does not match parameter name 'foo' +f(/*bar=*/true); +// warning: argument name 'bar' in comment does not match parameter name 'foo' +``` The check tries to detect typos and suggest automated fixes for them. It can also insert missing comments for configured argument kinds. -Options -------- - -.. option:: StrictMode - - When `false`, the check will ignore leading and trailing - underscores and case when comparing names -- otherwise they are taken into - account. Default is `false`. +## Options -.. option:: IgnoreSingleArgument +```{option} StrictMode +When `false`, the check will ignore leading and trailing +underscores and case when comparing names -- otherwise they are taken into +account. Default is `false`. +``` - When `true`, the check will ignore the single argument. Default is `false`. +```{option} IgnoreSingleArgument +When `true`, the check will ignore the single argument. Default is `false`. +``` -.. option:: CommentAnonymousInitLists - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before anonymous braced-init list arguments - such as ``{}`` and ``{1, 2, 3}``. Default is `false`. +```{option} CommentAnonymousInitLists +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before anonymous braced-init list arguments +such as `{}` and `{1, 2, 3}`. Default is `false`. +``` Before: -.. code-block:: c++ - - void foo(const std::vector<int> &Dims); +```c++ +void foo(const std::vector<int> &Dims); - foo({}); +foo({}); +``` After: -.. code-block:: c++ +```c++ +void foo(const std::vector<int> &Dims); - void foo(const std::vector<int> &Dims); +foo(/*Dims=*/{}); +``` - foo(/*Dims=*/{}); - -.. option:: CommentBoolLiterals - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the boolean literal argument. - Default is `false`. +```{option} CommentBoolLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the boolean literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ +```c++ +void foo(bool TurnKey, bool PressButton); - void foo(bool TurnKey, bool PressButton); - - foo(true, false); +foo(true, false); +``` After: -.. code-block:: c++ - - void foo(bool TurnKey, bool PressButton); +```c++ +void foo(bool TurnKey, bool PressButton); - foo(/*TurnKey=*/true, /*PressButton=*/false); +foo(/*TurnKey=*/true, /*PressButton=*/false); +``` -.. option:: CommentCharacterLiterals - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the character literal argument. - Default is `false`. +```{option} CommentCharacterLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the character literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ - - void foo(char *Character); +```c++ +void foo(char *Character); - foo('A'); +foo('A'); +``` After: -.. code-block:: c++ - - void foo(char *Character); - - foo(/*Character=*/'A'); +```c++ +void foo(char *Character); -.. option:: CommentFloatLiterals +foo(/*Character=*/'A'); +``` - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the float/double literal argument. - Default is `false`. +```{option} CommentFloatLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the float/double literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ +```c++ +void foo(float Pi); - void foo(float Pi); - - foo(3.14159); +foo(3.14159); +``` After: -.. code-block:: c++ - - void foo(float Pi); +```c++ +void foo(float Pi); - foo(/*Pi=*/3.14159); +foo(/*Pi=*/3.14159); +``` -.. option:: CommentIntegerLiterals - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the integer literal argument. - Default is `false`. +```{option} CommentIntegerLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the integer literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ - - void foo(int MeaningOfLife); +```c++ +void foo(int MeaningOfLife); - foo(42); +foo(42); +``` After: -.. code-block:: c++ +```c++ +void foo(int MeaningOfLife); - void foo(int MeaningOfLife); +foo(/*MeaningOfLife=*/42); +``` - foo(/*MeaningOfLife=*/42); - -.. option:: CommentNullPtrs - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the nullptr literal argument. - Default is `false`. +```{option} CommentNullPtrs +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the nullptr literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ +```c++ +void foo(A* Value); - void foo(A* Value); - - foo(nullptr); +foo(nullptr); +``` After: -.. code-block:: c++ - - void foo(A* Value); +```c++ +void foo(A* Value); - foo(/*Value=*/nullptr); +foo(/*Value=*/nullptr); +``` -.. option:: CommentParenthesizedTemporaries - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before explicit temporary constructions such as - ``Type()`` and ``Type(1, 2, 3)``. Default is `false`. +```{option} CommentParenthesizedTemporaries +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before explicit temporary constructions such as +`Type()` and `Type(1, 2, 3)`. Default is `false`. +``` Before: -.. code-block:: c++ - - struct Dims { - Dims(); - Dims(int, int, int); - }; +```c++ +struct Dims { + Dims(); + Dims(int, int, int); +}; - void foo(const Dims &DimsValue); +void foo(const Dims &DimsValue); - foo(Dims()); - foo(Dims(1, 2, 3)); +foo(Dims()); +foo(Dims(1, 2, 3)); +``` After: -.. code-block:: c++ - - struct Dims { - Dims(); - Dims(int, int, int); - }; - - void foo(const Dims &DimsValue); +```c++ +struct Dims { + Dims(); + Dims(int, int, int); +}; - foo(/*DimsValue=*/Dims()); - foo(/*DimsValue=*/Dims(1, 2, 3)); +void foo(const Dims &DimsValue); -.. option:: CommentStringLiterals +foo(/*DimsValue=*/Dims()); +foo(/*DimsValue=*/Dims(1, 2, 3)); +``` - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the string literal argument. - Default is `false`. +```{option} CommentStringLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the string literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ +```c++ +void foo(const char *String); +void foo(const wchar_t *WideString); - void foo(const char *String); - void foo(const wchar_t *WideString); - - foo("Hello World"); - foo(L"Hello World"); +foo("Hello World"); +foo(L"Hello World"); +``` After: -.. code-block:: c++ - - void foo(const char *String); - void foo(const wchar_t *WideString); +```c++ +void foo(const char *String); +void foo(const wchar_t *WideString); - foo(/*String=*/"Hello World"); - foo(/*WideString=*/L"Hello World"); +foo(/*String=*/"Hello World"); +foo(/*WideString=*/L"Hello World"); +``` -.. option:: CommentTypedInitLists - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before typed braced-init list arguments such - as ``Type{}``. Default is `false`. +```{option} CommentTypedInitLists +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before typed braced-init list arguments such +as `Type{}`. Default is `false`. +``` Before: -.. code-block:: c++ - - void foo(const std::vector<int> &Dims); +```c++ +void foo(const std::vector<int> &Dims); - foo(std::vector<int>{}); +foo(std::vector<int>{}); +``` After: -.. code-block:: c++ +```c++ +void foo(const std::vector<int> &Dims); - void foo(const std::vector<int> &Dims); +foo(/*Dims=*/std::vector<int>{}); +``` - foo(/*Dims=*/std::vector<int>{}); - -.. option:: CommentUserDefinedLiterals - - When `true`, the check will add argument comments in the format - ``/*ParameterName=*/`` right before the user defined literal argument. - Default is `false`. +```{option} CommentUserDefinedLiterals +When `true`, the check will add argument comments in the format +`/*ParameterName=*/` right before the user defined literal argument. +Default is `false`. +``` Before: -.. code-block:: c++ +```c++ +void foo(double Distance); - void foo(double Distance); +double operator"" _km(long double); - double operator"" _km(long double); - - foo(402.0_km); +foo(402.0_km); +``` After: -.. code-block:: c++ - - void foo(double Distance); +```c++ +void foo(double Distance); - double operator"" _km(long double); +double operator"" _km(long double); - foo(/*Distance=*/402.0_km); +foo(/*Distance=*/402.0_km); +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst index 3ca712b958d04..b05596e065dc3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst @@ -1,34 +1,33 @@ -.. title:: clang-tidy - bugprone-assert-side-effect +```{title} clang-tidy - bugprone-assert-side-effect +``` -bugprone-assert-side-effect -=========================== +# bugprone-assert-side-effect -Finds ``assert()`` with side effect. +Finds `assert()` with side effect. -The condition of ``assert()`` is evaluated only in debug builds so a +The condition of `assert()` is evaluated only in debug builds so a condition with side effect can cause different behavior in debug / release builds. -Options -------- - -.. option:: AssertMacros - - A comma-separated list of the names of assert macros to be checked. - Default is `assert,NSAssert,NSCAssert`. - -.. option:: CheckFunctionCalls - - Whether to treat non-const member and non-member functions as they produce - side effects. Disabled by default because it can increase the number of false - positive warnings. - -.. option:: IgnoredFunctions - - A semicolon-separated list of the names of functions or methods to be - considered as not having side-effects. Regular expressions are accepted, - e.g. ``[Rr]ef(erence)?$`` matches every type with suffix ``Ref``, ``ref``, - ``Reference`` and ``reference``. The default is empty. If a name in the list - contains the sequence `::` it is matched against the qualified type name - (i.e. ``namespace::Type``), otherwise it is matched against only - the type name (i.e. ``Type``). +## Options + +```{option} AssertMacros +A comma-separated list of the names of assert macros to be checked. +Default is `assert,NSAssert,NSCAssert`. +``` + +```{option} CheckFunctionCalls +Whether to treat non-const member and non-member functions as they produce +side effects. Disabled by default because it can increase the number of false +positive warnings. +``` + +```{option} IgnoredFunctions +A semicolon-separated list of the names of functions or methods to be +considered as not having side-effects. Regular expressions are accepted, +e.g. `[Rr]ef(erence)?$` matches every type with suffix `Ref`, `ref`, +`Reference` and `reference`. The default is empty. If a name in the list +contains the sequence `::` it is matched against the qualified type name +(i.e. `namespace::Type`), otherwise it is matched against only +the type name (i.e. `Type`). +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-selection-statement.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-selection-statement.rst index 0513ce3e3f771..27e7cac50f169 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-selection-statement.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-selection-statement.rst @@ -1,63 +1,61 @@ -.. title:: clang-tidy - bugprone-assignment-in-selection-statement +```{title} clang-tidy - bugprone-assignment-in-selection-statement +``` -bugprone-assignment-in-selection-statement -========================================== +# bugprone-assignment-in-selection-statement Finds assignments within selection statements. Such assignments may indicate programmer error because they may have been -intended as equality tests. The selection statements are conditions of ``if`` -and loop (``for``, ``while``, ``do``) statements, condition of conditional -operator (``?:``) and any operand of a binary logical operator (``&&``, -``||``). The check finds assignments within these contexts if the single +intended as equality tests. The selection statements are conditions of `if` +and loop (`for`, `while`, `do`) statements, condition of conditional +operator (`?:`) and any operand of a binary logical operator (`&&`, +`||`). The check finds assignments within these contexts if the single expression is an assignment or the assignment is contained (recursively) in -last operand of a comma (``,``) operator or true and false expressions in a +last operand of a comma (`,`) operator or true and false expressions in a conditional operator. The warning is suppressed if the assignment is placed in extra parentheses, but only if the assignment is the single expression of a -condition (of ``if`` or a loop statement). +condition (of `if` or a loop statement). This check corresponds to the CERT rule -`EXP45-C. Do not perform assignments in selection statements -<https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/rules/expressions-exp/exp45-c/>`_. +[EXP45-C. Do not perform assignments in selection statements](https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/rules/expressions-exp/exp45-c/). -Examples -======== +# Examples The check emits a warning in the following cases at the indicated locations: -.. code-block:: c++ +```c++ +int x = 3; - int x = 3; +if (x = 4) // should it be `x == 4` instead of 'x = 4' ? + x = x + 1; - if (x = 4) // should it be `x == 4` instead of 'x = 4' ? - x = x + 1; +while ((x <= 11) || (x = 22)) // assignment appears as operand of a logical operator + x += 2; - while ((x <= 11) || (x = 22)) // assignment appears as operand of a logical operator - x += 2; +do { + x += 5; +} while ((x > 10) ? (x = 11) : (x > 5)); // assignment in loop condition (from `x = 11`) - do { - x += 5; - } while ((x > 10) ? (x = 11) : (x > 5)); // assignment in loop condition (from `x = 11`) +for (int i = 0; i == 2, x = 5; ++i) // assignment in loop condition (from last operand of comma) + foo1(i, x); - for (int i = 0; i == 2, x = 5; ++i) // assignment in loop condition (from last operand of comma) - foo1(i, x); +for (int i = 0; i == 2, (x = 5); ++i) // assignment is not a single expression, parentheses do not prevent the warning + foo1(i, x); - for (int i = 0; i == 2, (x = 5); ++i) // assignment is not a single expression, parentheses do not prevent the warning - foo1(i, x); - - int a = (x == 2) || (x = 3); // assignment appears in the operand a logical operator +int a = (x == 2) || (x = 3); // assignment appears in the operand a logical operator +``` The following cases do not produce a warning: -.. code-block:: c++ - - if ((x = 1)) { // a single assignment between parentheses - x += 10; +```c++ +if ((x = 1)) { // a single assignment between parentheses + x += 10; - if ((x = 1) != 0) { // assignment appears in a complex expression and without a logical operator - ++x; +if ((x = 1) != 0) { // assignment appears in a complex expression and without a logical operator + ++x; - if (foo(x = 9) && array[x = 8]) { // assignment appears in argument of function call or array index - ++x; +if (foo(x = 9) && array[x = 8]) { // assignment appears in argument of function call or array index + ++x; - for (int i = 0; i = 2, x == 5; ++i) // assignment does not take part in the condition of the loop - foo1(i, x); +for (int i = 0; i = 2, x == 5; ++i) // assignment does not take part in the condition of the loop + foo1(i, x); +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst index 171e6e6157072..ae1478606492e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst @@ -1,52 +1,52 @@ -.. title:: clang-tidy - bugprone-bitwise-pointer-cast +```{title} clang-tidy - bugprone-bitwise-pointer-cast +``` -bugprone-bitwise-pointer-cast -============================= +# bugprone-bitwise-pointer-cast Warns about code that tries to cast between pointers by means of -``std::bit_cast`` or ``memcpy``. +`std::bit_cast` or `memcpy`. -The motivation is that ``std::bit_cast`` is advertised as the safe alternative -to type punning via ``reinterpret_cast`` in modern C++. However, one should not -blindly replace ``reinterpret_cast`` with ``std::bit_cast``, as follows: +The motivation is that `std::bit_cast` is advertised as the safe alternative +to type punning via `reinterpret_cast` in modern C++. However, one should not +blindly replace `reinterpret_cast` with `std::bit_cast`, as follows: -.. code-block:: c++ +```c++ +int x{}; +-float y = *reinterpret_cast<float*>(&x); ++float y = *std::bit_cast<float*>(&x); +``` - int x{}; - -float y = *reinterpret_cast<float*>(&x); - +float y = *std::bit_cast<float*>(&x); - -The drop-in replacement behaves exactly the same as ``reinterpret_cast``, and -Undefined Behavior is still invoked. ``std::bit_cast`` is copying the bytes of +The drop-in replacement behaves exactly the same as `reinterpret_cast`, and +Undefined Behavior is still invoked. `std::bit_cast` is copying the bytes of the input pointer, not the pointee, into an output pointer of a different type, which may violate the strict aliasing rules. However, simply looking at the -code, it looks "safe", because it uses ``std::bit_cast`` which is advertised as +code, it looks "safe", because it uses `std::bit_cast` which is advertised as safe. -The solution to safe type punning is to apply ``std::bit_cast`` on value types, +The solution to safe type punning is to apply `std::bit_cast` on value types, not on pointer types: -.. code-block:: c++ - - int x{}; - float y = std::bit_cast<float>(x); +```c++ +int x{}; +float y = std::bit_cast<float>(x); +``` This way, the bytes of the input object are copied into the output object, which is much safer. Do note that Undefined Behavior can still occur, if there -is no value of type ``To`` corresponding to the value representation produced. +is no value of type `To` corresponding to the value representation produced. Compilers may be able to optimize this copy and generate identical assembly to -the original ``reinterpret_cast`` version. +the original `reinterpret_cast` version. -Code before C++20 may backport ``std::bit_cast`` by means of ``memcpy``, or -simply call ``memcpy`` directly, which is equally problematic. This is also +Code before C++20 may backport `std::bit_cast` by means of `memcpy`, or +simply call `memcpy` directly, which is equally problematic. This is also detected by this check: -.. code-block:: c++ - - int* x{}; - float* y{}; - std::memcpy(&y, &x, sizeof(x)); +```c++ +int* x{}; +float* y{}; +std::memcpy(&y, &x, sizeof(x)); +``` -Alternatively, if a cast between pointers is truly wanted, ``reinterpret_cast`` +Alternatively, if a cast between pointers is truly wanted, `reinterpret_cast` should be used, to clearly convey the intent and enable warnings from compilers and linters, which should be addressed accordingly. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/branch-clone.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/branch-clone.rst index a91645f32d96f..8c9b1b49d0948 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/branch-clone.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/branch-clone.rst @@ -1,108 +1,106 @@ -.. title:: clang-tidy - bugprone-branch-clone +```{title} clang-tidy - bugprone-branch-clone +``` -bugprone-branch-clone -===================== +# bugprone-branch-clone -Checks for repeated branches in ``if/else if/else`` chains, consecutive -repeated branches in ``switch`` statements and identical true and false +Checks for repeated branches in `if/else if/else` chains, consecutive +repeated branches in `switch` statements and identical true and false branches in conditional operators. -.. code-block:: c++ - - if (test_value(x)) { - y++; - do_something(x, y); - } else { - y++; - do_something(x, y); - } +```c++ +if (test_value(x)) { + y++; + do_something(x, y); +} else { + y++; + do_something(x, y); +} +``` In this simple example (which could arise e.g. as a copy-paste error) the -``then`` and ``else`` branches are identical and the code is equivalent the +`then` and `else` branches are identical and the code is equivalent the following shorter and cleaner code: -.. code-block:: c++ - - test_value(x); // can be omitted unless it has side effects - y++; - do_something(x, y); - +```c++ +test_value(x); // can be omitted unless it has side effects +y++; +do_something(x, y); +``` If this is the intended behavior, then there is no reason to use a conditional statement; otherwise the issue can be solved by fixing the branch that is handled incorrectly. -The check detects repeated branches in longer ``if/else if/else`` chains +The check detects repeated branches in longer `if/else if/else` chains where it would be even harder to notice the problem. -The check also detects repeated inner and outer ``if`` statements that may +The check also detects repeated inner and outer `if` statements that may be a result of a copy-paste error. This check cannot currently detect -identical inner and outer ``if`` statements if code is between the ``if`` +identical inner and outer `if` statements if code is between the `if` conditions. An example is as follows. -.. code-block:: c++ - - void test_warn_inner_if_1(int x) { - if (x == 1) { // warns, if with identical inner if - if (x == 1) // inner if is here - ; - if (x == 1) { // does not warn, cannot detect - int y = x; - if (x == 1) - ; - } - } - - -In ``switch`` statements the check only reports repeated branches when they are -consecutive, because it is relatively common that the ``case:`` labels have +```c++ +void test_warn_inner_if_1(int x) { + if (x == 1) { // warns, if with identical inner if + if (x == 1) // inner if is here + ; + if (x == 1) { // does not warn, cannot detect + int y = x; + if (x == 1) + ; + } +} +``` + +In `switch` statements the check only reports repeated branches when they are +consecutive, because it is relatively common that the `case:` labels have some natural ordering and rearranging them would decrease the readability of the code. For example: -.. code-block:: c++ - - switch (ch) { - case 'a': - return 10; - case 'A': - return 10; - case 'b': - return 11; - case 'B': - return 11; - default: - return 10; - } - -Here the check reports that the ``'a'`` and ``'A'`` branches are identical -(and that the ``'b'`` and ``'B'`` branches are also identical), but does not -report that the ``default:`` branch is also identical to the first two branches. +```c++ +switch (ch) { +case 'a': + return 10; +case 'A': + return 10; +case 'b': + return 11; +case 'B': + return 11; +default: + return 10; +} +``` + +Here the check reports that the `'a'` and `'A'` branches are identical +(and that the `'b'` and `'B'` branches are also identical), but does not +report that the `default:` branch is also identical to the first two branches. If this is indeed the correct behavior, then it could be implemented as: -.. code-block:: c++ - - switch (ch) { - case 'a': - case 'A': - return 10; - case 'b': - case 'B': - return 11; - default: - return 10; - } - -Here the check does not warn for the repeated ``return 10;``, which is good if -we want to preserve that ``'a'`` is before ``'b'`` and ``default:`` is the last +```c++ +switch (ch) { +case 'a': +case 'A': + return 10; +case 'b': +case 'B': + return 11; +default: + return 10; +} +``` + +Here the check does not warn for the repeated `return 10;`, which is good if +we want to preserve that `'a'` is before `'b'` and `default:` is the last branch. -Switch cases marked with the ``[[fallthrough]]`` attribute are ignored. +Switch cases marked with the `[[fallthrough]]` attribute are ignored. Finally, the check also examines conditional operators and reports code like: -.. code-block:: c++ - - return test_value(x) ? x : x; +```c++ +return test_value(x) ? x : x; +``` Unlike if statements, the check does not detect chains of conditional operators. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst index 6a6ad7302566e..aa71c08937ca3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst @@ -1,49 +1,49 @@ -.. title:: clang-tidy - bugprone-capturing-this-in-member-variable +```{title} clang-tidy - bugprone-capturing-this-in-member-variable +``` -bugprone-capturing-this-in-member-variable -========================================== +# bugprone-capturing-this-in-member-variable -Finds lambda captures that capture the ``this`` pointer and store it as class +Finds lambda captures that capture the `this` pointer and store it as class members without handle the copy and move constructors and the assignments. Capture this in a lambda and store it as a class member is dangerous because the lambda can outlive the object it captures. Especially when the object is -copied or moved, the captured ``this`` pointer will be implicitly propagated +copied or moved, the captured `this` pointer will be implicitly propagated to the new object. Most of the time, people will believe that the captured -``this`` pointer points to the new object, which will lead to bugs. - -.. code-block:: c++ - - struct C { - C() : Captured([this]() -> C const * { return this; }) {} - std::function<C const *()> Captured; - }; - - void foo() { - C v1{}; - C v2 = v1; // v2.Captured capture v1's 'this' pointer - assert(v2.Captured() == v1.Captured()); // v2.Captured capture v1's 'this' pointer - assert(v2.Captured() == &v2); // assertion failed. - } +`this` pointer points to the new object, which will lead to bugs. + +```c++ +struct C { + C() : Captured([this]() -> C const * { return this; }) {} + std::function<C const *()> Captured; +}; + +void foo() { + C v1{}; + C v2 = v1; // v2.Captured capture v1's 'this' pointer + assert(v2.Captured() == v1.Captured()); // v2.Captured capture v1's 'this' pointer + assert(v2.Captured() == &v2); // assertion failed. +} +``` Possible fixes: - - marking copy and move constructors and assignment operators deleted. - - using class member method instead of class member variable with function - object types. - - passing ``this`` pointer as parameter. - -Options -------- - -.. option:: FunctionWrapperTypes - - A semicolon-separated list of names of types. Used to specify function - wrapper that can hold lambda expressions. - Default is `::std::function;::std::move_only_function;::boost::function`. - -.. option:: BindFunctions - A semicolon-separated list of fully qualified names of functions that can - capture ``this`` pointer. - Default is `::std::bind;::boost::bind;::std::bind_front;::std::bind_back; - ::boost::compat::bind_front;::boost::compat::bind_back`. +- marking copy and move constructors and assignment operators deleted. +- using class member method instead of class member variable with function + object types. +- passing `this` pointer as parameter. + +## Options + +```{option} FunctionWrapperTypes +A semicolon-separated list of names of types. Used to specify function +wrapper that can hold lambda expressions. +Default is `::std::function;::std::move_only_function;::boost::function`. +``` + +```{option} BindFunctions +A semicolon-separated list of fully qualified names of functions that can +capture `this` pointer. +Default is `::std::bind;::boost::bind;::std::bind_front;::std::bind_back; +::boost::compat::bind_front;::boost::compat::bind_back`. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst index 3c0b52abea707..f95909068871d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst @@ -1,13 +1,13 @@ -.. title:: clang-tidy - bugprone-casting-through-void +```{title} clang-tidy - bugprone-casting-through-void +``` -bugprone-casting-through-void -============================= +# bugprone-casting-through-void -Detects unsafe or redundant two-step casting operations involving ``void*``, -which is equivalent to ``reinterpret_cast`` as per the -`C++ Standard <https://eel.is/c++draft/expr.reinterpret.cast#7>`_. +Detects unsafe or redundant two-step casting operations involving `void*`, +which is equivalent to `reinterpret_cast` as per the +[C++ Standard](https://eel.is/c++draft/expr.reinterpret.cast#7). -Two-step type conversions via ``void*`` are discouraged for several reasons. +Two-step type conversions via `void*` are discouraged for several reasons. - They obscure code and impede its understandability, complicating maintenance. - These conversions bypass valuable compiler support, erasing warnings related @@ -17,35 +17,35 @@ Two-step type conversions via ``void*`` are discouraged for several reasons. outcomes can arise due to the loss of type information, posing runtime issues. -In summary, avoiding two-step type conversions through ``void*`` ensures +In summary, avoiding two-step type conversions through `void*` ensures clearer code, maintains essential compiler warnings, and prevents ambiguity and potential runtime errors, particularly in complex inheritance scenarios. -If such a cast is wanted, it shall be done via ``reinterpret_cast``, +If such a cast is wanted, it shall be done via `reinterpret_cast`, to express the intent more clearly. Note: it is expected that, after applying the suggested fix and using -``reinterpret_cast``, the check -:doc:`cppcoreguidelines-pro-type-reinterpret-cast +`reinterpret_cast`, the check +{doc}`cppcoreguidelines-pro-type-reinterpret-cast <../cppcoreguidelines/pro-type-reinterpret-cast>` will emit a warning. -This is intentional: ``reinterpret_cast`` is a dangerous operation that can +This is intentional: `reinterpret_cast` is a dangerous operation that can easily break the strict aliasing rules when dereferencing the casted pointer, invoking Undefined Behavior. The warning is there to prompt users to carefully -analyze whether the usage of ``reinterpret_cast`` is safe, in which case the +analyze whether the usage of `reinterpret_cast` is safe, in which case the warning may be suppressed. Examples: -.. code-block:: c++ +```c++ +using IntegerPointer = int *; +double *ptr; - using IntegerPointer = int *; - double *ptr; +static_cast<IntegerPointer>(static_cast<void *>(ptr)); // WRONG +reinterpret_cast<IntegerPointer>(reinterpret_cast<void *>(ptr)); // WRONG +(IntegerPointer)(void *)ptr; // WRONG +IntegerPointer(static_cast<void *>(ptr)); // WRONG - static_cast<IntegerPointer>(static_cast<void *>(ptr)); // WRONG - reinterpret_cast<IntegerPointer>(reinterpret_cast<void *>(ptr)); // WRONG - (IntegerPointer)(void *)ptr; // WRONG - IntegerPointer(static_cast<void *>(ptr)); // WRONG - - reinterpret_cast<IntegerPointer>(ptr); // OK, clearly expresses intent. - // NOTE: dereferencing this pointer violates - // the strict aliasing rules, invoking - // Undefined Behavior. +reinterpret_cast<IntegerPointer>(ptr); // OK, clearly expresses intent. + // NOTE: dereferencing this pointer violates + // the strict aliasing rules, invoking + // Undefined Behavior. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst index d3ad0dfe5adda..4e1554fe940e0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/chained-comparison.rst @@ -1,17 +1,17 @@ -.. title:: clang-tidy - bugprone-chained-comparison +```{title} clang-tidy - bugprone-chained-comparison +``` -bugprone-chained-comparison -=========================== +# bugprone-chained-comparison Check detects chained comparison operators that can lead to unintended behavior or logical errors. Chained comparisons are expressions that use multiple comparison operators -to compare three or more values. For example, the expression ``a < b < c`` -compares the values of ``a``, ``b``, and ``c``. However, this expression does -not evaluate as ``(a < b) && (b < c)``, which is probably what the developer -intended. Instead, it evaluates as ``(a < b) < c``, which may produce -unintended results, especially when the types of ``a``, ``b``, and ``c`` are +to compare three or more values. For example, the expression `a < b < c` +compares the values of `a`, `b`, and `c`. However, this expression does +not evaluate as `(a < b) && (b < c)`, which is probably what the developer +intended. Instead, it evaluates as `(a < b) < c`, which may produce +unintended results, especially when the types of `a`, `b`, and `c` are different. To avoid such errors, the check will issue a warning when a chained @@ -21,61 +21,57 @@ expressions. Consider the following examples: -.. code-block:: c++ +```c++ +int a = 2, b = 6, c = 4; +if (a < b < c) { + // This block will be executed +} +``` - int a = 2, b = 6, c = 4; - if (a < b < c) { - // This block will be executed - } +In this example, the developer intended to check if `a` is less than `b` +and `b` is less than `c`. However, the expression `a < b < c` is +equivalent to `(a < b) < c`. Since `a < b` is `true`, the expression +`(a < b) < c` is evaluated as `1 < c`, which is equivalent to `true < c` +and is invalid in this case as `b < c` is `false`. - -In this example, the developer intended to check if ``a`` is less than ``b`` -and ``b`` is less than ``c``. However, the expression ``a < b < c`` is -equivalent to ``(a < b) < c``. Since ``a < b`` is ``true``, the expression -``(a < b) < c`` is evaluated as ``1 < c``, which is equivalent to ``true < c`` -and is invalid in this case as ``b < c`` is ``false``. - -Even that above issue could be detected as comparison of ``int`` to ``bool``, +Even that above issue could be detected as comparison of `int` to `bool`, there is more dangerous example: -.. code-block:: c++ +```c++ +bool a = false, b = false, c = true; +if (a == b == c) { + // This block will be executed +} +``` - bool a = false, b = false, c = true; - if (a == b == c) { - // This block will be executed - } - -In this example, the developer intended to check if ``a``, ``b``, and ``c`` are -all equal. However, the expression ``a == b == c`` is evaluated as -``(a == b) == c``. Since ``a == b`` is true, the expression ``(a == b) == c`` -is evaluated as ``true == c``, which is equivalent to ``true == true``. -This comparison yields ``true``, even though ``a`` and ``b`` are ``false``, and -are not equal to ``c``. +In this example, the developer intended to check if `a`, `b`, and `c` are +all equal. However, the expression `a == b == c` is evaluated as +`(a == b) == c`. Since `a == b` is true, the expression `(a == b) == c` +is evaluated as `true == c`, which is equivalent to `true == true`. +This comparison yields `true`, even though `a` and `b` are `false`, and +are not equal to `c`. To avoid this issue, the developer can use a logical operator to separate the comparison expressions, like this: -.. code-block:: c++ - - if (a == b && b == c) { - // This block will not be executed - } - +```c++ +if (a == b && b == c) { + // This block will not be executed +} +``` Alternatively, use of parentheses in the comparison expressions can make the developer's intention more explicit and help avoid misunderstanding. -.. code-block:: c++ - - if ((a == b) == c) { - // This block will be executed - } - -Options -------- - -.. option:: IgnoreMacros +```c++ +if ((a == b) == c) { + // This block will be executed +} +``` - If `true`, the check will not warn on chained comparisons inside macros. - Default is `false`. +## Options +```{option} IgnoreMacros +If `true`, the check will not warn on chained comparisons inside macros. +Default is `false`. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst index 6b2a82f1cfe96..991bb4bd40465 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst @@ -1,39 +1,39 @@ -.. title:: clang-tidy - bugprone-compare-pointer-to-member-virtual-function +```{title} clang-tidy - bugprone-compare-pointer-to-member-virtual-function +``` -bugprone-compare-pointer-to-member-virtual-function -=================================================== +# bugprone-compare-pointer-to-member-virtual-function Detects unspecified behavior about equality comparison between pointer to member virtual function and anything other than null-pointer-constant. -.. code-block:: c++ +```c++ +struct A { + void f1(); + void f2(); + virtual void f3(); + virtual void f4(); - struct A { - void f1(); - void f2(); - virtual void f3(); - virtual void f4(); + void g1(int); +}; - void g1(int); - }; +void fn() { + bool r1 = (&A::f1 == &A::f2); // ok + bool r2 = (&A::f1 == &A::f3); // bugprone + bool r3 = (&A::f1 != &A::f3); // bugprone + bool r4 = (&A::f3 == nullptr); // ok + bool r5 = (&A::f3 == &A::f4); // bugprone - void fn() { - bool r1 = (&A::f1 == &A::f2); // ok - bool r2 = (&A::f1 == &A::f3); // bugprone - bool r3 = (&A::f1 != &A::f3); // bugprone - bool r4 = (&A::f3 == nullptr); // ok - bool r5 = (&A::f3 == &A::f4); // bugprone + void (A::*v1)() = &A::f3; + bool r6 = (v1 == &A::f1); // bugprone + bool r6 = (v1 == nullptr); // ok - void (A::*v1)() = &A::f3; - bool r6 = (v1 == &A::f1); // bugprone - bool r6 = (v1 == nullptr); // ok + void (A::*v2)() = &A::f2; + bool r7 = (v2 == &A::f1); // false positive, but potential risk if assigning other value to v2. - void (A::*v2)() = &A::f2; - bool r7 = (v2 == &A::f1); // false positive, but potential risk if assigning other value to v2. - - void (A::*v3)(int) = &A::g1; - bool r8 = (v3 == &A::g1); // ok, no virtual function match void(A::*)(int) signature. - } + void (A::*v3)(int) = &A::g1; + bool r8 = (v3 == &A::g1); // ok, no virtual function match void(A::*)(int) signature. +} +``` Provide warnings on equality comparisons involve pointers to member virtual function or variables which is potential pointer to member virtual function and @@ -47,19 +47,17 @@ becomes particularly challenging when dealing with pointers to pure virtual functions, as they may not even have a valid address, further complicating comparisons. -Instead, it is recommended to utilize the ``typeid`` operator or other +Instead, it is recommended to utilize the `typeid` operator or other appropriate mechanisms for comparing objects to ensure robust and predictable behavior in your codebase. By heeding this detection and adopting a more reliable comparison method, you can mitigate potential issues related to unspecified behavior, especially when dealing with pointers to member virtual functions or pure virtual functions, thereby improving the overall stability and maintainability of your code. In scenarios involving pointers to member virtual functions, it's -only advisable to employ ``nullptr`` for comparisons. - +only advisable to employ `nullptr` for comparisons. -Limitations ------------ +## Limitations Does not analyze values stored in a variable. For variable, only analyze all -virtual methods in the same ``class`` or ``struct`` and diagnose when assigning +virtual methods in the same `class` or `struct` and diagnose when assigning a pointer to member virtual function to this variable is possible. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-init.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-init.rst index 02d3ddefb8adc..117c67852d62d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-init.rst @@ -1,33 +1,33 @@ -.. title:: clang-tidy - bugprone-copy-constructor-init +```{title} clang-tidy - bugprone-copy-constructor-init +``` -bugprone-copy-constructor-init -============================== +# bugprone-copy-constructor-init Finds copy constructors where the constructor doesn't call the copy constructor of the base class. -.. code-block:: c++ +```c++ +class Copyable { +public: + Copyable() = default; + Copyable(const Copyable &) = default; - class Copyable { - public: - Copyable() = default; - Copyable(const Copyable &) = default; + int memberToBeCopied = 0; +}; - int memberToBeCopied = 0; - }; - - class X2 : public Copyable { - X2(const X2 &other) {} // Copyable(other) is missing - }; +class X2 : public Copyable { + X2(const X2 &other) {} // Copyable(other) is missing +}; +``` Also finds copy constructors where the constructor of the base class don't have parameter. -.. code-block:: c++ - - class X3 : public Copyable { - X3(const X3 &other) : Copyable() {} // other is missing - }; +```c++ +class X3 : public Copyable { + X3(const X3 &other) : Copyable() {} // other is missing +}; +``` Failure to properly initialize base class sub-objects during copy construction can result in undefined behavior, crashes, data corruption, or other unexpected @@ -35,17 +35,13 @@ outcomes. The check ensures that the copy constructor of a derived class properly calls the copy constructor of the base class, helping to prevent bugs and improve code quality. +## Limitations -Limitations ------------ - -* It won't generate warnings for empty classes, as there are no class members +- It won't generate warnings for empty classes, as there are no class members (including base class sub-objects) to worry about. - -* It won't generate warnings for base classes that have copy constructor +- It won't generate warnings for base classes that have copy constructor private or deleted. - -* It won't generate warnings for base classes that are initialized using other +- It won't generate warnings for base classes that are initialized using other non-default constructor, as this could be intentional. The check also suggests a fix-its in some cases. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst index 53082f44638b6..50a167e0c2dc0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - bugprone-crtp-constructor-accessibility +```{title} clang-tidy - bugprone-crtp-constructor-accessibility +``` -bugprone-crtp-constructor-accessibility -======================================= +# bugprone-crtp-constructor-accessibility Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP can be constructed outside itself and the derived class. @@ -13,15 +13,15 @@ the derived class is its template argument. Example: -.. code-block:: c++ +```c++ +template <typename T> class CRTP { +private: + CRTP() = default; + friend T; +}; - template <typename T> class CRTP { - private: - CRTP() = default; - friend T; - }; - - class Derived : CRTP<Derived> {}; +class Derived : CRTP<Derived> {}; +``` Below can be seen some common mistakes that will allow the breaking of the idiom. @@ -31,17 +31,17 @@ it allows users to construct that class on its own. Example: -.. code-block:: c++ - - template <typename T> class CRTP { - public: - CRTP() = default; - }; +```c++ +template <typename T> class CRTP { +public: + CRTP() = default; +}; - class Good : CRTP<Good> {}; - Good GoodInstance; +class Good : CRTP<Good> {}; +Good GoodInstance; - CRTP<int> BadInstance; +CRTP<int> BadInstance; +``` If the constructor is protected, the possibility of an accidental instantiation is prevented, however it can fade an error, when a different class is used as @@ -49,18 +49,18 @@ the template parameter instead of the derived one. Example: -.. code-block:: c++ - - template <typename T> class CRTP { - protected: - CRTP() = default; - }; +```c++ +template <typename T> class CRTP { +protected: + CRTP() = default; +}; - class Good : CRTP<Good> {}; - Good GoodInstance; +class Good : CRTP<Good> {}; +Good GoodInstance; - class Bad : CRTP<Good> {}; - Bad BadInstance; +class Bad : CRTP<Good> {}; +Bad BadInstance; +``` To ensure that no accidental instantiation happens, the best practice is to make the constructor private and declare the derived class as friend. Note @@ -70,32 +70,29 @@ protected if they are deleted. Example: -.. code-block:: c++ +```c++ +template <typename T> class CRTP { + CRTP() = default; + friend T; +}; - template <typename T> class CRTP { - CRTP() = default; - friend T; - }; +class Good : CRTP<Good> {}; +Good GoodInstance; - class Good : CRTP<Good> {}; - Good GoodInstance; +class Bad : CRTP<Good> {}; +Bad CompileTimeError; - class Bad : CRTP<Good> {}; - Bad CompileTimeError; +CRTP<int> AlsoCompileTimeError; +``` - CRTP<int> AlsoCompileTimeError; +## Limitations +- The check is not supported below C++11 -Limitations ------------ - -* The check is not supported below C++11 - -* The check does not handle when the derived class is passed as a variadic +- The check does not handle when the derived class is passed as a variadic template argument -* Accessible functions that can construct the CRTP, like factory functions +- Accessible functions that can construct the CRTP, like factory functions are not checked The check also suggests a fix-its in some cases. - diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst index c25f8c4e7caaa..81098114a2e31 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst @@ -1,46 +1,45 @@ -.. title:: clang-tidy - bugprone-dangling-handle +```{title} clang-tidy - bugprone-dangling-handle +``` -bugprone-dangling-handle -======================== +# bugprone-dangling-handle -Detect dangling references in value handles like ``std::string_view``. +Detect dangling references in value handles like `std::string_view`. These dangling references can be a result of constructing handles from temporary values, where the temporary is destroyed soon after the handle is created. Examples: -.. code-block:: c++ - - string_view View = string(); // View will dangle. - string A; - View = A + "A"; // still dangle. - - vector<string_view> V; - V.push_back(string()); // V[0] is dangling. - V.resize(3, string()); // V[1] and V[2] will also dangle. - - string_view f() { - // All these return values will dangle. - return string(); - string S; - return S; - char Array[10]{}; - return Array; - } - - span<int> g() { - array<int, 1> V; - return {V}; - int Array[10]{}; - return {Array}; - } - -Options -------- - -.. option:: HandleClasses - - A semicolon-separated list of class names that should be treated as handles. - By default only ``std::basic_string_view``, - ``std::experimental::basic_string_view`` and ``std::span`` are considered. +```c++ +string_view View = string(); // View will dangle. +string A; +View = A + "A"; // still dangle. + +vector<string_view> V; +V.push_back(string()); // V[0] is dangling. +V.resize(3, string()); // V[1] and V[2] will also dangle. + +string_view f() { + // All these return values will dangle. + return string(); + string S; + return S; + char Array[10]{}; + return Array; +} + +span<int> g() { + array<int, 1> V; + return {V}; + int Array[10]{}; + return {Array}; +} +``` + +## Options + +```{option} HandleClasses +A semicolon-separated list of class names that should be treated as handles. +By default only `std::basic_string_view`, +`std::experimental::basic_string_view` and `std::span` are considered. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst index 4906b501f9ff3..560993d9b2494 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - bugprone-derived-method-shadowing-base-method +```{title} clang-tidy - bugprone-derived-method-shadowing-base-method +``` -bugprone-derived-method-shadowing-base-method -============================================= +# bugprone-derived-method-shadowing-base-method Finds derived class methods that shadow a (non-virtual) base class method. @@ -9,23 +9,23 @@ In order to be considered "shadowing", methods must have the same signature (i.e. the same name, same number of parameters, same parameter types, etc). Only checks public, non-templated methods. -The below example is bugprone because consumers of the ``Derived`` class will -expect the ``reset`` method to do the work of ``Base::reset()`` in addition to -extra work required to reset the ``Derived`` class. Common fixes include: +The below example is bugprone because consumers of the `Derived` class will +expect the `reset` method to do the work of `Base::reset()` in addition to +extra work required to reset the `Derived` class. Common fixes include: -- Making the ``reset`` method polymorphic -- Re-naming ``Derived::reset`` if it's not meant to intersect with - ``Base::reset`` -- Using ``using Base::reset`` to change the access specifier +- Making the `reset` method polymorphic +- Re-naming `Derived::reset` if it's not meant to intersect with + `Base::reset` +- Using `using Base::reset` to change the access specifier This is also a violation of the Liskov Substitution Principle. -.. code-block:: c++ +```c++ +struct Base { + void reset() {/* reset the base class */}; +}; - struct Base { - void reset() {/* reset the base class */}; - }; - - struct Derived : public Base { - void reset() {/* reset the derived class, but not the base class */}; - }; +struct Derived : public Base { + void reset() {/* reset the derived class, but not the base class */}; +}; +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst index 59ccab4851dcc..2ef319cc08634 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst @@ -1,39 +1,37 @@ -.. title:: clang-tidy - bugprone-easily-swappable-parameters +```{title} clang-tidy - bugprone-easily-swappable-parameters +``` -bugprone-easily-swappable-parameters -==================================== +# bugprone-easily-swappable-parameters Finds function definitions where parameters of convertible types follow each other directly, making call sites prone to calling the function with swapped (or badly ordered) arguments. -.. code-block:: c++ +```c++ +void drawPoint(int X, int Y) { /* ... */ } +FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } +``` - void drawPoint(int X, int Y) { /* ... */ } - FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } - -A potential call like ``drawPoint(-2, 5)`` or -``openPath("a.txt", "tmp", Read)`` is perfectly legal from the language's +A potential call like `drawPoint(-2, 5)` or +`openPath("a.txt", "tmp", Read)` is perfectly legal from the language's perspective, but might not be what the developer of the function intended. More elaborate and type-safe constructs, such as opaque typedefs or strong types should be used instead, to prevent a mistaken order of arguments. -.. code-block:: c++ - - struct Coord2D { int X; int Y; }; - void drawPoint(const Coord2D Pos) { /* ... */ } +```c++ +struct Coord2D { int X; int Y; }; +void drawPoint(const Coord2D Pos) { /* ... */ } - FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ } +FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ } +``` Due to the potentially elaborate refactoring and API-breaking that is necessary to strengthen the type safety of a project, no automatic fix-its are offered. -Options -------- +## Options -Extension/relaxation options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +### Extension/relaxation options Relaxation (or extension) options can be used to broaden the scope of the analysis and fine-tune the enabling of more mixes between types. @@ -43,155 +41,154 @@ way of mixing at call sites the most. These options are expected to make the check report for more functions, and report longer mixable ranges. -.. option:: QualifiersMix - - Whether to consider parameters of some *cvr-qualified* ``T`` and a - differently *cvr-qualified* ``T`` (i.e. ``T`` and ``const T``, ``const T`` - and ``volatile T``, etc.) mixable between one another. - If `false`, the check will consider differently qualified types unmixable. - `True` turns the warnings on. - Defaults to `false`. - - The following example produces a diagnostic only if `QualifiersMix` is - enabled: - - .. code-block:: c++ - - void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ } - -.. option:: ModelImplicitConversions - - Whether to consider parameters of type ``T`` and ``U`` mixable if there - exists an implicit conversion from ``T`` to ``U`` and ``U`` to ``T``. - If `false`, the check will not consider implicitly convertible types for - mixability. - `True` turns warnings for implicit conversions on. - Defaults to `true`. - - The following examples produce a diagnostic only if - `ModelImplicitConversions` is enabled: - - .. code-block:: c++ - - void fun(int Int, double Double) { /* ... */ } - void compare(const char *CharBuf, std::string String) { /* ... */ } - - .. note:: - - Changing the qualifiers of an expression's type (e.g. from ``int`` to - ``const int``) is defined as an *implicit conversion* in the C++ - Standard. - However, the check separates this decision-making on the mixability of - differently qualified types based on whether `QualifiersMix` was - enabled. - - For example, the following code snippet will only produce a diagnostic - if **both** `QualifiersMix` and `ModelImplicitConversions` are enabled: - - .. code-block:: c++ - - void fun2(int Int, const double Double) { /* ... */ } - -Filtering options -^^^^^^^^^^^^^^^^^ +````{option} QualifiersMix +Whether to consider parameters of some *cvr-qualified* `T` and a +differently *cvr-qualified* `T` (i.e. `T` and `const T`, `const T` +and `volatile T`, etc.) mixable between one another. +If `false`, the check will consider differently qualified types unmixable. +`True` turns the warnings on. +Defaults to `false`. + +The following example produces a diagnostic only if `QualifiersMix` is +enabled: + +```c++ +void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ } +``` +```` + +`````{option} ModelImplicitConversions +Whether to consider parameters of type `T` and `U` mixable if there +exists an implicit conversion from `T` to `U` and `U` to `T`. +If `false`, the check will not consider implicitly convertible types for +mixability. +`True` turns warnings for implicit conversions on. +Defaults to `true`. + +The following examples produce a diagnostic only if +`ModelImplicitConversions` is enabled: + +```c++ +void fun(int Int, double Double) { /* ... */ } +void compare(const char *CharBuf, std::string String) { /* ... */ } +``` + +````{note} +Changing the qualifiers of an expression's type (e.g. from `int` to +`const int`) is defined as an *implicit conversion* in the C++ +Standard. +However, the check separates this decision-making on the mixability of +differently qualified types based on whether `QualifiersMix` was +enabled. + +For example, the following code snippet will only produce a diagnostic +if **both** `QualifiersMix` and `ModelImplicitConversions` are enabled: + +```c++ +void fun2(int Int, const double Double) { /* ... */ } +``` +```` +````` + +### Filtering options Filtering options can be used to lessen the size of the diagnostics emitted by the checker, whether the aim is to ignore certain constructs or dampen the noisiness. -.. option:: MinimumLength - - The minimum length required from an adjacent parameter sequence to be - diagnosed. - Defaults to `2`. - Might be any positive integer greater or equal to `2`. - If `0` or `1` is given, the default value `2` will be used instead. - - For example, if `3` is specified, the examples above will not be matched. - -.. option:: IgnoredParameterNames - - The list of parameter **names** that should never be considered part of a - swappable adjacent parameter sequence. - The value is a `;`-separated list of names. - To ignore unnamed parameters, add `""` to the list verbatim (not the - empty string, but the two quotes, potentially escaped!). - **This option is case-sensitive!** - - By default, the following parameter names, and their Uppercase-initial - variants are ignored: - `""` (unnamed parameters), `iterator`, `begin`, `end`, `first`, `last`, - `lhs`, `rhs`. - -.. option:: IgnoredParameterTypeSuffixes - - The list of parameter **type name suffixes** that should never be - considered part of a swappable adjacent parameter sequence. - Parameters which type, as written in the source code, end with an element - of this option will be ignored. - The value is a `;`-separated list of names. - **This option is case-sensitive!** - - By default, the following, and their lowercase-initial variants are ignored: - `bool`, `It`, `Iterator`, `InputIt`, `ForwardIt`, `BidirIt`, `RandomIt`, - `random_iterator`, `ReverseIt`, `reverse_iterator`, - `reverse_const_iterator`, `RandomIt`, `random_iterator`, `ReverseIt`, - `reverse_iterator`, `reverse_const_iterator`, `Const_Iterator`, - `ConstIterator`, `const_reverse_iterator`, `ConstReverseIterator`. - In addition, `_Bool` (but not `_bool`) is also part of the default value. - -.. option:: SuppressParametersUsedTogether - - Suppresses diagnostics about parameters that are used together or in a - similar fashion inside the function's body. - Defaults to `true`. - Specifying `false` will turn off the heuristics. - - Currently, the following heuristics are implemented which will suppress the - warning about the parameter pair involved: - - * The parameters are used in the same expression, e.g. ``f(a, b)`` or - ``a < b``. - * The parameters are further passed to the same function to the same - parameter of that function, of the same overload. - E.g. ``f(a, 1)`` and ``f(b, 2)`` to some ``f(T, int)``. - - .. note:: - - The check does not perform path-sensitive analysis, and as such, - "same function" in this context means the same function declaration. - If the same member function of a type on two distinct instances are - called with the parameters, it will still be regarded as - "same function". - - * The same member field is accessed, or member method is called of the - two parameters, e.g. ``a.foo()`` and ``b.foo()``. - * Separate ``return`` statements return either of the parameters on - different code paths. - -.. option:: NamePrefixSuffixSilenceDissimilarityThreshold - - The number of characters two parameter names might be different on *either* - the head or the tail end with the rest of the name the same so that the - warning about the two parameters are silenced. - Defaults to `1`. - Might be any positive integer. - If `0`, the filtering heuristic based on the parameters' names is turned - off. - - This option can be used to silence warnings about parameters where the - naming scheme indicates that the order of those parameters do not matter. - - For example, the parameters ``LHS`` and ``RHS`` are 1-dissimilar suffixes - of each other: ``L`` and ``R`` is the different character, while ``HS`` - is the common suffix. - Similarly, parameters ``text1, text2, text3`` are 1-dissimilar prefixes - of each other, with the numbers at the end being the dissimilar part. - If the value is at least `1`, such cases will not be reported. - - -Limitations ------------ +```{option} MinimumLength +The minimum length required from an adjacent parameter sequence to be +diagnosed. +Defaults to `2`. +Might be any positive integer greater or equal to `2`. +If `0` or `1` is given, the default value `2` will be used instead. + +For example, if `3` is specified, the examples above will not be matched. +``` + +```{option} IgnoredParameterNames +The list of parameter **names** that should never be considered part of a +swappable adjacent parameter sequence. +The value is a `;`-separated list of names. +To ignore unnamed parameters, add `""` to the list verbatim (not the +empty string, but the two quotes, potentially escaped!). +**This option is case-sensitive!** + +By default, the following parameter names, and their Uppercase-initial +variants are ignored: +`""` (unnamed parameters), `iterator`, `begin`, `end`, `first`, `last`, +`lhs`, `rhs`. +``` + +```{option} IgnoredParameterTypeSuffixes +The list of parameter **type name suffixes** that should never be +considered part of a swappable adjacent parameter sequence. +Parameters which type, as written in the source code, end with an element +of this option will be ignored. +The value is a `;`-separated list of names. +**This option is case-sensitive!** + +By default, the following, and their lowercase-initial variants are ignored: +`bool`, `It`, `Iterator`, `InputIt`, `ForwardIt`, `BidirIt`, `RandomIt`, +`random_iterator`, `ReverseIt`, `reverse_iterator`, +`reverse_const_iterator`, `RandomIt`, `random_iterator`, `ReverseIt`, +`reverse_iterator`, `reverse_const_iterator`, `Const_Iterator`, +`ConstIterator`, `const_reverse_iterator`, `ConstReverseIterator`. +In addition, `_Bool` (but not `_bool`) is also part of the default value. +``` + +````{option} SuppressParametersUsedTogether +Suppresses diagnostics about parameters that are used together or in a +similar fashion inside the function's body. +Defaults to `true`. +Specifying `false` will turn off the heuristics. + +Currently, the following heuristics are implemented which will suppress the +warning about the parameter pair involved: + +- The parameters are used in the same expression, e.g. `f(a, b)` or + `a < b`. + +- The parameters are further passed to the same function to the same + parameter of that function, of the same overload. + E.g. `f(a, 1)` and `f(b, 2)` to some `f(T, int)`. + + ```{note} + The check does not perform path-sensitive analysis, and as such, + "same function" in this context means the same function declaration. + If the same member function of a type on two distinct instances are + called with the parameters, it will still be regarded as + "same function". + ``` + +- The same member field is accessed, or member method is called of the + two parameters, e.g. `a.foo()` and `b.foo()`. + +- Separate `return` statements return either of the parameters on + different code paths. +```` + +```{option} NamePrefixSuffixSilenceDissimilarityThreshold +The number of characters two parameter names might be different on *either* +the head or the tail end with the rest of the name the same so that the +warning about the two parameters are silenced. +Defaults to `1`. +Might be any positive integer. +If `0`, the filtering heuristic based on the parameters' names is turned +off. + +This option can be used to silence warnings about parameters where the +naming scheme indicates that the order of those parameters do not matter. + +For example, the parameters `LHS` and `RHS` are 1-dissimilar suffixes +of each other: `L` and `R` is the different character, while `HS` +is the common suffix. +Similarly, parameters `text1, text2, text3` are 1-dissimilar prefixes +of each other, with the numbers at the end being the dissimilar part. +If the value is at least `1`, such cases will not be reported. +``` + +## Limitations **This check is designed to check function signatures!** @@ -206,71 +203,72 @@ specializations are matched and analyzed. None of the following cases produce a diagnostic: -.. code-block:: c++ - - int printf(const char *Format, ...) { /* ... */ } - int someOldCFunction() { /* ... */ } +```c++ +int printf(const char *Format, ...) { /* ... */ } +int someOldCFunction() { /* ... */ } - template <typename T, typename U> - int add(T X, U Y) { return X + Y }; +template <typename T, typename U> +int add(T X, U Y) { return X + Y }; - void theseAreNotWarnedAbout() { - printf("%d %d\n", 1, 2); // Two ints passed, they could be swapped. - someOldCFunction(1, 2, 3); // Similarly, multiple ints passed. +void theseAreNotWarnedAbout() { + printf("%d %d\n", 1, 2); // Two ints passed, they could be swapped. + someOldCFunction(1, 2, 3); // Similarly, multiple ints passed. - add(1, 2); // Instantiates 'add<int, int>', but that's not a user-defined function. - } + add(1, 2); // Instantiates 'add<int, int>', but that's not a user-defined function. +} +``` Due to the limitation above, parameters which type are further dependent upon template instantiations to *prove* that they mix with another parameter's is not diagnosed. -.. code-block:: c++ - - template <typename T> - struct Vector { - typedef T element_type; - }; - - // Diagnosed: Explicit instantiation was done by the user, we can prove it - // is the same type. - void instantiated(int A, Vector<int>::element_type B) { /* ... */ } - - // Diagnosed: The two parameter types are exactly the same. - template <typename T> - void exact(typename Vector<T>::element_type A, - typename Vector<T>::element_type B) { /* ... */ } - - // Skipped: The two parameters are both 'T' but we cannot prove this - // without actually instantiating. - template <typename T> - void falseNegative(T A, typename Vector<T>::element_type B) { /* ... */ } - -In the context of *implicit conversions* (when `ModelImplicitConversions` is +```c++ +template <typename T> +struct Vector { + typedef T element_type; +}; + +// Diagnosed: Explicit instantiation was done by the user, we can prove it +// is the same type. +void instantiated(int A, Vector<int>::element_type B) { /* ... */ } + +// Diagnosed: The two parameter types are exactly the same. +template <typename T> +void exact(typename Vector<T>::element_type A, + typename Vector<T>::element_type B) { /* ... */ } + +// Skipped: The two parameters are both 'T' but we cannot prove this +// without actually instantiating. +template <typename T> +void falseNegative(T A, typename Vector<T>::element_type B) { /* ... */ } +``` + +In the context of *implicit conversions* (when +`ModelImplicitConversions` is enabled), the modelling performed by the check warns if the parameters are swappable and the swapped order matches implicit conversions. It does not model whether there exists an unrelated third type from which *both* parameters can be given in a function call. -This means that in the following example, even while ``strs()`` clearly carries +This means that in the following example, even while `strs()` clearly carries the possibility to be called with swapped arguments (as long as the arguments are string literals), will not be warned about. -.. code-block:: c++ - - struct String { - String(const char *Buf); - }; +```c++ +struct String { + String(const char *Buf); +}; - struct StringView { - StringView(const char *Buf); - operator const char *() const; - }; +struct StringView { + StringView(const char *Buf); + operator const char *() const; +}; - // Skipped: Directly swapping expressions of the two type cannot mix. - // (Note: StringView -> const char * -> String would be **two** - // user-defined conversions, which is disallowed by the language.) - void strs(String Str, StringView SV) { /* ... */ } +// Skipped: Directly swapping expressions of the two type cannot mix. +// (Note: StringView -> const char * -> String would be **two** +// user-defined conversions, which is disallowed by the language.) +void strs(String Str, StringView SV) { /* ... */ } - // Diagnosed: StringView implicitly converts to and from a buffer. - void cStr(StringView SV, const char *Buf() { /* ... */ } +// Diagnosed: StringView implicitly converts to and from a buffer. +void cStr(StringView SV, const char *Buf() { /* ... */ } +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst index 87c7edc30f2d4..297c1de33d465 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst @@ -1,16 +1,16 @@ -.. title:: clang-tidy - bugprone-empty-catch +```{title} clang-tidy - bugprone-empty-catch +``` -bugprone-empty-catch -==================== +# bugprone-empty-catch Detects and suggests addressing issues with empty catch statements. -.. code-block:: c++ - - try { - // Some code that can throw an exception - } catch(const std::exception&) { - } +```c++ +try { + // Some code that can throw an exception +} catch(const std::exception&) { +} +``` Having empty catch statements in a codebase can be a serious problem that developers should be aware of. Catch statements are used to handle exceptions @@ -23,21 +23,18 @@ exception but do nothing with it. This means that the exception is not handled properly, and the program continues to run as if nothing happened. This can lead to several issues, such as: -* *Hidden Bugs*: If an exception is caught and ignored, it can lead to hidden +- *Hidden Bugs*: If an exception is caught and ignored, it can lead to hidden bugs that are difficult to diagnose and fix. The root cause of the problem may not be apparent, and the program may continue to behave in unexpected ways. - -* *Security Issues*: Ignoring exceptions can lead to security issues, such as +- *Security Issues*: Ignoring exceptions can lead to security issues, such as buffer overflows or null pointer dereferences. Hackers can exploit these vulnerabilities to gain access to sensitive data or execute malicious code. - -* *Poor Code Quality*: Empty catch statements can indicate poor code quality +- *Poor Code Quality*: Empty catch statements can indicate poor code quality and a lack of attention to detail. This can make the codebase difficult to maintain and update, leading to longer development cycles and increased costs. - -* *Unreliable Code*: Code that ignores exceptions is often unreliable and can +- *Unreliable Code*: Code that ignores exceptions is often unreliable and can lead to unpredictable behavior. This can cause frustration for users and erode trust in the software. @@ -53,49 +50,49 @@ taking other appropriate action to ensure that the exception is not ignored. Here is an example: -.. code-block:: c++ - - try { - // Some code that can throw an exception - } catch (const std::exception& ex) { - // Properly handle the exception, e.g.: - std::cerr << "Exception caught: " << ex.what() << std::endl; - } +```c++ +try { + // Some code that can throw an exception +} catch (const std::exception& ex) { + // Properly handle the exception, e.g.: + std::cerr << "Exception caught: " << ex.what() << std::endl; +} +``` If the exception cannot be handled locally and needs to be propagated up the call stack, it should be re-thrown or new exception should be thrown. Here is an example: -.. code-block:: c++ - - try { - // Some code that can throw an exception - } catch (const std::exception& ex) { - // Re-throw the exception - throw; - } +```c++ +try { + // Some code that can throw an exception +} catch (const std::exception& ex) { + // Re-throw the exception + throw; +} +``` In some cases, catching the exception at this level may not be necessary, and it may be appropriate to let the exception propagate up the call stack. -This can be done simply by not using ``try/catch`` block. +This can be done simply by not using `try/catch` block. Here is an example: -.. code-block:: c++ +```c++ +void function() { + // Some code that can throw an exception +} - void function() { - // Some code that can throw an exception - } - - void callerFunction() { - try { - function(); - } catch (const std::exception& ex) { - // Handling exception on higher level - std::cerr << "Exception caught: " << ex.what() << std::endl; - } +void callerFunction() { + try { + function(); + } catch (const std::exception& ex) { + // Handling exception on higher level + std::cerr << "Exception caught: " << ex.what() << std::endl; } +} +``` Other potential solution to avoid empty catch statements is to modify the code to avoid throwing the exception in the first place. This can be achieved by @@ -105,45 +102,44 @@ need for try-catch blocks, the code becomes simpler and less error-prone. Here is an example: -.. code-block:: c++ - - // Old code: - try { - mapContainer["Key"].callFunction(); - } catch(const std::out_of_range&) { - } +```c++ +// Old code: +try { + mapContainer["Key"].callFunction(); +} catch(const std::out_of_range&) { +} - // New code - if (auto it = mapContainer.find("Key"); it != mapContainer.end()) { - it->second.callFunction(); - } +// New code +if (auto it = mapContainer.find("Key"); it != mapContainer.end()) { + it->second.callFunction(); +} +``` In conclusion, empty catch statements are a bad practice that can lead to hidden bugs, security issues, poor code quality, and unreliable code. By handling exceptions properly, developers can ensure that their code is robust, secure, and maintainable. -Options -------- - -.. option:: IgnoreCatchWithKeywords - - This option can be used to ignore specific catch statements containing - certain keywords. If a ``catch`` statement body contains (case-insensitive) - any of the keywords listed in this semicolon-separated option, then the - catch will be ignored, and no warning will be raised. - Default value: `@TODO;@FIXME`. - -.. option:: AllowEmptyCatchForExceptions - - This option can be used to ignore empty catch statements for specific - exception types. By default, the check will raise a warning if an empty - catch statement is detected, regardless of the type of exception being - caught. However, in certain situations, such as when a developer wants to - intentionally ignore certain exceptions or handle them in a different way, - it may be desirable to allow empty catch statements for specific exception - types. - To configure this option, a semicolon-separated list of exception type names - should be provided. If an exception type name in the list is caught in an - empty catch statement, no warning will be raised. - Default value: empty string. +## Options + +```{option} IgnoreCatchWithKeywords +This option can be used to ignore specific catch statements containing +certain keywords. If a `catch` statement body contains (case-insensitive) +any of the keywords listed in this semicolon-separated option, then the +catch will be ignored, and no warning will be raised. +Default value: `@TODO;@FIXME`. +``` + +```{option} AllowEmptyCatchForExceptions +This option can be used to ignore empty catch statements for specific +exception types. By default, the check will raise a warning if an empty +catch statement is detected, regardless of the type of exception being +caught. However, in certain situations, such as when a developer wants to +intentionally ignore certain exceptions or handle them in a different way, +it may be desirable to allow empty catch statements for specific exception +types. +To configure this option, a semicolon-separated list of exception type names +should be provided. If an exception type name in the list is caught in an +empty catch statement, no warning will be raised. +Default value: empty string. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst index 9c45cac525f7e..105a5622f9dd0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - bugprone-exception-copy-constructor-throws +```{title} clang-tidy - bugprone-exception-copy-constructor-throws +``` -bugprone-exception-copy-constructor-throws -========================================== +# bugprone-exception-copy-constructor-throws Checks whether a thrown object's copy constructor can throw. @@ -9,23 +9,21 @@ Exception objects are required to be copy constructible in C++. However, an exception's copy constructor should not throw to avoid potential issues when unwinding the stack. If an exception is thrown during stack unwinding (such as from a copy constructor of an exception object), the program will -terminate via ``std::terminate``. +terminate via `std::terminate`. -.. code-block:: c++ +```c++ +class SomeException { +public: + SomeException() = default; + SomeException(const SomeException&) { /* may throw */ } +}; - class SomeException { - public: - SomeException() = default; - SomeException(const SomeException&) { /* may throw */ } - }; +void f() { + throw SomeException(); // warning: thrown exception type's copy constructor can throw +} +``` - void f() { - throw SomeException(); // warning: thrown exception type's copy constructor can throw - } - -References ----------- +## References This check corresponds to the CERT C++ Coding Standard rule -`ERR60-CPP. Exception objects must be nothrow copy constructible -<https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/exceptions-and-error-handling-err/err60-cpp/>`_. +[ERR60-CPP. Exception objects must be nothrow copy constructible](https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/exceptions-and-error-handling-err/err60-cpp/). diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst index 0a0c21f62c7a0..c8a446bbd893f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst @@ -1,95 +1,94 @@ -.. title:: clang-tidy - bugprone-exception-escape +```{title} clang-tidy - bugprone-exception-escape +``` -bugprone-exception-escape -========================= +# bugprone-exception-escape Finds functions which may throw an exception directly or indirectly, but they should not. The functions which should not throw exceptions are the following: -* Destructors -* Move constructors -* Move assignment operators -* The ``main()`` functions -* ``swap()`` functions -* ``iter_swap()`` functions -* ``iter_move()`` functions -* Functions marked with ``throw()`` or ``noexcept`` -* Other functions given as option +- Destructors +- Move constructors +- Move assignment operators +- The `main()` functions +- `swap()` functions +- `iter_swap()` functions +- `iter_move()` functions +- Functions marked with `throw()` or `noexcept` +- Other functions given as option A destructor throwing an exception may result in undefined behavior, resource leaks or unexpected termination of the program. Throwing move constructor or move assignment also may result in undefined behavior or resource leak. The -``swap()`` operations expected to be non throwing most of the cases and they -are always possible to implement in a non throwing way. Non throwing ``swap()`` -operations are also used to create move operations. A throwing ``main()`` +`swap()` operations expected to be non throwing most of the cases and they +are always possible to implement in a non throwing way. Non throwing `swap()` +operations are also used to create move operations. A throwing `main()` function also results in unexpected termination. -Functions declared explicitly with ``noexcept(false)`` or ``throw(exception)`` +Functions declared explicitly with `noexcept(false)` or `throw(exception)` will be excluded from the analysis, as even though it is not recommended for -functions like ``swap()``, ``main()``, move constructors, move assignment +functions like `swap()`, `main()`, move constructors, move assignment operators and destructors, it is a clear indication of the developer's intention and should be respected. To check if these special functions are marked as potentially throwing, the check -:doc:`bugprone-unsafe-to-allow-exceptions <unsafe-to-allow-exceptions>` can be +{doc}`bugprone-unsafe-to-allow-exceptions <unsafe-to-allow-exceptions>` can be used. WARNING! This check may be expensive on large source files. -Options -------- - -.. option:: CheckDestructors - - When `true`, destructors are analyzed to not throw exceptions. - Default value is `true`. - -.. option:: CheckMoveMemberFunctions - - When `true`, move constructors and move assignment operators are analyzed - to not throw exceptions. Default value is `true`. - -.. option:: CheckMain - - When `true`, the ``main()`` function is analyzed to not throw exceptions. - Default value is `true`. - -.. option:: CheckNothrowFunctions - - When `true`, functions marked with ``noexcept`` or ``throw()`` exception - specifications are analyzed to not throw exceptions. Default value is `true`. - -.. option:: CheckedSwapFunctions - - Comma-separated list of swap function names which should not throw exceptions. - Default value is `swap,iter_swap,iter_move`. - -.. option:: FunctionsThatShouldNotThrow - - Comma separated list containing function names which should not throw. An - example value for this parameter can be ``WinMain`` which adds function - ``WinMain()`` in the Windows API to the list of the functions which should - not throw. Default value is an empty string. - -.. option:: IgnoredExceptions - - Comma separated list containing type names which are not counted as thrown - exceptions in the check. Default value is an empty string. - -.. option:: TreatFunctionsWithoutSpecificationAsThrowing - - Determines which functions are considered as throwing if they do not have - an explicit exception specification. It can be set to the following values: - - - `None` - The check will consider functions without an explicit exception - specification as throwing only if they have a visible definition which - can be deduced to throw. - - `OnlyUndefined` - The check will consider functions with only a declaration available and - no visible definition as throwing. - - `All` - The check will consider all functions without an explicit exception - specification (such as ``noexcept``) as throwing, even if they have a - visible definition and do not contain any throwing statements. - - Default value is `None`. +## Options + +```{option} CheckDestructors +When `true`, destructors are analyzed to not throw exceptions. +Default value is `true`. +``` + +```{option} CheckMoveMemberFunctions +When `true`, move constructors and move assignment operators are analyzed +to not throw exceptions. Default value is `true`. +``` + +```{option} CheckMain +When `true`, the `main()` function is analyzed to not throw exceptions. +Default value is `true`. +``` + +```{option} CheckNothrowFunctions +When `true`, functions marked with `noexcept` or `throw()` exception +specifications are analyzed to not throw exceptions. Default value is `true`. +``` + +```{option} CheckedSwapFunctions +Comma-separated list of swap function names which should not throw exceptions. +Default value is `swap,iter_swap,iter_move`. +``` + +```{option} FunctionsThatShouldNotThrow +Comma separated list containing function names which should not throw. An +example value for this parameter can be `WinMain` which adds function +`WinMain()` in the Windows API to the list of the functions which should +not throw. Default value is an empty string. +``` + +```{option} IgnoredExceptions +Comma separated list containing type names which are not counted as thrown +exceptions in the check. Default value is an empty string. +``` + +```{option} TreatFunctionsWithoutSpecificationAsThrowing +Determines which functions are considered as throwing if they do not have +an explicit exception specification. It can be set to the following values: + +- `None` + : The check will consider functions without an explicit exception + specification as throwing only if they have a visible definition which + can be deduced to throw. +- `OnlyUndefined` + : The check will consider functions with only a declaration available and + no visible definition as throwing. +- `All` + : The check will consider all functions without an explicit exception + specification (such as `noexcept`) as throwing, even if they have a + visible definition and do not contain any throwing statements. + +Default value is `None`. +``` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst index e8b3be35d9b66..1b77fe8d68b5e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst @@ -1,46 +1,46 @@ -.. title:: clang-tidy - bugprone-fold-init-type +```{title} clang-tidy - bugprone-fold-init-type +``` -bugprone-fold-init-type -======================= +# bugprone-fold-init-type The check flags type mismatches in -`folds <https://en.wikipedia.org/wiki/Fold_(higher-order_function)>`_ +[folds](<https://en.wikipedia.org/wiki/Fold_(higher-order_function)>) that might result in loss of precision. The check supports the following functions: -- ``std::accumulate`` -- ``std::reduce`` -- ``std::inner_product`` +- `std::accumulate` +- `std::reduce` +- `std::inner_product` These functions fold an input range into an initial value using the type of the -latter. By default, ``std::accumulate`` and ``std::reduce`` use ``operator+`` -while ``std::inner_product`` uses ``operator+`` and ``operator*``. This can +latter. By default, `std::accumulate` and `std::reduce` use `operator+` +while `std::inner_product` uses `operator+` and `operator*`. This can cause loss of precision through: - Truncation: The following code uses a floating point range and an int initial value, so truncation will happen at every application of - ``operator+`` and the result will be `0`, which might not be what the + `operator+` and the result will be `0`, which might not be what the user expected. -.. code-block:: c++ - - auto a = {0.5f, 0.5f, 0.5f, 0.5f}; - return std::accumulate(std::begin(a), std::end(a), 0); +```c++ +auto a = {0.5f, 0.5f, 0.5f, 0.5f}; +return std::accumulate(std::begin(a), std::end(a), 0); +``` - Overflow: The following code also returns `0`. -.. code-block:: c++ - - auto a = {65536LL * 65536 * 65536}; - return std::accumulate(std::begin(a), std::end(a), 0); +```c++ +auto a = {65536LL * 65536 * 65536}; +return std::accumulate(std::begin(a), std::end(a), 0); +``` The check handles overloads with the following transparent standard functors: -- ``std::plus`` -- ``std::minus`` -- ``std::multiplies`` -- ``std::divides`` -- ``std::bit_and`` -- ``std::bit_or`` -- ``std::bit_xor`` +- `std::plus` +- `std::minus` +- `std::multiplies` +- `std::divides` +- `std::bit_and` +- `std::bit_or` +- `std::bit_xor` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst index cd079a35a38e2..3672e810c4f10 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - bugprone-forwarding-reference-overload +```{title} clang-tidy - bugprone-forwarding-reference-overload +``` -bugprone-forwarding-reference-overload -====================================== +# bugprone-forwarding-reference-overload The check looks for perfect forwarding constructors that can hide copy or move constructors. If a non const lvalue reference is passed to the constructor, the @@ -13,53 +13,51 @@ Item 26. Consider the following example: -.. code-block:: c++ +```c++ +class Person { +public: + // C1: perfect forwarding ctor + template<typename T> + explicit Person(T&& n) {} - class Person { - public: - // C1: perfect forwarding ctor - template<typename T> - explicit Person(T&& n) {} + // C2: perfect forwarding ctor with parameter default value + template<typename T> + explicit Person(T&& n, int x = 1) {} - // C2: perfect forwarding ctor with parameter default value - template<typename T> - explicit Person(T&& n, int x = 1) {} + // C3: perfect forwarding ctor guarded with enable_if + template<typename T, typename X = enable_if_t<is_special<T>, void>> + explicit Person(T&& n) {} - // C3: perfect forwarding ctor guarded with enable_if - template<typename T, typename X = enable_if_t<is_special<T>, void>> - explicit Person(T&& n) {} + // C4: variadic perfect forwarding ctor guarded with enable_if + template<typename... A, + enable_if_t<is_constructible_v<tuple<string, int>, A&&...>, int> = 0> + explicit Person(A&&... a) {} - // C4: variadic perfect forwarding ctor guarded with enable_if - template<typename... A, - enable_if_t<is_constructible_v<tuple<string, int>, A&&...>, int> = 0> - explicit Person(A&&... a) {} + // C5: perfect forwarding ctor guarded with requires expression + template<typename T> + requires requires { is_special<T>; } + explicit Person(T&& n) {} - // C5: perfect forwarding ctor guarded with requires expression - template<typename T> - requires requires { is_special<T>; } - explicit Person(T&& n) {} + // C6: perfect forwarding ctor guarded with concept requirement + template<Special T> + explicit Person(T&& n) {} - // C6: perfect forwarding ctor guarded with concept requirement - template<Special T> - explicit Person(T&& n) {} - - // (possibly compiler generated) copy ctor - Person(const Person& rhs); - }; + // (possibly compiler generated) copy ctor + Person(const Person& rhs); +}; +``` The check warns for constructors C1 and C2, because those can hide copy and move constructors. We suppress warnings if the copy and the move constructors are both disabled (deleted or private), because there is nothing the perfect forwarding constructor could hide in this case. We also suppress warnings for -constructors like C3-C6 that are guarded with an ``enable_if`` or a concept, +constructors like C3-C6 that are guarded with an `enable_if` or a concept, assuming the programmer was aware of the possible hiding. -Background ----------- +## Background For deciding whether a constructor is guarded with enable_if, we consider the types of the constructor parameters, the default values of template type parameters and the types of non-type template parameters with a default literal value. If any -part of these types is ``std::enable_if`` or ``std::enable_if_t``, we assume the +part of these types is `std::enable_if` or `std::enable_if_t`, we assume the constructor is guarded. - diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/implicit-widening-of-multiplication-result.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/implicit-widening-of-multiplication-result.rst index efa77925a3fe6..bc3381f267017 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/implicit-widening-of-multiplication-result.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/implicit-widening-of-multiplication-result.rst @@ -1,7 +1,7 @@ -.. title:: clang-tidy - bugprone-implicit-widening-of-multiplication-result +```{title} clang-tidy - bugprone-implicit-widening-of-multiplication-result +``` -bugprone-implicit-widening-of-multiplication-result -=================================================== +# bugprone-implicit-widening-of-multiplication-result The check diagnoses instances where a result of a multiplication is implicitly widened, and suggests (with fix-it) to either silence the code by making @@ -11,59 +11,57 @@ to avoid the widening afterwards. This is mainly useful when operating on very large buffers. For example, consider: -.. code-block:: c++ - - void zeroinit(char* base, unsigned width, unsigned height) { - for(unsigned row = 0; row != height; ++row) { - for(unsigned col = 0; col != width; ++col) { - char* ptr = base + row * width + col; - *ptr = 0; - } +```c++ +void zeroinit(char* base, unsigned width, unsigned height) { + for(unsigned row = 0; row != height; ++row) { + for(unsigned col = 0; col != width; ++col) { + char* ptr = base + row * width + col; + *ptr = 0; } } +} +``` -This is fine in general, but if ``width * height`` overflows, -you end up wrapping back to the beginning of ``base`` +This is fine in general, but if `width * height` overflows, +you end up wrapping back to the beginning of `base` instead of processing the entire requested buffer. Indeed, this only matters for pretty large buffers (4GB+), but that can happen very easily for example in image processing, where for that to happen you "only" need a ~269MPix image. +## Options -Options -------- - -.. option:: UseCXXStaticCastsInCppSources - - When suggesting fix-its for C++ code, should C++-style ``static_cast<>()``'s - be suggested, or C-style casts. Defaults to `true`. - -.. option:: UseCXXHeadersInCppSources - - When suggesting to include the appropriate header in C++ code, - should ``<cstddef>`` header be suggested, or ``<stddef.h>``. - Defaults to `true`. +```{option} UseCXXStaticCastsInCppSources +When suggesting fix-its for C++ code, should C++-style `static_cast<>()`'s +be suggested, or C-style casts. Defaults to `true`. +``` -.. option:: IgnoreConstantIntExpr +```{option} UseCXXHeadersInCppSources +When suggesting to include the appropriate header in C++ code, +should `<cstddef>` header be suggested, or `<stddef.h>`. +Defaults to `true`. +``` - If the multiplication operands are compile-time constants (like literals or - are ``constexpr``) and fit within the source expression type, do not emit a - diagnostic or suggested fix. Only considers expressions where the source - expression is a signed integer type. Defaults to `false`. +```{option} IgnoreConstantIntExpr +If the multiplication operands are compile-time constants (like literals or +are `constexpr`) and fit within the source expression type, do not emit a +diagnostic or suggested fix. Only considers expressions where the source +expression is a signed integer type. Defaults to `false`. +``` Examples: -.. code-block:: c++ +```c++ +long mul(int a, int b) { + return a * b; // warning: performing an implicit widening conversion to type 'long' of a multiplication performed in type 'int' +} - long mul(int a, int b) { - return a * b; // warning: performing an implicit widening conversion to type 'long' of a multiplication performed in type 'int' - } - - char* ptr_add(char *base, int a, int b) { - return base + a * b; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' - } +char* ptr_add(char *base, int a, int b) { + return base + a * b; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' +} - char ptr_subscript(char *base, int a, int b) { - return base[a * b]; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' - } +char ptr_subscript(char *base, int a, int b) { + return base[a * b]; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' +} +``` _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
