Author: MichelleCDjunaidi Date: 2025-01-12T11:04:40+01:00 New Revision: 8ebc35f8d041f097a2b973b455dc3533420af6bf
URL: https://github.com/llvm/llvm-project/commit/8ebc35f8d041f097a2b973b455dc3533420af6bf DIFF: https://github.com/llvm/llvm-project/commit/8ebc35f8d041f097a2b973b455dc3533420af6bf.diff LOG: [clang-tidy] Create bugprone-incorrect-enable-shared-from-this check (#102299) This checks that classes/structs inheriting from ``std::enable_shared_from_this`` does so with public inheritance, so it prevents crashes due to ``std::make_shared`` and ``shared_from_this()`` getting called when the internal weak pointer was not initialized (e.g. due to private inheritance). Added: clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp Modified: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index b27616f3dcc658..c5f0b5b28418f8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -33,6 +33,7 @@ #include "InaccurateEraseCheck.h" #include "IncDecInConditionsCheck.h" #include "IncorrectEnableIfCheck.h" +#include "IncorrectEnableSharedFromThisCheck.h" #include "IncorrectRoundingsCheck.h" #include "InfiniteLoopCheck.h" #include "IntegerDivisionCheck.h" @@ -144,6 +145,8 @@ class BugproneModule : public ClangTidyModule { "bugprone-inaccurate-erase"); CheckFactories.registerCheck<IncorrectEnableIfCheck>( "bugprone-incorrect-enable-if"); + CheckFactories.registerCheck<IncorrectEnableSharedFromThisCheck>( + "bugprone-incorrect-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 8bd5646c5fe05a..e8309c68b7fcaa 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -27,6 +27,11 @@ add_clang_library(clangTidyBugproneModule STATIC ForwardingReferenceOverloadCheck.cpp ImplicitWideningOfMultiplicationResultCheck.cpp InaccurateEraseCheck.cpp + IncorrectEnableIfCheck.cpp + IncorrectEnableSharedFromThisCheck.cpp + ReturnConstRefFromParameterCheck.cpp + SuspiciousStringviewDataUsageCheck.cpp + SwitchMissingDefaultCaseCheck.cpp IncDecInConditionsCheck.cpp IncorrectEnableIfCheck.cpp IncorrectRoundingsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp new file mode 100644 index 00000000000000..425e46cf6c88cd --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp @@ -0,0 +1,65 @@ +//===--- IncorrectEnableSharedFromThisCheck.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 "IncorrectEnableSharedFromThisCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void IncorrectEnableSharedFromThisCheck::registerMatchers(MatchFinder *Finder) { + const auto EnableSharedFromThis = + cxxRecordDecl(hasName("enable_shared_from_this"), isInStdNamespace()); + const auto QType = hasCanonicalType(hasDeclaration( + cxxRecordDecl( + anyOf(EnableSharedFromThis.bind("enable_rec"), + cxxRecordDecl(hasAnyBase(cxxBaseSpecifier( + isPublic(), hasType(hasCanonicalType( + hasDeclaration(EnableSharedFromThis)))))))) + .bind("base_rec"))); + Finder->addMatcher( + cxxRecordDecl( + unless(isExpansionInSystemHeader()), + hasDirectBase(cxxBaseSpecifier(unless(isPublic()), hasType(QType)) + .bind("base"))) + .bind("derived"), + this); +} + +void IncorrectEnableSharedFromThisCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *BaseSpec = Result.Nodes.getNodeAs<CXXBaseSpecifier>("base"); + const auto *Base = Result.Nodes.getNodeAs<CXXRecordDecl>("base_rec"); + const auto *Derived = Result.Nodes.getNodeAs<CXXRecordDecl>("derived"); + const bool IsEnableSharedFromThisDirectBase = + Result.Nodes.getNodeAs<CXXRecordDecl>("enable_rec") == Base; + const bool HasWrittenAccessSpecifier = + BaseSpec->getAccessSpecifierAsWritten() != AS_none; + const auto ReplacementRange = CharSourceRange( + SourceRange(BaseSpec->getBeginLoc()), HasWrittenAccessSpecifier); + const llvm::StringRef Replacement = + HasWrittenAccessSpecifier ? "public" : "public "; + const FixItHint Hint = + IsEnableSharedFromThisDirectBase + ? FixItHint::CreateReplacement(ReplacementRange, Replacement) + : FixItHint(); + diag(Derived->getLocation(), + "%2 is not publicly inheriting from " + "%select{%1 which inherits from |}0'std::enable_shared_" + "from_this', " + "which will cause unintended behaviour " + "when using 'shared_from_this'; make the inheritance " + "public", + DiagnosticIDs::Warning) + << IsEnableSharedFromThisDirectBase << Base << Derived << Hint; +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h new file mode 100644 index 00000000000000..987c56059259b3 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.h @@ -0,0 +1,35 @@ +//===--- IncorrectEnableSharedFromThisCheck.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_INCORRECTENABLESHAREDFROMTHISCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTENABLESHAREDFROMTHISCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Detect classes or structs that do not publicly inherit from +/// ``std::enable_shared_from_this``, because unintended behavior will +/// otherwise occur when calling ``shared_from_this``. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.html +class IncorrectEnableSharedFromThisCheck : public ClangTidyCheck { +public: + IncorrectEnableSharedFromThisCheck(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.CPlusPlus11; + } +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INCORRECTENABLESHAREDFROMTHISCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 08156325369e61..375de831f0e118 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -145,6 +145,13 @@ New checks Warns about code that tries to cast between pointers by means of ``std::bit_cast`` or ``memcpy``. +- New :doc:`bugprone-incorrect-enable-shared-from-this + <clang-tidy/checks/bugprone/incorrect-enable-shared-from-this>` check. + + Detect classes or structs that do not publicly inherit from + ``std::enable_shared_from_this``, because unintended behavior will + otherwise occur when calling ``shared_from_this``. + - New :doc:`bugprone-nondeterministic-pointer-iteration-order <clang-tidy/checks/bugprone/nondeterministic-pointer-iteration-order>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst new file mode 100644 index 00000000000000..cc9e7be70f6ea8 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/incorrect-enable-shared-from-this.rst @@ -0,0 +1,34 @@ +.. title:: clang-tidy - bugprone-incorrect-enable-shared-from-this + +bugprone-incorrect-enable-shared-from-this +========================================== + +Detect classes or structs that do not publicly inherit from +``std::enable_shared_from_this``, because unintended behavior will +otherwise occur when calling ``shared_from_this``. + +Consider the following code: + +.. code-block:: c++ + + #include <memory> + + // private inheritance + class BadExample : std::enable_shared_from_this<BadExample> { + + // ``shared_from_this``` unintended behaviour + // `libstdc++` implementation returns uninitialized ``weak_ptr`` + 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(); + } + +Using `libstdc++` implementation, ``shared_from_this`` will throw +``std::bad_weak_ptr``. When ``using_not_public()`` is called, this code will +crash without exception handling. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e8f9b4e829634b..7b9b905ef76715 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -101,6 +101,7 @@ Clang-Tidy Checks :doc:`bugprone-inaccurate-erase <bugprone/inaccurate-erase>`, "Yes" :doc:`bugprone-inc-dec-in-conditions <bugprone/inc-dec-in-conditions>`, :doc:`bugprone-incorrect-enable-if <bugprone/incorrect-enable-if>`, "Yes" + :doc:`bugprone-incorrect-enable-shared-from-this <bugprone/incorrect-enable-shared-from-this>`, "Yes" :doc:`bugprone-incorrect-roundings <bugprone/incorrect-roundings>`, :doc:`bugprone-infinite-loop <bugprone/infinite-loop>`, :doc:`bugprone-integer-division <bugprone/integer-division>`, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp new file mode 100644 index 00000000000000..d9048ef359281b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-shared-from-this.cpp @@ -0,0 +1,180 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-incorrect-enable-shared-from-this %t + +// NOLINTBEGIN +namespace std { + template <typename T> class enable_shared_from_this {}; +} //namespace std +// NOLINTEND + +class BadClassExample : std::enable_shared_from_this<BadClassExample> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'BadClassExample' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: public std::enable_shared_from_this<BadClassExample> + +class BadClass2Example : private std::enable_shared_from_this<BadClass2Example> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'BadClass2Example' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: public std::enable_shared_from_this<BadClass2Example> + +struct BadStructExample : private std::enable_shared_from_this<BadStructExample> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'BadStructExample' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: public std::enable_shared_from_this<BadStructExample> + +class GoodClassExample : public std::enable_shared_from_this<GoodClassExample> {}; + +struct GoodStructExample : public std::enable_shared_from_this<GoodStructExample> {}; + +struct GoodStruct2Example : std::enable_shared_from_this<GoodStruct2Example> {}; + +class dummy_class1 {}; +class dummy_class2 {}; + +class BadMultiClassExample : std::enable_shared_from_this<BadMultiClassExample>, dummy_class1 {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'BadMultiClassExample' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: public std::enable_shared_from_this<BadMultiClassExample>, dummy_class1 + +class BadMultiClass2Example : dummy_class1, std::enable_shared_from_this<BadMultiClass2Example>, dummy_class2 {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'BadMultiClass2Example' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: dummy_class1, public std::enable_shared_from_this<BadMultiClass2Example>, dummy_class2 + +class BadMultiClass3Example : dummy_class1, dummy_class2, std::enable_shared_from_this<BadMultiClass3Example> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'BadMultiClass3Example' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: dummy_class1, dummy_class2, public std::enable_shared_from_this<BadMultiClass3Example> + +class ClassBase : public std::enable_shared_from_this<ClassBase> {}; +class PrivateInheritClassBase : private ClassBase {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'PrivateInheritClassBase' is not publicly inheriting from 'ClassBase' which inherits from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +class DefaultInheritClassBase : ClassBase {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'DefaultInheritClassBase' is not publicly inheriting from 'ClassBase' which inherits from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +class PublicInheritClassBase : public ClassBase {}; + +struct StructBase : public std::enable_shared_from_this<StructBase> {}; +struct PrivateInheritStructBase : private StructBase {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'PrivateInheritStructBase' is not publicly inheriting from 'StructBase' which inherits from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +struct DefaultInheritStructBase : StructBase {}; + +struct PublicInheritStructBase : StructBase {}; + +//alias the template itself +template <typename T> using esft_template = std::enable_shared_from_this<T>; + +class PrivateAliasTemplateClassBase : private esft_template<PrivateAliasTemplateClassBase> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'PrivateAliasTemplateClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class PrivateAliasTemplateClassBase : public esft_template<PrivateAliasTemplateClassBase> {}; + +class DefaultAliasTemplateClassBase : esft_template<DefaultAliasTemplateClassBase> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'DefaultAliasTemplateClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class DefaultAliasTemplateClassBase : public esft_template<DefaultAliasTemplateClassBase> {}; + +class PublicAliasTemplateClassBase : public esft_template<PublicAliasTemplateClassBase> {}; + +struct PrivateAliasTemplateStructBase : private esft_template<PrivateAliasTemplateStructBase> {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'PrivateAliasTemplateStructBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: struct PrivateAliasTemplateStructBase : public esft_template<PrivateAliasTemplateStructBase> {}; + +struct DefaultAliasTemplateStructBase : esft_template<DefaultAliasTemplateStructBase> {}; + +struct PublicAliasTemplateStructBase : public esft_template<PublicAliasTemplateStructBase> {}; + +//alias with specific instance +using esft = std::enable_shared_from_this<ClassBase>; +class PrivateAliasClassBase : private esft {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'PrivateAliasClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class PrivateAliasClassBase : public esft {}; + +class DefaultAliasClassBase : esft {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'DefaultAliasClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class DefaultAliasClassBase : public esft {}; + +class PublicAliasClassBase : public esft {}; + +struct PrivateAliasStructBase : private esft {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'PrivateAliasStructBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: struct PrivateAliasStructBase : public esft {}; + +struct DefaultAliasStructBase : esft {}; + +struct PublicAliasStructBase : public esft {}; + +//we can only typedef a specific instance of the template +typedef std::enable_shared_from_this<ClassBase> EnableSharedFromThis; +class PrivateTypedefClassBase : private EnableSharedFromThis {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'PrivateTypedefClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class PrivateTypedefClassBase : public EnableSharedFromThis {}; + +class DefaultTypedefClassBase : EnableSharedFromThis {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'DefaultTypedefClassBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class DefaultTypedefClassBase : public EnableSharedFromThis {}; + +class PublicTypedefClassBase : public EnableSharedFromThis {}; + +struct PrivateTypedefStructBase : private EnableSharedFromThis {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'PrivateTypedefStructBase' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: struct PrivateTypedefStructBase : public EnableSharedFromThis {}; + +struct DefaultTypedefStructBase : EnableSharedFromThis {}; + +struct PublicTypedefStructBase : public EnableSharedFromThis {}; + +#define PRIVATE_ESFT_CLASS(ClassName) \ + class ClassName: private std::enable_shared_from_this<ClassName> { \ + }; + +PRIVATE_ESFT_CLASS(PrivateEsftClass); +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'PrivateEsftClass' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +#define DEFAULT_ESFT_CLASS(ClassName) \ + class ClassName: std::enable_shared_from_this<ClassName> { \ + }; + +DEFAULT_ESFT_CLASS(DefaultEsftClass); +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 'DefaultEsftClass' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +#define PUBLIC_ESFT_CLASS(ClassName) \ + class ClassName: public std::enable_shared_from_this<ClassName> { \ + }; + +PUBLIC_ESFT_CLASS(PublicEsftClass); + +#define PRIVATE_ESFT_STRUCT(StructName) \ + struct StructName: private std::enable_shared_from_this<StructName> { \ + }; + +PRIVATE_ESFT_STRUCT(PrivateEsftStruct); +// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'PrivateEsftStruct' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +#define DEFAULT_ESFT_STRUCT(StructName) \ + struct StructName: std::enable_shared_from_this<StructName> { \ + }; + +DEFAULT_ESFT_STRUCT(DefaultEsftStruct); + +#define PUBLIC_ESFT_STRUCT(StructName) \ + struct StructName: std::enable_shared_from_this<StructName> { \ + }; + +PUBLIC_ESFT_STRUCT(PublicEsftStruct); + +struct A : std::enable_shared_from_this<A> {}; +#define MACRO_A A + +class B : MACRO_A {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'B' is not publicly inheriting from 'A' which inherits from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +class C : private MACRO_A {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'C' is not publicly inheriting from 'A' which inherits from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] + +class D : public MACRO_A {}; + +#define MACRO_PARAM(CLASS) std::enable_shared_from_this<CLASS> + +class E : MACRO_PARAM(E) {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'E' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class E : public MACRO_PARAM(E) {}; + +class F : private MACRO_PARAM(F) {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'F' is not publicly inheriting from 'std::enable_shared_from_this', which will cause unintended behaviour when using 'shared_from_this'; make the inheritance public [bugprone-incorrect-enable-shared-from-this] +// CHECK-FIXES: class F : public MACRO_PARAM(F) {}; + +class G : public MACRO_PARAM(G) {}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits