[clang-tools-extra] [clang-tidy] Unsafe CRTP check (PR #82403)

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 20 13:22:11 PST 2024


================
@@ -0,0 +1,167 @@
+//===--- UnsafeCrtpCheck.cpp - clang-tidy ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UnsafeCrtpCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+namespace {
+// Finds a node if it's already a bound node.
+AST_MATCHER_P(CXXRecordDecl, isBoundNode, std::string, ID) {
+  return Builder->removeBindings(
+      [&](const ast_matchers::internal::BoundNodesMap &Nodes) {
+        const auto *BoundRecord = Nodes.getNodeAs<CXXRecordDecl>(ID);
+        return BoundRecord != &Node;
+      });
+}
+
+bool hasPrivateConstructor(const CXXRecordDecl *RD) {
+  for (auto &&Ctor : RD->ctors()) {
+    if (Ctor->getAccess() == AS_private)
+      return true;
+  }
+
+  return false;
+}
+
+bool isDerivedParameterBefriended(const CXXRecordDecl *CRTP,
+                                  const NamedDecl *Param) {
+  for (auto &&Friend : CRTP->friends()) {
+    const auto *TTPT =
+        dyn_cast<TemplateTypeParmType>(Friend->getFriendType()->getType());
+
+    if (TTPT && TTPT->getDecl() == Param)
+      return true;
+  }
+
+  return false;
+}
+
+bool isDerivedClassBefriended(const CXXRecordDecl *CRTP,
+                              const CXXRecordDecl *Derived) {
+  for (auto &&Friend : CRTP->friends()) {
+    if (Friend->getFriendType()->getType()->getAsCXXRecordDecl() == Derived)
+      return true;
+  }
+
+  return false;
+}
+
+std::optional<const NamedDecl *>
+getDerivedParameter(const ClassTemplateSpecializationDecl *CRTP,
----------------
isuckatcs wrote:

I think this is needed, because we want the fix to suggest befriending the template parameter, not the argument, so we need to know the name of the parameter and from the argument I didn't find a better way to figure it out.

E.g.:
```c++
template <typename T>
class CRTP {
    CRTP() = default;
};

class A : CRTP<A> {};
```

We want to suggest `friend T` instead of `friend A`. 

https://github.com/llvm/llvm-project/pull/82403


More information about the cfe-commits mailing list