@@ -551,91 +551,92 @@ void transferCallReturningOptional(const CallExpr *E,
551551 setHasValue (*Loc, State.Env .makeAtomicBoolValue (), State.Env );
552552}
553553
554+ // Returns true if the const accessor is handled by caching.
555+ // Returns false if we could not cache. We should perform default handling
556+ // in that case.
554557bool handleConstMemberCall (const CallExpr *CE,
555558 dataflow::RecordStorageLocation *RecordLoc,
556559 const MatchFinder::MatchResult &Result,
557560 LatticeTransferState &State) {
558561 if (RecordLoc == nullptr )
559562 return false ;
560563
561- // If the const method returns an optional or reference to an optional.
562- if (isSupportedOptionalType (CE->getType ())) {
563- const FunctionDecl *DirectCallee = CE->getDirectCallee ();
564- if (DirectCallee == nullptr )
565- return false ;
566- StorageLocation &Loc =
567- State.Lattice .getOrCreateConstMethodReturnStorageLocation (
568- *RecordLoc, DirectCallee, State.Env , [&](StorageLocation &Loc) {
569- setHasValue (cast<RecordStorageLocation>(Loc),
570- State.Env .makeAtomicBoolValue (), State.Env );
571- });
572- if (CE->isGLValue ()) {
573- // If the call to the const method returns a reference to an optional,
574- // link the call expression to the cached StorageLocation.
575- State.Env .setStorageLocation (*CE, Loc);
576- } else {
577- // If the call to the const method returns an optional by value, we
578- // need to use CopyRecord to link the optional to the result object
579- // of the call expression.
580- auto &ResultLoc = State.Env .getResultObjectLocation (*CE);
581- copyRecord (cast<RecordStorageLocation>(Loc), ResultLoc, State.Env );
582- }
583- return true ;
584- }
585-
586- // Cache if the const method returns a reference
564+ // Cache if the const method returns a reference.
587565 if (CE->isGLValue ()) {
588566 const FunctionDecl *DirectCallee = CE->getDirectCallee ();
589567 if (DirectCallee == nullptr )
590568 return false ;
591569
570+ // Initialize the optional's "has_value" property to true if the type is
571+ // optional, otherwise no-op. If we want to support const ref to pointers or
572+ // bools we should initialize their values here too.
573+ auto Init = [&](StorageLocation &Loc) {
574+ if (isSupportedOptionalType (CE->getType ()))
575+ setHasValue (cast<RecordStorageLocation>(Loc),
576+ State.Env .makeAtomicBoolValue (), State.Env );
577+ };
592578 StorageLocation &Loc =
593579 State.Lattice .getOrCreateConstMethodReturnStorageLocation (
594- *RecordLoc, DirectCallee, State.Env , [&](StorageLocation &Loc) {
595- // no-op
596- // NOTE: if we want to support const ref to pointers or bools
597- // we should initialize their values here.
598- });
580+ *RecordLoc, DirectCallee, State.Env , Init);
599581
600582 State.Env .setStorageLocation (*CE, Loc);
601583 return true ;
602- } else if (CE->getType ()->isBooleanType () || CE->getType ()->isPointerType ()) {
603- // Cache if the const method returns a boolean or pointer type.
604- Value *Val = State.Lattice .getOrCreateConstMethodReturnValue (*RecordLoc, CE,
605- State.Env );
606- if (Val == nullptr )
607- return false ;
608- State.Env .setValue (*CE, *Val);
609- return true ;
584+ } else {
585+ // PRValue cases:
586+ if (CE->getType ()->isBooleanType () || CE->getType ()->isPointerType ()) {
587+ // If the const method returns a boolean or pointer type.
588+ Value *Val = State.Lattice .getOrCreateConstMethodReturnValue (
589+ *RecordLoc, CE, State.Env );
590+ if (Val == nullptr )
591+ return false ;
592+ State.Env .setValue (*CE, *Val);
593+ return true ;
594+ } else if (isSupportedOptionalType (CE->getType ())) {
595+ // If the const method returns an optional by value.
596+ const FunctionDecl *DirectCallee = CE->getDirectCallee ();
597+ if (DirectCallee == nullptr )
598+ return false ;
599+ StorageLocation &Loc =
600+ State.Lattice .getOrCreateConstMethodReturnStorageLocation (
601+ *RecordLoc, DirectCallee, State.Env , [&](StorageLocation &Loc) {
602+ setHasValue (cast<RecordStorageLocation>(Loc),
603+ State.Env .makeAtomicBoolValue (), State.Env );
604+ });
605+ // Use copyRecord to link the optional to the result object of the call
606+ // expression.
607+ auto &ResultLoc = State.Env .getResultObjectLocation (*CE);
608+ copyRecord (cast<RecordStorageLocation>(Loc), ResultLoc, State.Env );
609+ return true ;
610+ }
610611 }
611612
612613 return false ;
613614}
614615
616+ void handleConstMemberCallWithFallbacks (
617+ const CallExpr *CE, dataflow::RecordStorageLocation *RecordLoc,
618+ const MatchFinder::MatchResult &Result, LatticeTransferState &State) {
619+ if (handleConstMemberCall (CE, RecordLoc, Result, State))
620+ return ;
621+ // Perform default handling if the call returns an optional, but wasn't
622+ // handled by caching.
623+ if (isSupportedOptionalType (CE->getType ()))
624+ transferCallReturningOptional (CE, Result, State);
625+ }
626+
615627void transferConstMemberCall (const CXXMemberCallExpr *MCE,
616628 const MatchFinder::MatchResult &Result,
617629 LatticeTransferState &State) {
618- if (!handleConstMemberCall (
619- MCE, dataflow::getImplicitObjectLocation (*MCE, State.Env ), Result,
620- State)) {
621- // Perform default handling if the call returns an optional,
622- // but wasn't handled.
623- if (isSupportedOptionalType (MCE->getType ()))
624- transferCallReturningOptional (MCE, Result, State);
625- }
630+ handleConstMemberCallWithFallbacks (
631+ MCE, dataflow::getImplicitObjectLocation (*MCE, State.Env ), Result, State);
626632}
627633
628634void transferConstMemberOperatorCall (const CXXOperatorCallExpr *OCE,
629635 const MatchFinder::MatchResult &Result,
630636 LatticeTransferState &State) {
631637 auto *RecordLoc = cast_or_null<dataflow::RecordStorageLocation>(
632638 State.Env .getStorageLocation (*OCE->getArg (0 )));
633- if (!handleConstMemberCall (OCE, RecordLoc, Result, State)) {
634- // Perform default handling if the call returns an optional,
635- // but wasn't handled.
636- if (isSupportedOptionalType (OCE->getType ()))
637- transferCallReturningOptional (OCE, Result, State);
638- }
639+ handleConstMemberCallWithFallbacks (OCE, RecordLoc, Result, State);
639640}
640641
641642void handleNonConstMemberCall (const CallExpr *CE,
0 commit comments