Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst @@ -1,4 +1,253 @@ modernize-loop-convert ====================== +This check converts ``for(...; ...; ...)`` loops to use the new range-based +loops in C++11. +Three kinds of loops can be converted: + +- Loops over statically allocated arrays. +- Loops over containers, using iterators. +- Loops over array-like containers, using ``operator[]`` and ``at()``. + +MinConfidence option +==================== + +risky +----- + +In loops where the container expression is more complex than just a +reference to a declared expression (a variable, function, enum, etc.), +and some part of it appears elsewhere in the loop, we lower our confidence +in the transformation due to the increased risk of changing semantics. +Transformations for these loops are marked as `risky`, and thus will only +be converted if the minimum required confidence level is set to ``risky``. + +.. code-block:: c++ + + int arr[10][20]; + int l = 5; + + for (int j = 0; j < 20; ++j) + int k = arr[l][j] + l; // using l outside arr[l] is considered risky + + for (int i = 0; i < obj.getVector().size(); ++i) + obj.foo(10); // using 'obj' is considered risky + +See +:ref:`Range-based loops evaluate end() only once` +for an example of an incorrect transformation when the minimum required confidence +level is set to `risky`. + +reasonable (Default) +-------------------- + +If a loop calls ``.end()`` or ``.size()`` after each iteration, the +transformation for that loop is marked as `reasonable`, and thus will +be converted if the required confidence level is set to ``reasonable`` +(default) or lower. + +.. code-block:: c++ + + // using size() is considered reasonable + for (int i = 0; i < container.size(); ++i) + cout << container[i]; + +safe +---- + +Any other loops that do not match the above criteria to be marked as +`risky` or `reasonable` are marked `safe`, and thus will be converted +if the required confidence level is set to ``safe`` or lower. + +.. code-block:: c++ + + int arr[] = {1,2,3}; + + for (int i = 0; i < 3; ++i) + cout << arr[i]; + +Example +======= + +Original: + +.. code-block:: c++ + + const int N = 5; + int arr[] = {1,2,3,4,5}; + vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + // safe transform + for (int i = 0; i < N; ++i) + cout << arr[i]; + + // reasonable transform + for (vector::iterator it = v.begin(); it != v.end(); ++it) + cout << *it;* + + // reasonable transform + for (int i = 0; i < v.size(); ++i) + cout << v[i]; + +After transformation with confidence level set to ``reasonable`` (default): + +.. code-block:: c++ + + const int N = 5; + int arr[] = {1,2,3,4,5}; + vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + // safe transform + for (auto & elem : arr) + cout << elem; + + // reasonable transform + for (auto & elem : v) + cout << elem; + + // reasonable transform + for (auto & elem : v) + cout << elem; + +Limitations +=========== + +There are certain situations where the tool may erroneously perform +transformations that remove information and change semantics. Users of the tool +should be aware of the behaviour and limitations of the transform outlined by +the cases below. + +Comments inside loop headers +---------------------------- + +Comments inside the original loop header are ignored and deleted when +transformed. + +.. code-block:: c++ + + for (int i = 0; i < N; /* This will be deleted */ ++i) { } + +Range-based loops evaluate end() only once +------------------------------------------ + +The C++11 range-based for loop calls ``.end()`` only once during the +initialization of the loop. If in the original loop ``.end()`` is called after +each iteration the semantics of the transformed loop may differ. + +.. code-block:: c++ + + // The following is semantically equivalent to the C++11 range-based for loop, + // therefore the semantics of the header will not change. + for (iterator it = container.begin(), e = container.end(); it != e; ++it) { } + + // Instead of calling .end() after each iteration, this loop will be + // transformed to call .end() only once during the initialization of the loop, + // which may affect semantics. + for (iterator it = container.begin(); it != container.end(); ++it) { } + +.. _IncorrectRiskyTransformation: + +As explained above, calling member functions of the container in the body +of the loop is considered `risky`. If the called member function modifies the +container the semantics of the converted loop will differ due to ``.end()`` +being called only once. + +.. code-block:: c++ + + bool flag = false; + for (vector::iterator it = vec.begin(); it != vec.end(); ++it) { + // Add a copy of the first element to the end of the vector. + if (!flag) { + // This line makes this transformation 'risky'. + vec.push_back(*it); + flag = true; + } + cout << *it; + } + +The original code above prints out the contents of the container including the +newly added element while the converted loop, shown below, will only print the +original contents and not the newly added element. + +.. code-block:: c++ + + bool flag = false; + for (auto & elem : vec) { + // Add a copy of the first element to the end of the vector. + if (!flag) { + // This line makes this transformation 'risky' + vec.push_back(elem); + flag = true; + } + cout << elem; + } + +Semantics will also be affected if ``.end()`` has side effects. For example, in +the case where calls to ``.end()`` are logged the semantics will change in the +transformed loop if ``.end()`` was originally called after each iteration. + +.. code-block:: c++ + + iterator end() { + num_of_end_calls++; + return container.end(); + } + +Overloaded operator->() with side effects +----------------------------------------- + +Similarly, if ``operator->()`` was overloaded to have side effects, such as +logging, the semantics will change. If the iterator's ``operator->()`` was used +in the original loop it will be replaced with ``.`` +instead due to the implicit dereference as part of the range-based for loop. +Therefore any side effect of the overloaded ``operator->()`` will no longer be +performed. + +.. code-block:: c++ + + for (iterator it = c.begin(); it != c.end(); ++it) { + it->func(); // Using operator->() + } + // Will be transformed to: + for (auto & elem : c) { + elem.func(); // No longer using operator->() + } + +Pointers and references to containers +------------------------------------- + +While most of the transform's risk analysis is dedicated to determining whether +the iterator or container was modified within the loop, it is possible to +circumvent the analysis by accessing and modifying the container through a +pointer or reference. + +If the container were directly used instead of using the pointer or reference +the following transformation would have only been applied at the ``risky`` +level since calling a member function of the container is considered `risky`. +The transform cannot identify expressions associated with the container that are +different than the one used in the loop header, therefore the transformation +below ends up being performed at the ``safe`` level. + +.. code-block:: c++ + + vector vec; + + vector *ptr = &vec; + vector &ref = vec; + + for (vector::iterator it = vec.begin(), e = vec.end(); it != e; ++it) { + if (!flag) { + // Accessing and modifying the container is considered risky, but the risk + // level is not raised here. + ptr->push_back(*it); + ref.push_back(*it); + flag = true; + } + } Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst @@ -1,4 +1,151 @@ modernize-pass-by-value ======================= +With move semantics added to the language and the standard library updated with +move constructors added for many types it is now interesting to take an argument +directly by value, instead of by const-reference, and then copy. This +transformation allows the compiler to take care of choosing the best way to +construct the copy. +The transformation is usually beneficial when the calling code passes an +*rvalue* and assumes the move construction is a cheap operation. This short +example illustrates how the construction of the value happens: + + .. code-block:: c++ + + void foo(std::string s); + std::string get_str(); + + void f(const std::string &str) { + foo(str); // lvalue -> copy construction + foo(get_str()); // prvalue -> move construction + } + +.. note:: + + Currently, only constructors are transformed to make use of pass-by-value. + Contributions that handle other situations are welcome! + + +Pass-by-value in constructors +----------------------------- + +Replaces the uses of const-references constructor parameters that are copied +into class fields. The parameter is then moved with `std::move()`. + +Since `std::move()` is a library function declared in `` it may be +necessary to add this include. The transform will add the include directive when +necessary. + + .. code-block:: c++ + + #include + + class Foo { + public: + - Foo(const std::string &Copied, const std::string &ReadOnly) + - : Copied(Copied), ReadOnly(ReadOnly) + + Foo(std::string Copied, const std::string &ReadOnly) + + : Copied(std::move(Copied)), ReadOnly(ReadOnly) + {} + + private: + std::string Copied; + const std::string &ReadOnly; + }; + + std::string get_cwd(); + + void f(const std::string &Path) { + // The parameter corresponding to 'get_cwd()' is move-constructed. By + // using pass-by-value in the Foo constructor we managed to avoid a + // copy-construction. + Foo foo(get_cwd(), Path); + } + + +If the parameter is used more than once no transformation is performed since +moved objects have an undefined state. It means the following code will be left +untouched: + +.. code-block:: c++ + + #include + + void pass(const std::string &S); + + struct Foo { + Foo(const std::string &S) : Str(S) { + pass(S); + } + + std::string Str; + }; + + +Known limitations +^^^^^^^^^^^^^^^^^ + +A situation where the generated code can be wrong is when the object referenced +is modified before the assignment in the init-list through a "hidden" reference. + +Example: + +.. code-block:: c++ + + std::string s("foo"); + + struct Base { + Base() { + s = "bar"; + } + }; + + struct Derived : Base { + - Derived(const std::string &S) : Field(S) + + Derived(std::string S) : Field(std::move(S)) + { } + + std::string Field; + }; + + void f() { + - Derived d(s); // d.Field holds "bar" + + Derived d(s); // d.Field holds "foo" + } + + +Note about delayed template parsing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When delayed template parsing is enabled, constructors part of templated +contexts; templated constructors, constructors in class templates, constructors +of inner classes of template classes, etc., are not transformed. Delayed +template parsing is enabled by default on Windows as a Microsoft extension: +`Clang Compiler User’s Manual - Microsoft extensions`_. + +Delayed template parsing can be enabled using the `-fdelayed-template-parsing` +flag and disabled using `-fno-delayed-template-parsing`. + +Example: + +.. code-block:: c++ + + template class C { + std::string S; + + public: + = // using -fdelayed-template-parsing (default on Windows) + = C(const std::string &S) : S(S) {} + + + // using -fno-delayed-template-parsing (default on non-Windows systems) + + C(std::string S) : S(std::move(S)) {} + }; + +.. _Clang Compiler User’s Manual - Microsoft extensions: http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions + +.. seealso:: + + For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_. + + .. _Want Speed? Pass by Value: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst @@ -1,29 +1,71 @@ modernize-replace-auto-ptr ========================== +This check replaces the uses of the deprecated class ``std::auto_ptr`` by +``std::unique_ptr`` (introduced in C++11). The transfer of ownership, done +by the copy-constructor and the assignment operator, is changed to match +``std::unique_ptr`` usage by using explicit calls to ``std::move()``. + +Migration example: + +.. code-block:: c++ + + -void take_ownership_fn(std::auto_ptr int_ptr); + +void take_ownership_fn(std::unique_ptr int_ptr); + + void f(int x) { + - std::auto_ptr a(new int(x)); + - std::auto_ptr b; + + std::unique_ptr a(new int(x)); + + std::unique_ptr b; + + - b = a; + - take_ownership_fn(b); + + b = std::move(a); + + take_ownership_fn(std::move(b)); + } + +Since `std::move()` is a library function declared in `` it may be +necessary to add this include. The transform will add the include directive when +necessary. + +Known Limitations +================= +* If headers modification is not activated or if a header is not allowed to be + changed this transform will produce broken code (compilation error), where the + the headers' code will stay unchanged while the code using them will be + changed. + +* Client code that declares a reference to an ``std::auto_ptr`` coming from code + that can't be migrated (such as a header coming from a 3\ :sup:`rd` party + library) will produce a compilation error after migration. This is because the + type of the reference will be changed to ``std::unique_ptr`` but the type + returned by the library won't change, binding a reference to + ``std::unique_ptr`` from an ``std::auto_ptr``. This pattern doesn't make much + sense and usually ``std::auto_ptr`` are stored by value (otherwise what is the + point in using them instead of a reference or a pointer?). + + .. code-block:: c++ + + // <3rd-party header...> + std::auto_ptr get_value(); + const std::auto_ptr & get_ref(); + + // + -std::auto_ptr a(get_value()); + +std::unique_ptr a(get_value()); // ok, unique_ptr constructed from auto_ptr + + -const std::auto_ptr & p = get_ptr(); + +const std::unique_ptr & p = get_ptr(); // won't compile + +* Non-instantiated templates aren't modified. + + .. code-block:: c++ + + template + void f() { + std::auto_ptr p; + } -Transforms the deprecated ``std::auto_ptr`` into the C++11 ``std::unique_ptr``. - -Note that both the ``std::auto_ptr`` type and the transfer of ownership are -transformed. ``std::auto_ptr`` provides two ways to transfer the ownership, -the copy-constructor and the assignment operator. Unlike most classes these -operations do not 'copy' the resource but they 'steal' it. -``std::unique_ptr`` uses move semantics instead, which makes the intent of -transferring the resource explicit. This difference between the two smart -pointers requeres to wrap the copy-ctor and assign-operator with -``std::move()``. - -For example, given: - -.. code:: c++ - - std::auto_ptr i, j; - i = j; - -This code is transformed to: - -.. code:: c++ - - std::unique_ptr i, j; - i = std::move(j); + // only 'f()' (or similar) will trigger the replacement. Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst @@ -1,4 +1,134 @@ modernize-use-auto ================== +This check is responsible for using the ``auto`` type specifier for +variable declarations to *improve code readability and maintainability*. +For example: + +.. code-block:: c++ + + std::vector::iterator I = my_container.begin(); + + // transforms to: + + auto I = my_container.begin(); + +The ``auto`` type specifier will only be introduced in situations where the +variable type matches the type of the initializer expression. In other words +``auto`` should deduce the same type that was originally spelled in the source. +However, not every situation should be transformed: + +.. code-block:: c++ + + int val = 42; + InfoStruct &I = SomeObject.getInfo(); + + // Should not become: + + auto val = 42; + auto &I = SomeObject.getInfo(); + +In this example using ``auto`` for builtins doesn't improve readability. In +other situations it makes the code less self-documenting impairing readability +and maintainability. As a result, ``auto`` is used only introduced in specific +situations described below. + +Iterators +========= + +Iterator type specifiers tend to be long and used frequently, especially in +loop constructs. Since the functions generating iterators have a common format, +the type specifier can be replaced without obscuring the meaning of code while +improving readability and maintainability. + +.. code-block:: c++ + + for (std::vector::iterator I = my_container.begin(), + E = my_container.end(); + I != E; ++I) { + } + + // becomes + + for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) { + } + +The transform will only replace iterator type-specifiers when all of the +following conditions are satisfied: +* The iterator is for one of the standard container in ``std`` namespace: + + * ``array`` + + * ``deque`` + + * ``forward_list`` + + * ``list`` + + * ``vector`` + + * ``map`` + + * ``multimap`` + + * ``set`` + + * ``multiset`` + + * ``unordered_map`` + + * ``unordered_multimap`` + + * ``unordered_set`` + + * ``unordered_multiset`` + + * ``queue`` + + * ``priority_queue`` + + * ``stack`` + +* The iterator is one of the possible iterator types for standard containers: + + * ``iterator`` + + * ``reverse_iterator`` + + * ``const_iterator`` + + * ``const_reverse_iterator`` + +* In addition to using iterator types directly, typedefs or other ways of + referring to those types are also allowed. However, implementation-specific + types for which a type like ``std::vector::iterator`` is itself a + typedef will not be transformed. Consider the following examples: + +.. code-block:: c++ + + // The following direct uses of iterator types will be transformed. + std::vector::iterator I = MyVec.begin(); + { + using namespace std; + list::iterator I = MyList.begin(); + } + + // The type specifier for J would transform to auto since it's a typedef + // to a standard iterator type. + typedef std::map::const_iterator map_iterator; + map_iterator J = MyMap.begin(); + + // The following implementation-specific iterator type for which + // std::vector::iterator could be a typedef would not be transformed. + __gnu_cxx::__normal_iterator K = MyVec.begin(); + +* The initializer for the variable being declared is not a braced initializer + list. Otherwise, use of ``auto`` would cause the type of the variable to be + deduced as``std::initializer_list``. + +Known Limitations +================= +* If the initializer is an explicit conversion constructor, the transform will + not replace the type specifier even though it would be safe to do so. +* User-defined iterators are not handled at this time. Index: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst =================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst +++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst @@ -1,4 +1,65 @@ modernize-use-nullptr ===================== +The check converts the usage of null pointer constants (eg. ``NULL``, ``0``) +to use the new C++11 ``nullptr`` keyword. +Example +======= + +.. code-block:: c++ + + void assignment() { + char *a = NULL; + char *b = 0; + char c = 0; + } + + int *ret_ptr() { + return 0; + } + + +transforms to: + +.. code-block:: c++ + + void assignment() { + char *a = nullptr; + char *b = nullptr; + char c = 0; + } + + int *ret_ptr() { + return nullptr; + } + + +User defined macros +=================== + +By default this transform will only replace the ``NULL`` macro and will skip any +user-defined macros that behaves like ``NULL``. The user can use the +:option:``UserNullMacros`` option to specify a comma-separated list of macro +names that will be transformed along with ``NULL``. + +Example +------- + +.. code-block:: c++ + + #define MY_NULL (void*)0 + void assignment() { + void *p = MY_NULL; + } + +transforms to: + +.. code-block:: c++ + + #define MY_NULL NULL + void assignment() { + int *p = nullptr; + } + + if the ``UserNullMacros`` option is set to ``MY_NULL``.