19 const auto EnableSharedFromThis =
20 cxxRecordDecl(hasName(
"enable_shared_from_this"), isInStdNamespace());
21 const auto QType = hasCanonicalType(hasDeclaration(
23 anyOf(EnableSharedFromThis.bind(
"enable_rec"),
24 cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(
25 isPublic(), hasType(hasCanonicalType(
26 hasDeclaration(EnableSharedFromThis))))))))
30 hasDirectBase(cxxBaseSpecifier(unless(isPublic()), hasType(QType))
37 const MatchFinder::MatchResult &Result) {
38 const auto *BaseSpec = Result.Nodes.getNodeAs<CXXBaseSpecifier>(
"base");
39 const auto *Base = Result.Nodes.getNodeAs<CXXRecordDecl>(
"base_rec");
40 const auto *Derived = Result.Nodes.getNodeAs<CXXRecordDecl>(
"derived");
41 const bool IsEnableSharedFromThisDirectBase =
42 Result.Nodes.getNodeAs<CXXRecordDecl>(
"enable_rec") == Base;
43 const bool HasWrittenAccessSpecifier =
44 BaseSpec->getAccessSpecifierAsWritten() != AS_none;
45 const auto ReplacementRange = CharSourceRange(
46 SourceRange(BaseSpec->getBeginLoc()), HasWrittenAccessSpecifier);
47 const llvm::StringRef Replacement =
48 HasWrittenAccessSpecifier ?
"public" :
"public ";
49 const FixItHint Hint =
50 IsEnableSharedFromThisDirectBase
51 ? FixItHint::CreateReplacement(ReplacementRange, Replacement)
53 diag(Derived->getLocation(),
54 "%2 is not publicly inheriting from "
55 "%select{%1 which inherits from |}0'std::enable_shared_"
57 "which will cause unintended behaviour "
58 "when using 'shared_from_this'; make the inheritance "
60 DiagnosticIDs::Warning)
61 << IsEnableSharedFromThisDirectBase << Base << Derived << Hint;