[clang-tools-extra] [clang-tidy] Unsafe CRTP check (PR #82403)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 23 12:25:25 PST 2024
================
@@ -0,0 +1,232 @@
+// RUN: %check_clang_tidy %s bugprone-unsafe-crtp %t
+
+namespace class_implicit_ctor {
+template <typename T>
+class CRTP {};
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-unsafe-crtp]
+// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private
+// CHECK-FIXES: CRTP() = default;
+
+class A : CRTP<A> {};
+} // namespace class_implicit_ctor
+
+namespace class_uncostructible {
+template <typename T>
+class CRTP {
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class [bugprone-unsafe-crtp]
+// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider declaring the derived class as friend
+// CHECK-FIXES: friend T;
----------------
isuckatcs wrote:
Since checking if a public or protected function can construct the class would require path sensitive analysis I'd add this example as a limitation to the docs.
E.g.:
```c++
template <class T>
class CRTP
{
CRTP(int I) {}
public:
static void hardToDetect(CRTP* Escape, int X) {
if(X > 2) {
Escape = new CRTP{1};
}
}
};
```
Another solution would be to walk the callgraph, but that would just pollute the user with non-meaningful warnings.
E.g.:
```c++
template <class T>
class CRTP
{
CRTP(int I) {}
public:
void hardToDetect(CRTP* Escape, int X) {
if(CRTP && X > 2) {
Escape = new CRTP{1};
}
}
void warning1() { hardToDetect(nullptr, 3); }
void warning2() { warning1(); }
void warning3() { warning2(); }
};
```
In the above `CRTP` we could report a warning for every function, right?
https://github.com/llvm/llvm-project/pull/82403
More information about the cfe-commits
mailing list