10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
20 return Node.hasDefinition() && Node.getNumBases() > 0;
24bool MultipleInheritanceCheck::isInterface(
const CXXBaseSpecifier &Base) {
25 const CXXRecordDecl *
const Node = Base.getType()->getAsCXXRecordDecl();
29 assert(Node->isCompleteDefinition());
32 if (
const auto CachedValue = InterfaceMap.find(Node);
33 CachedValue != InterfaceMap.end())
34 return CachedValue->second;
37 const bool CurrentClassIsInterface =
39 llvm::none_of(Node->bases(),
40 [&](
const CXXBaseSpecifier &I) {
41 return !I.isVirtual() && !isInterface(I);
44 Node->field_empty() &&
46 llvm::none_of(Node->methods(), [](
const CXXMethodDecl *M) {
47 return M->isUserProvided() && !M->isPureVirtual() && !M->isStatic();
50 InterfaceMap.try_emplace(Node, CurrentClassIsInterface);
51 return CurrentClassIsInterface;
55 Finder->addMatcher(cxxRecordDecl(hasBases(), isDefinition()).bind(
"decl"),
60 const auto &D = *Result.Nodes.getNodeAs<CXXRecordDecl>(
"decl");
62 unsigned NumConcrete =
63 llvm::count_if(D.bases(), [&](
const CXXBaseSpecifier &I) {
64 return !I.isVirtual() && !isInterface(I);
69 NumConcrete += llvm::count_if(
70 D.vbases(), [&](
const CXXBaseSpecifier &V) { return !isInterface(V); });
73 diag(D.getBeginLoc(),
"inheriting multiple classes that aren't "
74 "pure virtual is discouraged");
void registerMatchers(ast_matchers::MatchFinder *Finder) override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
AST_MATCHER(BinaryOperator, isRelationalOperator)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//