brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.6 KiB · 59ccab4 Raw
277 lines · plain
1.. title:: clang-tidy - bugprone-easily-swappable-parameters2 3bugprone-easily-swappable-parameters4====================================5 6Finds function definitions where parameters of convertible types follow each7other directly, making call sites prone to calling the function with8swapped (or badly ordered) arguments.9 10.. code-block:: c++11 12    void drawPoint(int X, int Y) { /* ... */ }13    FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ }14 15A potential call like ``drawPoint(-2, 5)`` or16``openPath("a.txt", "tmp", Read)`` is perfectly legal from the language's17perspective, but might not be what the developer of the function intended.18 19More elaborate and type-safe constructs, such as opaque typedefs or strong20types should be used instead, to prevent a mistaken order of arguments.21 22.. code-block:: c++23 24    struct Coord2D { int X; int Y; };25    void drawPoint(const Coord2D Pos) { /* ... */ }26 27    FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ }28 29Due to the potentially elaborate refactoring and API-breaking that is necessary30to strengthen the type safety of a project, no automatic fix-its are offered.31 32Options33-------34 35Extension/relaxation options36^^^^^^^^^^^^^^^^^^^^^^^^^^^^37 38Relaxation (or extension) options can be used to broaden the scope of the39analysis and fine-tune the enabling of more mixes between types.40Some mixes may depend on coding style or preference specific to a project,41however, it should be noted that enabling *all* of these relaxations model the42way of mixing at call sites the most.43These options are expected to make the check report for more functions, and44report longer mixable ranges.45 46.. option:: QualifiersMix47 48    Whether to consider parameters of some *cvr-qualified* ``T`` and a49    differently *cvr-qualified* ``T`` (i.e. ``T`` and ``const T``, ``const T``50    and ``volatile T``, etc.) mixable between one another.51    If `false`, the check will consider differently qualified types unmixable.52    `True` turns the warnings on.53    Defaults to `false`.54 55    The following example produces a diagnostic only if `QualifiersMix` is56    enabled:57 58    .. code-block:: c++59 60        void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ }61 62.. option:: ModelImplicitConversions63 64    Whether to consider parameters of type ``T`` and ``U`` mixable if there65    exists an implicit conversion from ``T`` to ``U`` and ``U`` to ``T``.66    If `false`, the check will not consider implicitly convertible types for67    mixability.68    `True` turns warnings for implicit conversions on.69    Defaults to `true`.70 71    The following examples produce a diagnostic only if72    `ModelImplicitConversions` is enabled:73 74    .. code-block:: c++75 76        void fun(int Int, double Double) { /* ... */ }77        void compare(const char *CharBuf, std::string String) { /* ... */ }78 79    .. note::80 81        Changing the qualifiers of an expression's type (e.g. from ``int`` to82        ``const int``) is defined as an *implicit conversion* in the C++83        Standard.84        However, the check separates this decision-making on the mixability of85        differently qualified types based on whether `QualifiersMix` was86        enabled.87 88        For example, the following code snippet will only produce a diagnostic89        if **both** `QualifiersMix` and `ModelImplicitConversions` are enabled:90 91        .. code-block:: c++92 93            void fun2(int Int, const double Double) { /* ... */ }94 95Filtering options96^^^^^^^^^^^^^^^^^97 98Filtering options can be used to lessen the size of the diagnostics emitted by99the checker, whether the aim is to ignore certain constructs or dampen the100noisiness.101 102.. option:: MinimumLength103 104    The minimum length required from an adjacent parameter sequence to be105    diagnosed.106    Defaults to `2`.107    Might be any positive integer greater or equal to `2`.108    If `0` or `1` is given, the default value `2` will be used instead.109 110    For example, if `3` is specified, the examples above will not be matched.111 112.. option:: IgnoredParameterNames113 114    The list of parameter **names** that should never be considered part of a115    swappable adjacent parameter sequence.116    The value is a `;`-separated list of names.117    To ignore unnamed parameters, add `""` to the list verbatim (not the118    empty string, but the two quotes, potentially escaped!).119    **This option is case-sensitive!**120 121    By default, the following parameter names, and their Uppercase-initial122    variants are ignored:123    `""` (unnamed parameters), `iterator`, `begin`, `end`, `first`, `last`,124    `lhs`, `rhs`.125 126.. option:: IgnoredParameterTypeSuffixes127 128    The list of parameter **type name suffixes** that should never be129    considered part of a swappable adjacent parameter sequence.130    Parameters which type, as written in the source code, end with an element131    of this option will be ignored.132    The value is a `;`-separated list of names.133    **This option is case-sensitive!**134 135    By default, the following, and their lowercase-initial variants are ignored:136    `bool`, `It`, `Iterator`, `InputIt`, `ForwardIt`, `BidirIt`, `RandomIt`,137    `random_iterator`, `ReverseIt`, `reverse_iterator`,138    `reverse_const_iterator`, `RandomIt`, `random_iterator`, `ReverseIt`,139    `reverse_iterator`, `reverse_const_iterator`, `Const_Iterator`,140    `ConstIterator`, `const_reverse_iterator`, `ConstReverseIterator`.141    In addition, `_Bool` (but not `_bool`) is also part of the default value.142 143.. option:: SuppressParametersUsedTogether144 145    Suppresses diagnostics about parameters that are used together or in a146    similar fashion inside the function's body.147    Defaults to `true`.148    Specifying `false` will turn off the heuristics.149 150    Currently, the following heuristics are implemented which will suppress the151    warning about the parameter pair involved:152 153    * The parameters are used in the same expression, e.g. ``f(a, b)`` or154      ``a < b``.155    * The parameters are further passed to the same function to the same156      parameter of that function, of the same overload.157      E.g. ``f(a, 1)`` and ``f(b, 2)`` to some ``f(T, int)``.158 159      .. note::160 161        The check does not perform path-sensitive analysis, and as such,162        "same function" in this context means the same function declaration.163        If the same member function of a type on two distinct instances are164        called with the parameters, it will still be regarded as165        "same function".166 167    * The same member field is accessed, or member method is called of the168      two parameters, e.g. ``a.foo()`` and ``b.foo()``.169    * Separate ``return`` statements return either of the parameters on170      different code paths.171 172.. option:: NamePrefixSuffixSilenceDissimilarityThreshold173 174    The number of characters two parameter names might be different on *either*175    the head or the tail end with the rest of the name the same so that the176    warning about the two parameters are silenced.177    Defaults to `1`.178    Might be any positive integer.179    If `0`, the filtering heuristic based on the parameters' names is turned180    off.181 182    This option can be used to silence warnings about parameters where the183    naming scheme indicates that the order of those parameters do not matter.184 185    For example, the parameters ``LHS`` and ``RHS`` are 1-dissimilar suffixes186    of each other: ``L`` and ``R`` is the different character, while ``HS``187    is the common suffix.188    Similarly, parameters ``text1, text2, text3`` are 1-dissimilar prefixes189    of each other, with the numbers at the end being the dissimilar part.190    If the value is at least `1`, such cases will not be reported.191 192 193Limitations194-----------195 196**This check is designed to check function signatures!**197 198The check does not investigate functions that are generated by the compiler199in a context that is only determined from a call site.200These cases include variadic functions, functions in C code that do not have201an argument list, and C++ template instantiations.202Most of these cases, which are otherwise swappable from a caller's standpoint,203have no way of getting "fixed" at the definition point.204In the case of C++ templates, only primary template definitions and explicit205specializations are matched and analyzed.206 207None of the following cases produce a diagnostic:208 209.. code-block:: c++210 211    int printf(const char *Format, ...) { /* ... */ }212    int someOldCFunction() { /* ... */ }213 214    template <typename T, typename U>215    int add(T X, U Y) { return X + Y };216 217    void theseAreNotWarnedAbout() {218        printf("%d %d\n", 1, 2);   // Two ints passed, they could be swapped.219        someOldCFunction(1, 2, 3); // Similarly, multiple ints passed.220 221        add(1, 2); // Instantiates 'add<int, int>', but that's not a user-defined function.222    }223 224Due to the limitation above, parameters which type are further dependent upon225template instantiations to *prove* that they mix with another parameter's is226not diagnosed.227 228.. code-block:: c++229 230    template <typename T>231    struct Vector {232      typedef T element_type;233    };234 235    // Diagnosed: Explicit instantiation was done by the user, we can prove it236    // is the same type.237    void instantiated(int A, Vector<int>::element_type B) { /* ... */ }238 239    // Diagnosed: The two parameter types are exactly the same.240    template <typename T>241    void exact(typename Vector<T>::element_type A,242               typename Vector<T>::element_type B) { /* ... */ }243 244    // Skipped: The two parameters are both 'T' but we cannot prove this245    // without actually instantiating.246    template <typename T>247    void falseNegative(T A, typename Vector<T>::element_type B) { /* ... */ }248 249In the context of *implicit conversions* (when `ModelImplicitConversions` is250enabled), the modelling performed by the check251warns if the parameters are swappable and the swapped order matches implicit252conversions.253It does not model whether there exists an unrelated third type from which254*both* parameters can be given in a function call.255This means that in the following example, even while ``strs()`` clearly carries256the possibility to be called with swapped arguments (as long as the arguments257are string literals), will not be warned about.258 259.. code-block:: c++260 261    struct String {262        String(const char *Buf);263    };264 265    struct StringView {266        StringView(const char *Buf);267        operator const char *() const;268    };269 270    // Skipped: Directly swapping expressions of the two type cannot mix.271    // (Note: StringView -> const char * -> String would be **two**272    // user-defined conversions, which is disallowed by the language.)273    void strs(String Str, StringView SV) { /* ... */ }274 275    // Diagnosed: StringView implicitly converts to and from a buffer.276    void cStr(StringView SV, const char *Buf() { /* ... */ }277