llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Donát Nagy (NagyDonat)

<details>
<summary>Changes</summary>

This commit documents `cplusplus.PureVirtualCall` (which was previously 
completely undocumented) and improves the documentation of 
`optin.cplusplus.VirtualCall` (which was very barebones).

Note that in this documentation I do not mention the checker options of 
`optin.cplusplus.VirtualCall`, because `ShowFixIts` is apparently in an 
unfinished alpha state (since 2019 when it was added by commit 
6cee434ed10ead6b7416ca5ee9592b2b207eeb0f) and `PureOnly` is a deprecated option 
that I'm going to remove very soon.

-----------

Screenshots of the HTML output:

![image](https://github.com/user-attachments/assets/10ddaf2b-45f5-44bf-8d49-fc0f023e8d31)

![image](https://github.com/user-attachments/assets/797292f9-f8d3-4c4b-a8b2-7f18881d3aa0)

In the introductory paragraphs I'm linking to [the relevant section of 
cppreference](https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction)
 because that seems to be an useful description of the issue that's being 
reported by this checker. (In general, I feel that it would be nice to add 
similar cppreference links in our docs when they're warranted.) 

---
Full diff: https://github.com/llvm/llvm-project/pull/131861.diff


1 Files Affected:

- (modified) clang/docs/analyzer/checkers.rst (+64-12) 


``````````diff
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 28286a8a5dba6..f3243d002bd35 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -543,6 +543,42 @@ Do not attempt to create a std::string from a null pointer
    }
  }
 
+.. _cplusplus-PureVirtualCall:
+
+cplusplus.PureVirtualCall (C++)
+"""""""""""""""""""""""""""""""
+
+When `virtual methods are called during construction and destruction
+<https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction>`__
+the polymorphism is restricted to the class that's being constructed or
+destructed because the more derived contexts are either not yet initialized or
+already destructed.
+
+This checker reports situations where this restricted polymorphism causes a
+call to a pure virtual method, which is undefined behavior. (See also the
+related checker :ref:`optin-cplusplus-VirtualCall` which reports situations
+where the restricted polymorphism affects a call and the called method is not
+pure virtual – but may be still surprising for the programmer.)
+
+.. code-block:: cpp
+
+ struct A {
+   virtual void getKind() = 0;
+
+   A() {
+     // warn: This calls the pure virtual method A::getKind().
+     log << "Constructing " << getKind();
+   }
+   virtual ~A() {
+     releaseResources();
+   }
+   void releaseResources() {
+     // warn: This can call the pure virtual method A::getKind() when this is
+     // called from the destructor.
+     callSomeFunction(getKind())
+   }
+ };
+
 .. _deadcode-checkers:
 
 deadcode
@@ -833,24 +869,40 @@ This checker has several options which can be set from 
command line (e.g.
 
 optin.cplusplus.VirtualCall (C++)
 """""""""""""""""""""""""""""""""
-Check virtual function calls during construction or destruction.
+
+When `virtual methods are called during construction and destruction
+<https://en.cppreference.com/w/cpp/language/virtual#During_construction_and_destruction>`__
+the polymorphism is restricted to the class that's being constructed or
+destructed because the more derived contexts are either not yet initialized or
+already destructed.
+
+Although this behavior is well-defined, it can surprise the programmer and
+cause unintended behavior, so this checker reports calls that appear to be
+virtual calls but can be affected by this restricted polymorphism.
+
+Note that situations where this restricted polymorphism causes a call to a pure
+virtual method (which is definitely invalid, triggers undefined behavior) are
+**reported by another checker:** :ref:`cplusplus-PureVirtualCall` and **this
+checker does not report them**.
 
 .. code-block:: cpp
 
- class A {
- public:
+ struct A {
+   virtual void getKind();
+
    A() {
-     f(); // warn
+     // warn: This calls A::getKind() even if we are constructing an instance
+     // of a different class that is derived from A.
+     log << "Constructing " << getKind();
    }
-   virtual void f();
- };
-
- class A {
- public:
-   ~A() {
-     this->f(); // warn
+   virtual ~A() {
+     releaseResources();
+   }
+   void releaseResources() {
+     // warn: This can be called within ~A() and calls A::getKind() even if
+     // we are destructing a class that is derived from A.
+     callSomeFunction(getKind())
    }
-   virtual void f();
  };
 
 .. _optin-mpi-MPI-Checker:

``````````

</details>


https://github.com/llvm/llvm-project/pull/131861
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to