11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 using namespace clang;
23 if (Node.hasDefinition())
24 return Node.getNumBases() > 0;
31 void MultipleInheritanceCheck::addNodeToInterfaceMap(
const CXXRecordDecl *Node,
33 assert(Node->getIdentifier());
34 StringRef
Name = Node->getIdentifier()->getName();
35 InterfaceMap.insert(std::make_pair(Name, isInterface));
41 bool MultipleInheritanceCheck::getInterfaceStatus(
const CXXRecordDecl *Node,
42 bool &isInterface)
const {
43 assert(Node->getIdentifier());
44 StringRef Name = Node->getIdentifier()->getName();
45 llvm::StringMapConstIterator<bool> Pair = InterfaceMap.find(Name);
46 if (Pair == InterfaceMap.end())
48 isInterface = Pair->second;
52 bool MultipleInheritanceCheck::isCurrentClassInterface(
53 const CXXRecordDecl *Node)
const {
55 if (!Node->field_empty())
return false;
58 return llvm::none_of(Node->methods(), [](
const CXXMethodDecl *M) {
59 return M->isUserProvided() && !M->isPure() && !M->isStatic();
63 bool MultipleInheritanceCheck::isInterface(
const CXXRecordDecl *Node) {
64 if (!Node->getIdentifier())
68 bool PreviousIsInterfaceResult;
69 if (getInterfaceStatus(Node, PreviousIsInterfaceResult))
70 return PreviousIsInterfaceResult;
73 for (
const auto &I : Node->bases()) {
74 if (I.isVirtual())
continue;
75 const auto *Ty = I.getType()->getAs<RecordType>();
77 const RecordDecl *D = Ty->getDecl()->getDefinition();
79 const auto *Base = cast<CXXRecordDecl>(D);
80 if (!isInterface(Base)) {
81 addNodeToInterfaceMap(Node,
false);
86 bool CurrentClassIsInterface = isCurrentClassInterface(Node);
87 addNodeToInterfaceMap(Node, CurrentClassIsInterface);
88 return CurrentClassIsInterface;
91 void MultipleInheritanceCheck::registerMatchers(MatchFinder *Finder) {
93 if (!getLangOpts().CPlusPlus)
97 Finder->addMatcher(cxxRecordDecl(hasBases()).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->getLocStart(),
124 "inheriting mulitple classes that aren't " 125 "pure virtual is discouraged");
AST_MATCHER(BinaryOperator, isAssignmentOperator)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//