@@ -168,6 +168,15 @@ static auto isNotOkStatusCall() {
168168 " ::absl::UnimplementedError" , " ::absl::UnknownError" ))));
169169}
170170
171+ static auto isPointerComparisonOperatorCall (std::string operator_name) {
172+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
173+ return binaryOperator (hasOperatorName (operator_name),
174+ hasLHS (hasType (hasCanonicalType (pointerType (
175+ pointee (anyOf (statusOrType (), statusType ())))))),
176+ hasRHS (hasType (hasCanonicalType (pointerType (
177+ pointee (anyOf (statusOrType (), statusType ())))))));
178+ }
179+
171180static auto
172181buildDiagnoseMatchSwitch (const UncheckedStatusOrAccessModelOptions &Options) {
173182 return CFGMatchSwitchBuilder<const Environment,
@@ -438,6 +447,58 @@ static void transferComparisonOperator(const CXXOperatorCallExpr *Expr,
438447 State.Env .setValue (*Expr, *LhsAndRhsVal);
439448}
440449
450+ static RecordStorageLocation *getPointeeLocation (const Expr &Expr,
451+ Environment &Env) {
452+ if (auto *PointerVal = Env.get <PointerValue>(Expr))
453+ return dyn_cast<RecordStorageLocation>(&PointerVal->getPointeeLoc ());
454+ return nullptr ;
455+ }
456+
457+ static BoolValue *evaluatePointerEquality (const Expr *LhsExpr,
458+ const Expr *RhsExpr,
459+ Environment &Env) {
460+ assert (LhsExpr->getType ()->isPointerType ());
461+ assert (RhsExpr->getType ()->isPointerType ());
462+ RecordStorageLocation *LhsStatusLoc = nullptr ;
463+ RecordStorageLocation *RhsStatusLoc = nullptr ;
464+ if (isStatusOrType (LhsExpr->getType ()->getPointeeType ()) &&
465+ isStatusOrType (RhsExpr->getType ()->getPointeeType ())) {
466+ auto *LhsStatusOrLoc = getPointeeLocation (*LhsExpr, Env);
467+ auto *RhsStatusOrLoc = getPointeeLocation (*RhsExpr, Env);
468+ if (LhsStatusOrLoc == nullptr || RhsStatusOrLoc == nullptr )
469+ return nullptr ;
470+ LhsStatusLoc = &locForStatus (*LhsStatusOrLoc);
471+ RhsStatusLoc = &locForStatus (*RhsStatusOrLoc);
472+ } else if (isStatusType (LhsExpr->getType ()->getPointeeType ()) &&
473+ isStatusType (RhsExpr->getType ()->getPointeeType ())) {
474+ LhsStatusLoc = getPointeeLocation (*LhsExpr, Env);
475+ RhsStatusLoc = getPointeeLocation (*RhsExpr, Env);
476+ }
477+ if (LhsStatusLoc == nullptr || RhsStatusLoc == nullptr )
478+ return nullptr ;
479+ auto &LhsOkVal = valForOk (*LhsStatusLoc, Env);
480+ auto &RhsOkVal = valForOk (*RhsStatusLoc, Env);
481+ auto &Res = Env.makeAtomicBoolValue ();
482+ auto &A = Env.arena ();
483+ Env.assume (A.makeImplies (
484+ Res.formula (), A.makeEquals (LhsOkVal.formula (), RhsOkVal.formula ())));
485+ return &Res;
486+ }
487+
488+ static void transferPointerComparisonOperator (const BinaryOperator *Expr,
489+ LatticeTransferState &State,
490+ bool IsNegative) {
491+ auto *LhsAndRhsVal =
492+ evaluatePointerEquality (Expr->getLHS (), Expr->getRHS (), State.Env );
493+ if (LhsAndRhsVal == nullptr )
494+ return ;
495+
496+ if (IsNegative)
497+ State.Env .setValue (*Expr, State.Env .makeNot (*LhsAndRhsVal));
498+ else
499+ State.Env .setValue (*Expr, *LhsAndRhsVal);
500+ }
501+
441502static void transferOkStatusCall (const CallExpr *Expr,
442503 const MatchFinder::MatchResult &,
443504 LatticeTransferState &State) {
@@ -455,6 +516,18 @@ static void transferNotOkStatusCall(const CallExpr *Expr,
455516 State.Env .assume (A.makeNot (OkVal.formula ()));
456517}
457518
519+ static void transferEmplaceCall (const CXXMemberCallExpr *Expr,
520+ const MatchFinder::MatchResult &,
521+ LatticeTransferState &State) {
522+ RecordStorageLocation *StatusOrLoc =
523+ getImplicitObjectLocation (*Expr, State.Env );
524+ if (StatusOrLoc == nullptr )
525+ return ;
526+
527+ auto &OkVal = valForOk (locForStatus (*StatusOrLoc), State.Env );
528+ State.Env .assume (OkVal.formula ());
529+ }
530+
458531CFGMatchSwitch<LatticeTransferState>
459532buildTransferMatchSwitch (ASTContext &Ctx,
460533 CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
@@ -482,8 +555,24 @@ buildTransferMatchSwitch(ASTContext &Ctx,
482555 transferComparisonOperator (Expr, State,
483556 /* IsNegative=*/ true );
484557 })
558+ .CaseOfCFGStmt <BinaryOperator>(
559+ isPointerComparisonOperatorCall (" ==" ),
560+ [](const BinaryOperator *Expr, const MatchFinder::MatchResult &,
561+ LatticeTransferState &State) {
562+ transferPointerComparisonOperator (Expr, State,
563+ /* IsNegative=*/ false );
564+ })
565+ .CaseOfCFGStmt <BinaryOperator>(
566+ isPointerComparisonOperatorCall (" !=" ),
567+ [](const BinaryOperator *Expr, const MatchFinder::MatchResult &,
568+ LatticeTransferState &State) {
569+ transferPointerComparisonOperator (Expr, State,
570+ /* IsNegative=*/ true );
571+ })
485572 .CaseOfCFGStmt <CallExpr>(isOkStatusCall (), transferOkStatusCall)
486573 .CaseOfCFGStmt <CallExpr>(isNotOkStatusCall (), transferNotOkStatusCall)
574+ .CaseOfCFGStmt <CXXMemberCallExpr>(isStatusOrMemberCallWithName (" emplace" ),
575+ transferEmplaceCall)
487576 .Build ();
488577}
489578
0 commit comments