@@ -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) {
@@ -482,6 +543,20 @@ buildTransferMatchSwitch(ASTContext &Ctx,
482543 transferComparisonOperator (Expr, State,
483544 /* IsNegative=*/ true );
484545 })
546+ .CaseOfCFGStmt <BinaryOperator>(
547+ isPointerComparisonOperatorCall (" ==" ),
548+ [](const BinaryOperator *Expr, const MatchFinder::MatchResult &,
549+ LatticeTransferState &State) {
550+ transferPointerComparisonOperator (Expr, State,
551+ /* IsNegative=*/ false );
552+ })
553+ .CaseOfCFGStmt <BinaryOperator>(
554+ isPointerComparisonOperatorCall (" !=" ),
555+ [](const BinaryOperator *Expr, const MatchFinder::MatchResult &,
556+ LatticeTransferState &State) {
557+ transferPointerComparisonOperator (Expr, State,
558+ /* IsNegative=*/ true );
559+ })
485560 .CaseOfCFGStmt <CallExpr>(isOkStatusCall (), transferOkStatusCall)
486561 .CaseOfCFGStmt <CallExpr>(isNotOkStatusCall (), transferNotOkStatusCall)
487562 .Build ();
0 commit comments