clang-tools 23.0.0git
IncorrectEnableSharedFromThisCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/AST/ASTContext.h"
11#include "clang/AST/DeclCXX.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang::tidy::bugprone {
17
19 const auto EnableSharedFromThis =
20 cxxRecordDecl(hasName("enable_shared_from_this"), isInStdNamespace());
21 const auto QType = hasCanonicalType(hasDeclaration(
22 cxxRecordDecl(
23 anyOf(EnableSharedFromThis.bind("enable_rec"),
24 cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(
25 isPublic(), hasType(hasCanonicalType(
26 hasDeclaration(EnableSharedFromThis))))))))
27 .bind("base_rec")));
28 Finder->addMatcher(
29 cxxRecordDecl(
30 hasDirectBase(cxxBaseSpecifier(unless(isPublic()), hasType(QType))
31 .bind("base")))
32 .bind("derived"),
33 this);
34}
35
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)
52 : FixItHint();
53 diag(Derived->getLocation(),
54 "%2 is not publicly inheriting from "
55 "%select{%1 which inherits from |}0'std::enable_shared_"
56 "from_this', "
57 "which will cause unintended behaviour "
58 "when using 'shared_from_this'; make the inheritance "
59 "public",
60 DiagnosticIDs::Warning)
61 << IsEnableSharedFromThisDirectBase << Base << Derived << Hint;
62}
63
64} // namespace clang::tidy::bugprone
void check(const ast_matchers::MatchFinder::MatchResult &Result) override