10#include "clang/AST/ASTContext.h"
11#include "clang/AST/DeclCXX.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
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 unless(isExpansionInSystemHeader()),
31 hasDirectBase(cxxBaseSpecifier(unless(isPublic()), hasType(QType))
38 const MatchFinder::MatchResult &Result) {
39 const auto *BaseSpec = Result.Nodes.getNodeAs<CXXBaseSpecifier>(
"base");
40 const auto *Base = Result.Nodes.getNodeAs<CXXRecordDecl>(
"base_rec");
41 const auto *Derived = Result.Nodes.getNodeAs<CXXRecordDecl>(
"derived");
42 const bool IsEnableSharedFromThisDirectBase =
43 Result.Nodes.getNodeAs<CXXRecordDecl>(
"enable_rec") == Base;
44 const bool HasWrittenAccessSpecifier =
45 BaseSpec->getAccessSpecifierAsWritten() != AS_none;
46 const auto ReplacementRange = CharSourceRange(
47 SourceRange(BaseSpec->getBeginLoc()), HasWrittenAccessSpecifier);
48 const llvm::StringRef Replacement =
49 HasWrittenAccessSpecifier ?
"public" :
"public ";
50 const FixItHint Hint =
51 IsEnableSharedFromThisDirectBase
52 ? FixItHint::CreateReplacement(ReplacementRange, Replacement)
54 diag(Derived->getLocation(),
55 "%2 is not publicly inheriting from "
56 "%select{%1 which inherits from |}0'std::enable_shared_"
58 "which will cause unintended behaviour "
59 "when using 'shared_from_this'; make the inheritance "
61 DiagnosticIDs::Warning)
62 << IsEnableSharedFromThisDirectBase << Base << Derived << Hint;
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.