10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
21 switch (Node.getOverloadedOperator()) {
35 if (Node.isVariadic())
42 return Node.getNumParams() > 1;
43 if (Node.getNumParams() == 1)
50 if (Node.getNumParams() <= 1 || Node.getNumParams() > 2)
53 const auto *FPT = Node.getType()->castAs<FunctionProtoType>();
54 ASTContext &Ctx = Node.getASTContext();
55 if (Ctx.getLangOpts().SizedDeallocation &&
56 Ctx.hasSameType(FPT->getParamType(1), Ctx.getSizeType()))
65 switch (FD->getOverloadedOperator()) {
73 return OO_Array_Delete;
77 llvm_unreachable(
"Not an overloaded allocation operator");
85 return "operator new";
87 return "operator delete";
89 return "operator new[]";
91 return "operator delete[]";
93 llvm_unreachable(
"Not an overloaded allocation operator");
97 const FunctionDecl *RHS) {
103 const CXXRecordDecl *RD =
nullptr) {
106 for (
const auto *BMD : RD->methods())
107 if (BMD->isOverloadedOperator() && BMD->getAccess() != AS_private &&
114 RD = MD->getParent();
117 for (
const auto &BS : RD->bases()) {
120 if (BS.getType()->isDependentType())
122 if (
const auto *BaseRD = BS.getType()->getAsCXXRecordDecl())
140 functionDecl(unless(anyOf(isImplicit(), isPlacementOverload(),
141 isDeleted(), cxxMethodDecl(isPrivate()))),
142 anyOf(hasOverloadedOperatorName(
"new"),
143 hasOverloadedOperatorName(
"new[]"),
144 hasOverloadedOperatorName(
"delete"),
145 hasOverloadedOperatorName(
"delete[]")))
153 const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
154 const CXXRecordDecl *RD =
nullptr;
155 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD))
156 RD = MD->getParent();
157 Overloads[RD].push_back(FD);
165 SmallVector<const FunctionDecl *, 4> Diagnose;
166 for (
const auto &RP : Overloads) {
170 for (
const auto *Overload : RP.second) {
172 llvm::find_if(RP.second, [&Overload](
const FunctionDecl *FD) {
177 if (FD->getDeclContext() != Overload->getDeclContext())
182 if (!areCorrespondingOverloads(Overload, FD))
188 if (Match == RP.second.end()) {
192 const auto *MD = dyn_cast<CXXMethodDecl>(Overload);
194 Diagnose.push_back(Overload);
199 for (
const auto *FD : Diagnose)
200 diag(FD->getLocation(),
"declaration of %0 has no matching declaration "
201 "of '%1' at the same scope")
void onEndOfTranslationUnit() override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
AST_MATCHER(BinaryOperator, isRelationalOperator)
static bool areCorrespondingOverloads(const FunctionDecl *LHS, const FunctionDecl *RHS)
static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD)
static bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD, const CXXRecordDecl *RD=nullptr)
static const char * getOperatorName(OverloadedOperatorKind K)