void ParentVirtualCallCheck::check(const MatchFinder::MatchResult &Result) { const auto *Member = Result.Nodes.getNodeAs<MemberExpr>("member"); assert(Member); if (!Member->getQualifier()) return; const auto *MemberDecl = cast<CXXMethodDecl>(Member->getMemberDecl()); const auto *ThisTypePtr = Result.Nodes.getNodeAs<PointerType>("thisType"); assert(ThisTypePtr); const auto *ThisType = ThisTypePtr->getPointeeCXXRecordDecl(); assert(ThisType); const auto *CastToTypePtr = Result.Nodes.getNodeAs<Type>("castToType"); assert(CastToTypePtr); const auto *CastToType = CastToTypePtr->getAsCXXRecordDecl(); assert(CastToType); if (isParentOf(*CastToType, *ThisType)) return; const BasesVector Parents = getParentsByGrandParent(*CastToType, *ThisType, *MemberDecl); if (Parents.empty()) return; std::string ParentsStr; ParentsStr.reserve(30 * Parents.size()); for (const CXXRecordDecl *Parent : Parents) { if (!ParentsStr.empty()) ParentsStr.append(" or "); ParentsStr.append("'").append(getNameAsString(Parent)).append("'"); } assert(Member->getQualifierLoc().getSourceRange().getBegin().isValid()); auto Diag = diag(Member->getQualifierLoc().getSourceRange().getBegin(), "qualified name '%0' refers to a member overridden " "in subclass%1; did you mean %2?") << getExprAsString(*Member, *Result.Context) << (Parents.size() > 1 ? "es" : "") << ParentsStr; // Propose a fix if there's only one parent class... if (Parents.size() == 1 && // ...unless parent class is templated !isa<ClassTemplateSpecializationDecl>(Parents.front())) Diag << FixItHint::CreateReplacement( Member->getQualifierLoc().getSourceRange(), getNameAsString(Parents.front()) + "::"); }
bool isObjCInterfaceClassOrSubclass( const clang::ObjCInterfaceDecl* decl, const std::string& className) { for(auto current = decl; current != nullptr; current = current->getSuperClass()) { if(current->getNameAsString() == className) { return true; } } return false; }
void collectUnifiedSymbolResoltions(clang::ASTContext &astContext, const clang::SourceLocation &cursorSourceLocation) { const auto foundDeclarations = namedDeclarationsAt(astContext, cursorSourceLocation); if (!foundDeclarations.empty()) { const auto firstFoundDeclaration = foundDeclarations.front(); if (const auto *constructorDecl = clang::dyn_cast<clang::CXXConstructorDecl>(firstFoundDeclaration)) { const clang::CXXRecordDecl *foundDeclarationParent = constructorDecl->getParent(); unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent); } else if (const auto *destructorDecl = clang::dyn_cast<clang::CXXDestructorDecl>(firstFoundDeclaration)) { const clang::CXXRecordDecl *foundDeclarationParent = destructorDecl->getParent(); unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent); } else if (const auto *recordDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(firstFoundDeclaration)) { unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(recordDeclaration); } addUnifiedSymbolResolutionsForDeclaration(foundDeclarations, unifiedSymbolResolutions); symbolName = firstFoundDeclaration->getNameAsString(); } }
std::string FunctionState::getNameAsString() const { auto const FunctionDecl = getFunctionDecl(); return FunctionDecl ? FunctionDecl->getNameAsString() : UnmappedState.getFunction()->getName().str(); }