================ @@ -11,16 +11,118 @@ #include "PtrTypesSemantics.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/StmtVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include <optional> using namespace clang; using namespace ento; namespace { + +class DerefFuncDeleteExprVisitor + : public ConstStmtVisitor<DerefFuncDeleteExprVisitor, bool> { + // Returns true if any of child statements return true. + bool VisitChildren(const Stmt *S) { + for (const Stmt *Child : S->children()) { + if (Child && Visit(Child)) + return true; + } + return false; + } + + bool VisitBody(const Stmt *Body) { + if (!Body) + return false; + + auto [It, IsNew] = VisitedBody.insert(Body); + if (!IsNew) // This body is recursive + return false; + + return Visit(Body); + } + +public: + DerefFuncDeleteExprVisitor(const TemplateArgumentList &ArgList, + const CXXRecordDecl *ClassDecl) + : ArgList(&ArgList), ClassDecl(ClassDecl) {} + + DerefFuncDeleteExprVisitor(const CXXRecordDecl *ClassDecl) + : ClassDecl(ClassDecl) {} + + std::optional<bool> HasSpecializedDelete(CXXMethodDecl *Decl) { + if (auto *Body = Decl->getBody()) + return VisitBody(Body); + if (auto *Tmpl = Decl->getTemplateInstantiationPattern()) + return std::nullopt; // Indeterminate. There was no concrete instance. + return false; + } + + bool VisitCallExpr(const CallExpr *CE) { + const Decl *D = CE->getCalleeDecl(); + if (D && D->hasBody()) + return VisitBody(D->getBody()); + return false; + } + + bool VisitCXXDeleteExpr(const CXXDeleteExpr *E) { + auto *Arg = E->getArgument(); + while (Arg) { + if (auto *Paren = dyn_cast<ParenExpr>(Arg)) + Arg = Paren->getSubExpr(); + else if (auto *Cast = dyn_cast<CastExpr>(Arg)) { + Arg = Cast->getSubExpr(); + auto CastType = Cast->getType(); + if (auto *PtrType = dyn_cast<PointerType>(CastType)) { + auto PointeeType = PtrType->getPointeeType(); + while (auto *ET = dyn_cast<ElaboratedType>(PointeeType)) { + if (ET->isSugared()) + PointeeType = ET->desugar(); + } + if (auto *ParmType = dyn_cast<TemplateTypeParmType>(PointeeType)) { + if (ArgList) { + auto ParmIndex = ParmType->getIndex(); + auto Type = ArgList->get(ParmIndex).getAsType(); + if (auto *RD = dyn_cast<RecordType>(Type)) { ---------------- haoNoQ wrote:
`Type->getAsCXXRecordDecl() == ClassDecl` is a bit shorter, and you probably don't even need to null-check, because `ClassDecl` is never null anyway. https://github.com/llvm/llvm-project/pull/92837 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits