================ @@ -267,12 +286,128 @@ class FuchsiaHandleSymbolVisitor final : public SymbolVisitor { private: SmallVector<SymbolRef, 1024> Symbols; }; + +class FuchsiaBugVisitor final : public BugReporterVisitor { + // Handle that caused a problem. + SymbolRef Sym; + + bool IsLeak; + +public: + FuchsiaBugVisitor(SymbolRef S, bool Leak = false) : Sym(S), IsLeak(Leak) {} + + void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.AddPointer(Sym); + } + + static inline bool isAllocated(const HandleState *RSCurr, + const HandleState *RSPrev, const Stmt *Stmt) { + return isa_and_nonnull<CallExpr>(Stmt) && + ((RSCurr && (RSCurr->isAllocated() || RSCurr->maybeAllocated()) && + (!RSPrev || + !(RSPrev->isAllocated() || RSPrev->maybeAllocated())))); + } + + static inline bool isAllocatedUnowned(const HandleState *RSCurr, + const HandleState *RSPrev, + const Stmt *Stmt) { + return isa_and_nonnull<CallExpr>(Stmt) && + ((RSCurr && RSCurr->isUnowned()) && + (!RSPrev || !RSPrev->isUnowned())); + } + + static inline bool isReleased(const HandleState *RSCurr, + const HandleState *RSPrev, const Stmt *Stmt) { + return isa_and_nonnull<CallExpr>(Stmt) && + ((RSCurr && RSCurr->isReleased()) && + (!RSPrev || !RSPrev->isReleased())); + } + + PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) override; + + PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, + const ExplodedNode *EndPathNode, + PathSensitiveBugReport &BR) override { + if (!IsLeak) + return nullptr; + + PathDiagnosticLocation L = BR.getLocation(); + // Do not add the statement itself as a range in case of leak. + return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(), + false); + } +}; } // end anonymous namespace +PathDiagnosticPieceRef +FuchsiaBugVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { + ProgramStateRef State = N->getState(); + ProgramStateRef StatePrev = N->getFirstPred()->getState(); + + const HandleState *RSCurr = State->get<HStateMap>(Sym); + const HandleState *RSPrev = StatePrev->get<HStateMap>(Sym); + + const Stmt *S = N->getStmtForDiagnostics(); + + StringRef Msg; + SmallString<256> Buf; + llvm::raw_svector_ostream OS(Buf); + + if (isAllocated(RSCurr, RSPrev, S)) { + auto Index = RSCurr->getIndex(); + + if (Index > 0) + OS << "Handle allocated through " << Index + << llvm::getOrdinalSuffix(Index) << " parameter"; + else + OS << "Function returns an open handle"; + + Msg = OS.str(); + } else if (isAllocatedUnowned(RSCurr, RSPrev, S)) { + auto Index = RSCurr->getIndex(); + + if (Index > 0) + OS << "Unowned handle allocated through " << Index + << llvm::getOrdinalSuffix(Index) << " parameter"; + else + OS << "Function returns an unowned handle"; + + Msg = OS.str(); + } else if (isReleased(RSCurr, RSPrev, S)) { + auto Index = RSCurr->getIndex(); + + assert(Index > 0); + + OS << "Handle released through " << Index << llvm::getOrdinalSuffix(Index) + << " parameter"; + Msg = OS.str(); + } + + if (Msg.empty()) + return nullptr; + + PathDiagnosticLocation Pos; + if (!S) { + auto PostImplCall = N->getLocation().getAs<PostImplicitCall>(); + if (!PostImplCall) + return nullptr; + Pos = PathDiagnosticLocation(PostImplCall->getLocation(), + BRC.getSourceManager()); ---------------- NagyDonat wrote:
What is the goal of this logic? Perhaps add a brief comment that explains this. https://github.com/llvm/llvm-project/pull/111588 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits