@@ -211,6 +211,31 @@ static auto isStatusConstructor() {
211211 using namespace ::clang::ast_matchers; // NOLINT: Too many names
212212 return cxxConstructExpr (hasType (statusType ()));
213213}
214+ static auto isLoggingGetReferenceableValueCall () {
215+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
216+ return callExpr (callee (
217+ functionDecl (hasName (" ::absl::log_internal::GetReferenceableValue" ))));
218+ }
219+
220+ static auto isLoggingCheckEqImpl () {
221+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
222+ return callExpr (
223+ callee (functionDecl (hasName (" ::absl::log_internal::Check_EQImpl" ))));
224+ }
225+
226+ static auto isAsStatusCallWithStatus () {
227+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
228+ return callExpr (
229+ callee (functionDecl (hasName (" ::absl::log_internal::AsStatus" ))),
230+ hasArgument (0 , hasType (statusClass ())));
231+ }
232+
233+ static auto isAsStatusCallWithStatusOr () {
234+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
235+ return callExpr (
236+ callee (functionDecl (hasName (" ::absl::log_internal::AsStatus" ))),
237+ hasArgument (0 , hasType (statusOrType ())));
238+ }
214239
215240static auto
216241buildDiagnoseMatchSwitch (const UncheckedStatusOrAccessModelOptions &Options) {
@@ -602,6 +627,76 @@ static void transferStatusConstructor(const CXXConstructExpr *Expr,
602627 if (State.Env .getValue (locForOk (StatusLoc)) == nullptr )
603628 initializeStatus (StatusLoc, State.Env );
604629}
630+ static void
631+ transferLoggingGetReferenceableValueCall (const CallExpr *Expr,
632+ const MatchFinder::MatchResult &,
633+ LatticeTransferState &State) {
634+ assert (Expr->getNumArgs () == 1 );
635+ if (Expr->getArg (0 )->isPRValue ())
636+ return ;
637+ auto *ArgLoc = State.Env .getStorageLocation (*Expr->getArg (0 ));
638+ if (ArgLoc == nullptr )
639+ return ;
640+
641+ State.Env .setStorageLocation (*Expr, *ArgLoc);
642+ }
643+
644+ static void transferLoggingCheckEqImpl (const CallExpr *Expr,
645+ const MatchFinder::MatchResult &,
646+ LatticeTransferState &State) {
647+ assert (Expr->getNumArgs () > 2 );
648+
649+ auto *EqVal = evaluateEquality (Expr->getArg (0 ), Expr->getArg (1 ), State.Env );
650+ if (EqVal == nullptr )
651+ return ;
652+
653+ // Consider modelling this more accurately instead of assigning BoolValue
654+ // as the value of an expression of pointer type.
655+ // For now, this is being handled in transferPointerToBoolean.
656+ State.Env .setValue (*Expr, State.Env .makeNot (*EqVal));
657+ }
658+
659+ static void transferAsStatusCallWithStatus (const CallExpr *Expr,
660+ const MatchFinder::MatchResult &,
661+ LatticeTransferState &State) {
662+ assert (Expr->getNumArgs () == 1 );
663+
664+ auto *ArgLoc = State.Env .get <RecordStorageLocation>(*Expr->getArg (0 ));
665+ if (ArgLoc == nullptr )
666+ return ;
667+
668+ if (State.Env .getValue (locForOk (*ArgLoc)) == nullptr )
669+ initializeStatus (*ArgLoc, State.Env );
670+
671+ auto &ExprVal = State.Env .create <PointerValue>(*ArgLoc);
672+ State.Env .setValue (*Expr, ExprVal);
673+ }
674+
675+ static void transferAsStatusCallWithStatusOr (const CallExpr *Expr,
676+ const MatchFinder::MatchResult &,
677+ LatticeTransferState &State) {
678+ assert (Expr->getNumArgs () == 1 );
679+
680+ auto *ArgLoc = State.Env .get <RecordStorageLocation>(*Expr->getArg (0 ));
681+ if (ArgLoc == nullptr )
682+ return ;
683+
684+ RecordStorageLocation &StatusLoc = locForStatus (*ArgLoc);
685+
686+ if (State.Env .getValue (locForOk (StatusLoc)) == nullptr )
687+ initializeStatusOr (*ArgLoc, State.Env );
688+
689+ auto &ExprVal = State.Env .create <PointerValue>(StatusLoc);
690+ State.Env .setValue (*Expr, ExprVal);
691+ }
692+
693+ static void transferPointerToBoolean (const ImplicitCastExpr *Expr,
694+ const MatchFinder::MatchResult &,
695+ LatticeTransferState &State) {
696+ if (auto *SubExprVal =
697+ dyn_cast_or_null<BoolValue>(State.Env .getValue (*Expr->getSubExpr ())))
698+ State.Env .setValue (*Expr, *SubExprVal);
699+ }
605700
606701CFGMatchSwitch<LatticeTransferState>
607702buildTransferMatchSwitch (ASTContext &Ctx,
@@ -652,6 +747,14 @@ buildTransferMatchSwitch(ASTContext &Ctx,
652747 transferValueAssignmentCall)
653748 .CaseOfCFGStmt <CXXConstructExpr>(isStatusOrValueConstructor (),
654749 transferValueConstructor)
750+ .CaseOfCFGStmt <CallExpr>(isAsStatusCallWithStatus (),
751+ transferAsStatusCallWithStatus)
752+ .CaseOfCFGStmt <CallExpr>(isAsStatusCallWithStatusOr (),
753+ transferAsStatusCallWithStatusOr)
754+ .CaseOfCFGStmt <CallExpr>(isLoggingGetReferenceableValueCall (),
755+ transferLoggingGetReferenceableValueCall)
756+ .CaseOfCFGStmt <CallExpr>(isLoggingCheckEqImpl (),
757+ transferLoggingCheckEqImpl)
655758 // N.B. These need to come after all other CXXConstructExpr.
656759 // These are there to make sure that every Status and StatusOr object
657760 // have their ok boolean initialized when constructed. If we were to
@@ -662,6 +765,9 @@ buildTransferMatchSwitch(ASTContext &Ctx,
662765 transferStatusOrConstructor)
663766 .CaseOfCFGStmt <CXXConstructExpr>(isStatusConstructor (),
664767 transferStatusConstructor)
768+ .CaseOfCFGStmt <ImplicitCastExpr>(
769+ implicitCastExpr (hasCastKind (CK_PointerToBoolean)),
770+ transferPointerToBoolean)
665771 .Build ();
666772}
667773
0 commit comments