[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