================ @@ -3068,12 +3124,225 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, C.addTransition(state->set<RegionState>(RS), N); } +// Helper function to check if a name is a recognized smart owning pointer name +static bool isSmartOwningPtrName(StringRef Name) { + return Name == "unique_ptr" || Name == "shared_ptr"; +} + +// Allowlist of owning smart pointers we want to recognize. +// Start with unique_ptr and shared_ptr. (intentionally exclude weak_ptr) +static bool isSmartOwningPtrType(QualType QT) { + QT = QT->getCanonicalTypeUnqualified(); + + // First try TemplateSpecializationType (for both std and custom smart + // pointers) + if (const auto *TST = QT->getAs<TemplateSpecializationType>()) { + const TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl(); + if (!TD) + return false; + + const auto *ND = dyn_cast_or_null<NamedDecl>(TD->getTemplatedDecl()); + if (!ND) + return false; + + // Accept both std and custom smart pointer implementations for broader + // coverage + return isSmartOwningPtrName(ND->getName()); + } + + return false; +} + +/// Check if a record type has smart owning pointer fields (directly or in base +/// classes). +static bool hasSmartOwningPtrField(const CXXRecordDecl *CRD) { + // Check direct fields + if (llvm::any_of(CRD->fields(), [](const FieldDecl *FD) { + return isSmartOwningPtrType(FD->getType()); + })) + return true; + + // Check fields from base classes + for (const CXXBaseSpecifier &Base : CRD->bases()) { + if (const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl()) { + if (hasSmartOwningPtrField(BaseDecl)) + return true; + } + } + return false; +} + +/// Check if an expression is an rvalue record type passed by value. +static bool isRvalueByValueRecord(const Expr *AE) { + if (AE->isGLValue()) + return false; + + QualType T = AE->getType(); + if (!T->isRecordType() || T->isReferenceType()) + return false; + + // Accept common temp/construct forms but don't overfit. + return isa<CXXTemporaryObjectExpr, MaterializeTemporaryExpr, CXXConstructExpr, + InitListExpr, ImplicitCastExpr, CXXBindTemporaryExpr>(AE); +} + +/// Check if an expression is an rvalue record with smart owning pointer fields +/// passed by value. +static bool isRvalueByValueRecordWithSmartOwningPtr(const Expr *AE) { + if (!isRvalueByValueRecord(AE)) + return false; + + const auto *CRD = AE->getType()->getAsCXXRecordDecl(); + return CRD && hasSmartOwningPtrField(CRD); +} + +/// Check if a CXXRecordDecl has a name matching recognized smart pointer names. +static bool isSmartOwningPtrRecord(const CXXRecordDecl *RD) { + if (!RD) + return false; + + // Check the record name directly and accept both std and custom smart pointer + // implementations for broader coverage + return isSmartOwningPtrName(RD->getName()); +} + +/// Check if a call is a constructor of a smart owning pointer class that +/// accepts pointer parameters. +static bool isSmartOwningPtrCall(const CallEvent &Call) { + // Only check for smart pointer constructor calls + const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Call.getDecl()); + if (!CD) + return false; + + const auto *RD = CD->getParent(); + if (!isSmartOwningPtrRecord(RD)) + return false; + + // Check if constructor takes a pointer parameter + for (const auto *Param : CD->parameters()) { + QualType ParamType = Param->getType(); + if (ParamType->isPointerType() && !ParamType->isFunctionPointerType() && + !ParamType->isVoidPointerType()) { + return true; + } + } + + return false; +} + +static void collectSmartOwningPtrFieldRegions( + const MemRegion *Base, QualType RecQT, CheckerContext &C, ---------------- ivanmurashko wrote:
Good point. I applied the name change in 49b7d31d174559b343d83a3629b35e03a36d96e0. https://github.com/llvm/llvm-project/pull/152751 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits