1//===--- IncorrectEnableSharedFromThisCheck.cpp - clang-tidy --------------===//
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
9#include "IncorrectEnableSharedFromThisCheck.h"
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
18void IncorrectEnableSharedFromThisCheck::registerMatchers(MatchFinder *Finder) {
19 const auto EnableSharedFromThis =
20 cxxRecordDecl(hasName(Name: "enable_shared_from_this"), isInStdNamespace());
21 const auto QType = hasCanonicalType(InnerMatcher: hasDeclaration(
22 InnerMatcher: cxxRecordDecl(
23 anyOf(EnableSharedFromThis.bind(ID: "enable_rec"),
24 cxxRecordDecl(hasAnyBase(BaseSpecMatcher: cxxBaseSpecifier(
25 isPublic(), hasType(InnerMatcher: hasCanonicalType(
26 InnerMatcher: hasDeclaration(InnerMatcher: EnableSharedFromThis))))))))
27 .bind(ID: "base_rec")));
28 Finder->addMatcher(
29 NodeMatch: cxxRecordDecl(
30 unless(isExpansionInSystemHeader()),
31 hasDirectBase(BaseSpecMatcher: cxxBaseSpecifier(unless(isPublic()), hasType(InnerMatcher: QType))
32 .bind(ID: "base")))
33 .bind(ID: "derived"),
34 Action: this);
35}
36
37void IncorrectEnableSharedFromThisCheck::check(
38 const MatchFinder::MatchResult &Result) {
39 const auto *BaseSpec = Result.Nodes.getNodeAs<CXXBaseSpecifier>(ID: "base");
40 const auto *Base = Result.Nodes.getNodeAs<CXXRecordDecl>(ID: "base_rec");
41 const auto *Derived = Result.Nodes.getNodeAs<CXXRecordDecl>(ID: "derived");
42 const bool IsEnableSharedFromThisDirectBase =
43 Result.Nodes.getNodeAs<CXXRecordDecl>(ID: "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(RemoveRange: ReplacementRange, Code: Replacement)
53 : FixItHint();
54 diag(Derived->getLocation(),
55 "%2 is not publicly inheriting from "
56 "%select{%1 which inherits from |}0'std::enable_shared_"
57 "from_this', "
58 "which will cause unintended behaviour "
59 "when using 'shared_from_this'; make the inheritance "
60 "public",
61 DiagnosticIDs::Warning)
62 << IsEnableSharedFromThisDirectBase << Base << Derived << Hint;
63}
64
65} // namespace clang::tidy::bugprone
66

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang-tools-extra/clang-tidy/bugprone/IncorrectEnableSharedFromThisCheck.cpp