[clang-tools-extra] r247987 - Update clang-tidy documentation.
Angel Garcia Gomez via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 18 07:08:57 PDT 2015
Author: angelgarcia
Date: Fri Sep 18 09:08:57 2015
New Revision: 247987
URL: http://llvm.org/viewvc/llvm-project?rev=247987&view=rev
Log:
Update clang-tidy documentation.
Summary: Update documentation of the modernize module with clang-modernize's documentation.
Subscribers: cfe-commits, klimek, alexfh
Differential Revision: http://reviews.llvm.org/D12961
Modified:
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst?rev=247987&r1=247986&r2=247987&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-loop-convert.rst Fri Sep 18 09:08:57 2015
@@ -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<IncorrectRiskyTransformation>`
+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<int> 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<int>::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<int> 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<T>::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 ``<container element>.<member>``
+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<int> vec;
+
+ vector<int> *ptr = &vec;
+ vector<int> &ref = vec;
+
+ for (vector<int>::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;
+ }
+ }
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst?rev=247987&r1=247986&r2=247987&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-pass-by-value.rst Fri Sep 18 09:08:57 2015
@@ -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 `<utility>` it may be
+necessary to add this include. The transform will add the include directive when
+necessary.
+
+ .. code-block:: c++
+
+ #include <string>
+
+ 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 <string>
+
+ 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 <typename T> 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/
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst?rev=247987&r1=247986&r2=247987&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-replace-auto-ptr.rst Fri Sep 18 09:08:57 2015
@@ -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> int_ptr);
+ +void take_ownership_fn(std::unique_ptr<int> int_ptr);
+
+ void f(int x) {
+ - std::auto_ptr<int> a(new int(x));
+ - std::auto_ptr<int> b;
+ + std::unique_ptr<int> a(new int(x));
+ + std::unique_ptr<int> 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 `<utility>` 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<int> get_value();
+ const std::auto_ptr<int> & get_ref();
+
+ // <calling code (with migration)...>
+ -std::auto_ptr<int> a(get_value());
+ +std::unique_ptr<int> a(get_value()); // ok, unique_ptr constructed from auto_ptr
+
+ -const std::auto_ptr<int> & p = get_ptr();
+ +const std::unique_ptr<int> & p = get_ptr(); // won't compile
+
+* Non-instantiated templates aren't modified.
+
+ .. code-block:: c++
+
+ template <typename X>
+ void f() {
+ std::auto_ptr<X> 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<int> i, j;
- i = j;
-
-This code is transformed to:
-
-.. code:: c++
-
- std::unique_ptr<in> i, j;
- i = std::move(j);
+ // only 'f<int>()' (or similar) will trigger the replacement.
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst?rev=247987&r1=247986&r2=247987&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-auto.rst Fri Sep 18 09:08:57 2015
@@ -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<int>::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<int>::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<int>::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<int>::iterator I = MyVec.begin();
+ {
+ using namespace std;
+ list<int>::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<int, std::string>::const_iterator map_iterator;
+ map_iterator J = MyMap.begin();
+
+ // The following implementation-specific iterator type for which
+ // std::vector<int>::iterator could be a typedef would not be transformed.
+ __gnu_cxx::__normal_iterator<int*, std::vector> 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.
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst?rev=247987&r1=247986&r2=247987&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-nullptr.rst Fri Sep 18 09:08:57 2015
@@ -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``.
More information about the cfe-commits
mailing list