10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 using namespace clang;
22 if (Node.hasDefinition())
23 return Node.getNumBases() > 0;
30 void MultipleInheritanceCheck::addNodeToInterfaceMap(
const CXXRecordDecl *Node,
32 assert(Node->getIdentifier());
33 StringRef
Name = Node->getIdentifier()->getName();
34 InterfaceMap.insert(std::make_pair(Name, isInterface));
40 bool MultipleInheritanceCheck::getInterfaceStatus(
const CXXRecordDecl *Node,
41 bool &isInterface)
const {
42 assert(Node->getIdentifier());
43 StringRef Name = Node->getIdentifier()->getName();
44 llvm::StringMapConstIterator<bool> Pair = InterfaceMap.find(Name);
45 if (Pair == InterfaceMap.end())
47 isInterface = Pair->second;
51 bool MultipleInheritanceCheck::isCurrentClassInterface(
52 const CXXRecordDecl *Node)
const {
54 if (!Node->field_empty())
return false;
57 return llvm::none_of(Node->methods(), [](
const CXXMethodDecl *M) {
58 return M->isUserProvided() && !M->isPure() && !M->isStatic();
62 bool MultipleInheritanceCheck::isInterface(
const CXXRecordDecl *Node) {
63 if (!Node->getIdentifier())
67 bool PreviousIsInterfaceResult;
68 if (getInterfaceStatus(Node, PreviousIsInterfaceResult))
69 return PreviousIsInterfaceResult;
72 for (
const auto &I : Node->bases()) {
73 if (I.isVirtual())
continue;
74 const auto *Ty = I.getType()->getAs<RecordType>();
76 const RecordDecl *D = Ty->getDecl()->getDefinition();
78 const auto *
Base = cast<CXXRecordDecl>(D);
79 if (!isInterface(
Base)) {
80 addNodeToInterfaceMap(Node,
false);
85 bool CurrentClassIsInterface = isCurrentClassInterface(Node);
86 addNodeToInterfaceMap(Node, CurrentClassIsInterface);
87 return CurrentClassIsInterface;
90 void MultipleInheritanceCheck::registerMatchers(MatchFinder *Finder) {
92 if (!getLangOpts().CPlusPlus)
97 cxxRecordDecl(allOf(hasBases(), isDefinition())).bind(
"decl"),
this);
100 void MultipleInheritanceCheck::check(
const MatchFinder::MatchResult &Result) {
101 if (
const auto *D = Result.Nodes.getNodeAs<CXXRecordDecl>(
"decl")) {
104 unsigned NumConcrete = 0;
105 for (
const auto &I : D->bases()) {
106 if (I.isVirtual())
continue;
107 const auto *Ty = I.getType()->getAs<RecordType>();
109 const auto *
Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
110 if (!isInterface(
Base)) NumConcrete++;
115 for (
const auto &V : D->vbases()) {
116 const auto *Ty = V.getType()->getAs<RecordType>();
118 const auto *
Base = cast<CXXRecordDecl>(Ty->getDecl()->getDefinition());
119 if (!isInterface(
Base)) NumConcrete++;
122 if (NumConcrete > 1) {
123 diag(D->getBeginLoc(),
"inheriting mulitple classes that aren't " 124 "pure virtual is discouraged");
AST_MATCHER(Expr, isMacroID)
static constexpr llvm::StringLiteral Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< GlobalCompilationDatabase > Base