Skip to content

Commit 941df8d

Browse files
committed
Address review comments
1 parent 5761260 commit 941df8d

File tree

1 file changed

+54
-53
lines changed

1 file changed

+54
-53
lines changed

clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
554557
bool 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+
615627
void 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

628634
void 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

641642
void handleNonConstMemberCall(const CallExpr *CE,

0 commit comments

Comments
 (0)