@@ -631,38 +631,48 @@ void FactsGenerator::VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE) {
631631 Dst->getOuterOriginID (), Src->getOuterOriginID (), /* Kill=*/ true ));
632632}
633633
634+ void FactsGenerator::handlePlacementNew (const CXXNewExpr *NE ,
635+ OriginList *NewList) {
636+ // Model only the standard single-argument placement new form, where the
637+ // placement argument corresponds to a void* allocation-function parameter.
638+ // Other placement forms, such as std::nothrow, are not modeled as providing
639+ // storage for the returned pointer.
640+ if (NE ->getNumPlacementArgs () != 1 )
641+ return ;
642+
643+ const FunctionDecl *OperatorNew = NE ->getOperatorNew ();
644+ if (OperatorNew->getNumParams () <= 1 )
645+ return ;
646+
647+ const auto *Arg =
648+ OperatorNew->getParamDecl (1 )->getType ()->getAs <PointerType>();
649+ if (!Arg || !Arg->isVoidPointerType ())
650+ return ;
651+
652+ // Use the placement argument before the implicit conversion to void*, so
653+ // inner origins are still available.
654+ const Expr *PlacementArg = NE ->getPlacementArg (0 );
655+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PlacementArg);
656+ ICE && ICE ->getCastKind () == CK_BitCast &&
657+ PlacementArg->getType ()->isVoidPointerType ())
658+ PlacementArg = ICE ->getSubExpr ();
659+ OriginList *PlacementList = getOriginsList (*PlacementArg);
660+ // FIXME: General placement arguments need separate handling to overwrite
661+ // the right origins.
662+
663+ // The pointer returned by placement new comes from the placement
664+ // argument.
665+ if (PlacementList)
666+ CurrentBlockFacts.push_back (FactMgr.createFact <OriginFlowFact>(
667+ NewList->getOuterOriginID (), PlacementList->getOuterOriginID (), true ));
668+ }
669+
634670void FactsGenerator::VisitCXXNewExpr (const CXXNewExpr *NE ) {
635671 OriginList *NewList = getOriginsList (*NE );
636672 const Expr *Init = NE ->getInitializer ();
637673
638- // Check if we have a placement new where the second argument is void*, to
639- // avoid flowing from non-pointer parameters, such as std::nothrow.
640- // And that the placement parameter num is 1,
641- // that is to mostly limit to standard library placement new.
642674 if (NE ->getNumPlacementArgs () == 1 ) {
643- if (const auto *Arg = NE ->getOperatorNew ()
644- ->getParamDecl (1 )
645- ->getType ()
646- ->getAs <PointerType>();
647- Arg && Arg->isVoidPointerType ()) {
648- // Use the placement argument before the implicit conversion to void*, so
649- // inner origins are still available.
650- const Expr *PlacementArg = NE ->getPlacementArg (0 );
651- if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PlacementArg);
652- ICE && ICE ->getCastKind () == CK_BitCast &&
653- PlacementArg->getType ()->isVoidPointerType ())
654- PlacementArg = ICE ->getSubExpr ();
655- OriginList *PlacementList = getOriginsList (*PlacementArg);
656- // FIXME: General placement arguments need separate handling to overwrite
657- // the right origins.
658-
659- // The pointer returned by placement new comes from the placement
660- // argument.
661- if (PlacementList)
662- CurrentBlockFacts.push_back (FactMgr.createFact <OriginFlowFact>(
663- NewList->getOuterOriginID (), PlacementList->getOuterOriginID (),
664- true ));
665- }
675+ handlePlacementNew (NE , NewList);
666676 } else {
667677 const Loan *L = createLoan (FactMgr, NE );
668678 CurrentBlockFacts.push_back (
0 commit comments