-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[clang-tidy] Create bugprone-incorrect-enable-shared-from-this check #102299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang-tidy] Create bugprone-incorrect-enable-shared-from-this check #102299
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang-tools-extra Author: None (MichelleCDjunaidi) ChangesThis checks that classes/structs inheriting from Full diff: https://github.com/llvm/llvm-project/pull/102299.diff 8 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 689eb92a3d8d1..f12f0cd1c47da 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -53,6 +53,7 @@
#include "ParentVirtualCallCheck.h"
#include "PointerArithmeticOnPolymorphicObjectCheck.h"
#include "PosixReturnCheck.h"
+#include "PublicEnableSharedFromThisCheck.h"
#include "RedundantBranchConditionCheck.h"
#include "ReservedIdentifierCheck.h"
#include "ReturnConstRefFromParameterCheck.h"
@@ -139,6 +140,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IncorrectEnableIfCheck>(
"bugprone-incorrect-enable-if");
+ CheckFactories.registerCheck<PublicEnableSharedFromThisCheck>(
+ "bugprone-public-enable-shared-from-this");
CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
"bugprone-return-const-ref-from-parameter");
CheckFactories.registerCheck<SwitchMissingDefaultCaseCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index cb0d8ae98bac5..c9bea094241ed 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule
ImplicitWideningOfMultiplicationResultCheck.cpp
InaccurateEraseCheck.cpp
IncorrectEnableIfCheck.cpp
+ PublicEnableSharedFromThisCheck.cpp
ReturnConstRefFromParameterCheck.cpp
SuspiciousStringviewDataUsageCheck.cpp
SwitchMissingDefaultCaseCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
new file mode 100644
index 0000000000000..dab3e0ac596fe
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
@@ -0,0 +1,45 @@
+//===--- PublicEnableSharedFromThisCheck.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 "PublicEnableSharedFromThisCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+ void PublicEnableSharedFromThisCheck::registerMatchers(MatchFinder *match_finder) {
+ match_finder->addMatcher(
+ cxxRecordDecl(
+ hasAnyBase(
+ cxxBaseSpecifier(unless(isPublic()),
+ hasType(
+ cxxRecordDecl(
+ hasName("::std::enable_shared_from_this"))))
+ )
+ )
+ .bind("not-public-enable-shared"), this);
+ }
+
+ void PublicEnableSharedFromThisCheck::check(const MatchFinder::MatchResult &result) {
+ const auto *EnableSharedClassDecl =
+ result.Nodes.getNodeAs<CXXRecordDecl>("not-public-enable-shared");
+
+ for (const auto &Base : EnableSharedClassDecl->bases()) {
+ const auto *BaseType = Base.getType()->getAsCXXRecordDecl();
+ if (BaseType && BaseType->getQualifiedNameAsString() == "std::enable_shared_from_this") {
+ SourceLocation InsertLoc = Base.getBeginLoc();
+ FixItHint Hint = FixItHint::CreateInsertion(InsertLoc, "public ");
+ diag(EnableSharedClassDecl->getLocation(), "class %0 is not public even though it's derived from std::enable_shared_from_this", DiagnosticIDs::Warning)
+ << EnableSharedClassDecl->getNameAsString()
+ << Hint;
+ break;
+ }
+ }
+ }
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h
new file mode 100644
index 0000000000000..8a4013c3a46b7
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h
@@ -0,0 +1,33 @@
+//===--- PublicEnableSharedFromThisCheck.h - clang-tidy ---------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Checks if a class deriving from enable_shared_from_this has public access specifiers, because otherwise the program will crash when shared_from_this is called.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/public-enable-shared-from-this.html
+class PublicEnableSharedFromThisCheck : public ClangTidyCheck {
+public:
+ PublicEnableSharedFromThisCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 642ad39cc0c1c..67f6b1275a1ad 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -98,6 +98,11 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- New :doc:`bugprone-public-enable-shared-from-this
+ <clang-tidy/checks/bugprone/public-enable-shared-from-this>` check.
+
+ Checks if a class deriving from enable_shared_from_this has public access specifiers, because otherwise the program will crash when shared_from_this is called.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
new file mode 100644
index 0000000000000..616b2b52271e3
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - bugprone-public-enable-shared-from-this
+
+bugprone-public-enable-shared-from-this
+=======================================
+
+Checks that classes/structs inheriting from ``std::enable_shared_from_this`` derive it with the ``public`` access specifier. If not, then issue a FixItHint that can be applied.
+
+Consider the following code:
+.. code-block:: c++
+ #include <memory>
+
+ class BadExample : std::enable_shared_from_this<BadExample> {
+ // warning: class BadExample is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // will insert the public keyword if -fix is applied
+ public:
+ BadExample* foo() { return shared_from_this().get(); }
+ void bar() { return; }
+ };
+
+ void using_not_public() {
+ auto bad_example = std::make_shared<BadExample>();
+ auto* b_ex = bad_example->foo();
+ b_ex->bar();
+ }
+
+When ``using_not_public()`` is called, this code will crash.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index a931ebf025a10..2b918de89f7c1 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -120,6 +120,7 @@ Clang-Tidy Checks
:doc:`bugprone-parent-virtual-call <bugprone/parent-virtual-call>`, "Yes"
:doc:`bugprone-pointer-arithmetic-on-polymorphic-object <bugprone/pointer-arithmetic-on-polymorphic-object>`,
:doc:`bugprone-posix-return <bugprone/posix-return>`, "Yes"
+ :doc:`bugprone-public-enable-shared-from-this <bugprone/public-enable-shared-from-this>`, "Yes"
:doc:`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition>`, "Yes"
:doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes"
:doc:`bugprone-return-const-ref-from-parameter <bugprone/return-const-ref-from-parameter>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
new file mode 100644
index 0000000000000..b0954898ddb78
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s bugprone-public-enable-shared-from-this %t -- --
+
+namespace std {
+
+ template <typename T> class enable_shared_from_this {};
+
+ class BadExample : enable_shared_from_this<BadExample> {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: class BadExample is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // CHECK-FIXES: public enable_shared_from_this<BadExample>
+
+ class Bad2Example : std::enable_shared_from_this<Bad2Example> {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: class Bad2Example is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // CHECK-FIXES: public std::enable_shared_from_this<Bad2Example>
+
+ class GoodExample : public enable_shared_from_this<GoodExample> {
+ };
+
+ struct BaseClass {
+
+ void print() {
+ (void) State;
+ (void) Requester;
+ }
+ bool State;
+ int Requester;
+ };
+
+ class InheritPrivateBaseClass : BaseClass {
+ public:
+ void additionalFunction() {
+ (void) ID;
+ }
+ private:
+ int ID;
+ };
+
+ class InheritPublicBaseClass : public BaseClass {
+ public:
+ void additionalFunction() {
+ (void) ID;
+ }
+ private:
+ int ID;
+ };
+}
\ No newline at end of file
|
@llvm/pr-subscribers-clang-tidy Author: None (MichelleCDjunaidi) ChangesThis checks that classes/structs inheriting from Full diff: https://github.com/llvm/llvm-project/pull/102299.diff 8 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 689eb92a3d8d1..f12f0cd1c47da 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -53,6 +53,7 @@
#include "ParentVirtualCallCheck.h"
#include "PointerArithmeticOnPolymorphicObjectCheck.h"
#include "PosixReturnCheck.h"
+#include "PublicEnableSharedFromThisCheck.h"
#include "RedundantBranchConditionCheck.h"
#include "ReservedIdentifierCheck.h"
#include "ReturnConstRefFromParameterCheck.h"
@@ -139,6 +140,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IncorrectEnableIfCheck>(
"bugprone-incorrect-enable-if");
+ CheckFactories.registerCheck<PublicEnableSharedFromThisCheck>(
+ "bugprone-public-enable-shared-from-this");
CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
"bugprone-return-const-ref-from-parameter");
CheckFactories.registerCheck<SwitchMissingDefaultCaseCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index cb0d8ae98bac5..c9bea094241ed 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule
ImplicitWideningOfMultiplicationResultCheck.cpp
InaccurateEraseCheck.cpp
IncorrectEnableIfCheck.cpp
+ PublicEnableSharedFromThisCheck.cpp
ReturnConstRefFromParameterCheck.cpp
SuspiciousStringviewDataUsageCheck.cpp
SwitchMissingDefaultCaseCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
new file mode 100644
index 0000000000000..dab3e0ac596fe
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
@@ -0,0 +1,45 @@
+//===--- PublicEnableSharedFromThisCheck.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 "PublicEnableSharedFromThisCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+ void PublicEnableSharedFromThisCheck::registerMatchers(MatchFinder *match_finder) {
+ match_finder->addMatcher(
+ cxxRecordDecl(
+ hasAnyBase(
+ cxxBaseSpecifier(unless(isPublic()),
+ hasType(
+ cxxRecordDecl(
+ hasName("::std::enable_shared_from_this"))))
+ )
+ )
+ .bind("not-public-enable-shared"), this);
+ }
+
+ void PublicEnableSharedFromThisCheck::check(const MatchFinder::MatchResult &result) {
+ const auto *EnableSharedClassDecl =
+ result.Nodes.getNodeAs<CXXRecordDecl>("not-public-enable-shared");
+
+ for (const auto &Base : EnableSharedClassDecl->bases()) {
+ const auto *BaseType = Base.getType()->getAsCXXRecordDecl();
+ if (BaseType && BaseType->getQualifiedNameAsString() == "std::enable_shared_from_this") {
+ SourceLocation InsertLoc = Base.getBeginLoc();
+ FixItHint Hint = FixItHint::CreateInsertion(InsertLoc, "public ");
+ diag(EnableSharedClassDecl->getLocation(), "class %0 is not public even though it's derived from std::enable_shared_from_this", DiagnosticIDs::Warning)
+ << EnableSharedClassDecl->getNameAsString()
+ << Hint;
+ break;
+ }
+ }
+ }
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h
new file mode 100644
index 0000000000000..8a4013c3a46b7
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.h
@@ -0,0 +1,33 @@
+//===--- PublicEnableSharedFromThisCheck.h - clang-tidy ---------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Checks if a class deriving from enable_shared_from_this has public access specifiers, because otherwise the program will crash when shared_from_this is called.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/public-enable-shared-from-this.html
+class PublicEnableSharedFromThisCheck : public ClangTidyCheck {
+public:
+ PublicEnableSharedFromThisCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_PUBLICENABLESHAREDFROMTHISCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 642ad39cc0c1c..67f6b1275a1ad 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -98,6 +98,11 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- New :doc:`bugprone-public-enable-shared-from-this
+ <clang-tidy/checks/bugprone/public-enable-shared-from-this>` check.
+
+ Checks if a class deriving from enable_shared_from_this has public access specifiers, because otherwise the program will crash when shared_from_this is called.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
new file mode 100644
index 0000000000000..616b2b52271e3
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - bugprone-public-enable-shared-from-this
+
+bugprone-public-enable-shared-from-this
+=======================================
+
+Checks that classes/structs inheriting from ``std::enable_shared_from_this`` derive it with the ``public`` access specifier. If not, then issue a FixItHint that can be applied.
+
+Consider the following code:
+.. code-block:: c++
+ #include <memory>
+
+ class BadExample : std::enable_shared_from_this<BadExample> {
+ // warning: class BadExample is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // will insert the public keyword if -fix is applied
+ public:
+ BadExample* foo() { return shared_from_this().get(); }
+ void bar() { return; }
+ };
+
+ void using_not_public() {
+ auto bad_example = std::make_shared<BadExample>();
+ auto* b_ex = bad_example->foo();
+ b_ex->bar();
+ }
+
+When ``using_not_public()`` is called, this code will crash.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index a931ebf025a10..2b918de89f7c1 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -120,6 +120,7 @@ Clang-Tidy Checks
:doc:`bugprone-parent-virtual-call <bugprone/parent-virtual-call>`, "Yes"
:doc:`bugprone-pointer-arithmetic-on-polymorphic-object <bugprone/pointer-arithmetic-on-polymorphic-object>`,
:doc:`bugprone-posix-return <bugprone/posix-return>`, "Yes"
+ :doc:`bugprone-public-enable-shared-from-this <bugprone/public-enable-shared-from-this>`, "Yes"
:doc:`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition>`, "Yes"
:doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes"
:doc:`bugprone-return-const-ref-from-parameter <bugprone/return-const-ref-from-parameter>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
new file mode 100644
index 0000000000000..b0954898ddb78
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s bugprone-public-enable-shared-from-this %t -- --
+
+namespace std {
+
+ template <typename T> class enable_shared_from_this {};
+
+ class BadExample : enable_shared_from_this<BadExample> {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: class BadExample is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // CHECK-FIXES: public enable_shared_from_this<BadExample>
+
+ class Bad2Example : std::enable_shared_from_this<Bad2Example> {};
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: class Bad2Example is not public even though it's derived from std::enable_shared_from_this [bugprone-public-enable-shared-from-this]
+ // CHECK-FIXES: public std::enable_shared_from_this<Bad2Example>
+
+ class GoodExample : public enable_shared_from_this<GoodExample> {
+ };
+
+ struct BaseClass {
+
+ void print() {
+ (void) State;
+ (void) Requester;
+ }
+ bool State;
+ int Requester;
+ };
+
+ class InheritPrivateBaseClass : BaseClass {
+ public:
+ void additionalFunction() {
+ (void) ID;
+ }
+ private:
+ int ID;
+ };
+
+ class InheritPublicBaseClass : public BaseClass {
+ public:
+ void additionalFunction() {
+ (void) ID;
+ }
+ private:
+ int ID;
+ };
+}
\ No newline at end of file
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with idea behind this check. Just few fixes are needed.
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/PublicEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/public-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are classes that derive other classes that implement enable_shared_from_this
class A : public std::enable_shared_from_this {};
class B : private A{};
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/public-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
Looking at the AST dump that clang-check gives, it seems that B doesn't have any knowledge of A's internals, so the current approach will not work. Correct me if I'm wrong though |
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp
Show resolved
Hide resolved
I think you'd have to recursively check the inheritance of a class and if you have any private that derives from |
Yu could use isDerivedFrom, should do a trick |
Actually an ASTVisitor approach could be better here, this way you could create a set of all the |
To confirm, @njames93 do you mean I'm also unsure regarding best practices for using Or would it be an additional matcher to get every For example, looking at this from readability
and
that seems like a way to do the latter option? Otherwise, an example of the approach you're suggesting would be very helpful, or resources outside of the Doxygen; I'm not very familiar with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maintaining the name of the matched classes in a vector and checking for every other class if it inherits from
::std::enable_shared_from_this
or classes in the vector.
You wouldn't want to save the name, because then you would do a lot of string comparisons when you could do pointer comparisons (which would require using RDecl->getCanonical()
to ensure you get the same record decl, I believe).
Instead of a vector, you could use a set. Then checking the base classes would simply be a call to contains
(llvm::SmallPtrSet
?).
Wouldn't this necessitate changing the matchers and the check to instead allow RecursiveASTVisitor to handle the context instead?
Kind of. In this case, you would match the translation unit and call TraverseTranslationUnitDecl
on it.
Then you implement bool VisitCXXRecordDecl(CXXRecordDecl* RDecl)
and check if RDecl
is of type std::enable_shared_from_this
and adding that to the set if it is. Otherwise, checking if it publicly inherits from any class that is contained in the set, and adding it to the set if it is. If the inheritance is not public, then you can issue a diagnostic. You can save a pointer to the check (ClangTidyCheck* Check
) to do that (Check->diag(...)
).
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst
Outdated
Show resolved
Hide resolved
Thanks for the pointers! It's really helpful to have a starting point to learn the best practices, I'll try to figure this out and report back. |
@5chmidti so something like this then?
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for me oryginal version that used registerMatchers instead of visitor were way better, specially that there are matchers that could be used for this, or could be written.
And even for performance reasons it could be implemented in slightly better way by simply very quickly exclude all classes that do not derive from std::enable_shared_from_this.
If boost::enable_shared_from_this
got same flaw, then this check should also support it. And this mean it maybe should be configurable.
Edit: I understand why @njames93 mentioned Visitor, but thing is that in most projects not many classes actually used std::enable_shared_from_this
and there will be no visible performance gain from "remembering" list of classes, and as we could see this approach makes this check more complicated.
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
next time I shouldn't rebase and just wait to fix the conflict on merge
PRs that are quite outdated should, and those that have conflicts must be updated before the PR is merged. You can either rebase with upstream changes, or merge with upstream. Which one you chose is up to you, but merging seems to be less likely to cause issues with commits that are not yours from appearing in the PR. E.g., right now there is a conflict on the release notes. You could use the GitHub UI to fix the conflict, or use your local git by fetching from the remote, and either using git rebase origin/main
or git merge origin/main
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minus my comment, this looks good to me. Thanks for working on this.
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Outdated
Show resolved
Hide resolved
Note: I'll need someone to merge this in for me, as I don't have write access. |
Unless someone also wants to review this PR, I'll merge this tomorrow. The unresolved review comments of the other reviewers have, FWICT, been resolved. |
I think will be good idea to rebase branch again before merge and let others to see changes for some time. |
…prone-public-enable-shared-from-this
@5chmidti @EugeneZelenko Happy New Year! Is there anything left I need to do to get this merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp
Outdated
Show resolved
Hide resolved
Working on it. |
@MichelleCDjunaidi Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/161/builds/4099 Here is the relevant piece of the build log for the reference
|
This checks that classes/structs inheriting from
std::enable_shared_from_this
does so with public inheritance, so it prevents crashes due tostd::make_shared
andshared_from_this()
getting called when the internal weak pointer was not initialized (e.g. due to private inheritance).