[clang] [NFC][analyzer] Document the VirtualCall checkers (PR #131861)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 18 10:12:37 PDT 2025
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:


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
More information about the cfe-commits
mailing list