@@ -372,10 +372,26 @@ bool isNonEmptyOptional(const Value &OptionalVal, const Environment &Env) {
372
372
return HasValueVal != nullptr && Env.flowConditionImplies (*HasValueVal);
373
373
}
374
374
375
+ StorageLocation *maybeSkipPointer (StorageLocation *Loc,
376
+ const Environment &Env) {
377
+ if (Loc == nullptr )
378
+ return nullptr ;
379
+ if (auto *Val = dyn_cast_or_null<PointerValue>(Env.getValue (*Loc)))
380
+ return &Val->getPointeeLoc ();
381
+ return Loc;
382
+ }
383
+
384
+ Value *getValueBehindPossiblePointer (const Expr &E, const Environment &Env) {
385
+ Value *Val = Env.getValue (E, SkipPast::Reference);
386
+ if (auto *PointerVal = dyn_cast_or_null<PointerValue>(Val))
387
+ return Env.getValue (PointerVal->getPointeeLoc ());
388
+ return Val;
389
+ }
390
+
375
391
void transferUnwrapCall (const Expr *UnwrapExpr, const Expr *ObjectExpr,
376
392
LatticeTransferState &State) {
377
393
if (auto *OptionalVal =
378
- State. Env . getValue (*ObjectExpr, SkipPast::ReferenceThenPointer )) {
394
+ getValueBehindPossiblePointer (*ObjectExpr, State. Env )) {
379
395
if (State.Env .getStorageLocation (*UnwrapExpr, SkipPast::None) == nullptr )
380
396
if (auto *Loc = maybeInitializeOptionalValueMember (
381
397
UnwrapExpr->getType (), *OptionalVal, State.Env ))
@@ -396,8 +412,8 @@ void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr,
396
412
const MatchFinder::MatchResult &,
397
413
LatticeTransferState &State) {
398
414
if (auto *HasValueVal = getHasValue (
399
- State.Env , State. Env . getValue (*CallExpr-> getImplicitObjectArgument (),
400
- SkipPast::ReferenceThenPointer ))) {
415
+ State.Env , getValueBehindPossiblePointer (
416
+ *CallExpr-> getImplicitObjectArgument (), State. Env ))) {
401
417
auto &CallExprLoc = State.Env .createStorageLocation (*CallExpr);
402
418
State.Env .setValue (CallExprLoc, *HasValueVal);
403
419
State.Env .setStorageLocation (*CallExpr, CallExprLoc);
@@ -419,8 +435,7 @@ void transferValueOrImpl(const clang::Expr *ValueOrPredExpr,
419
435
->getImplicitObjectArgument ();
420
436
421
437
auto *HasValueVal = getHasValue (
422
- State.Env ,
423
- State.Env .getValue (*ObjectArgumentExpr, SkipPast::ReferenceThenPointer));
438
+ State.Env , getValueBehindPossiblePointer (*ObjectArgumentExpr, State.Env ));
424
439
if (HasValueVal == nullptr )
425
440
return ;
426
441
@@ -472,8 +487,8 @@ void transferCallReturningOptional(const CallExpr *E,
472
487
473
488
void assignOptionalValue (const Expr &E, Environment &Env,
474
489
BoolValue &HasValueVal) {
475
- if (auto *OptionalLoc =
476
- Env.getStorageLocation (E, SkipPast::ReferenceThenPointer )) {
490
+ if (auto *OptionalLoc = maybeSkipPointer (
491
+ Env.getStorageLocation (E, SkipPast::Reference), Env )) {
477
492
Env.setValue (*OptionalLoc, createOptionalValue (Env, HasValueVal));
478
493
}
479
494
}
@@ -550,13 +565,11 @@ void transferNulloptAssignment(const CXXOperatorCallExpr *E,
550
565
transferAssignment (E, State.Env .getBoolLiteralValue (false ), State);
551
566
}
552
567
553
- void transferSwap (const Expr & E1 , SkipPast E1Skip, const Expr & E2 ,
568
+ void transferSwap (StorageLocation *Loc1, StorageLocation *Loc2 ,
554
569
Environment &Env) {
555
570
// We account for cases where one or both of the optionals are not modeled,
556
571
// either lacking associated storage locations, or lacking values associated
557
572
// to such storage locations.
558
- auto *Loc1 = Env.getStorageLocation (E1 , E1Skip);
559
- auto *Loc2 = Env.getStorageLocation (E2 , SkipPast::Reference);
560
573
561
574
if (Loc1 == nullptr ) {
562
575
if (Loc2 != nullptr )
@@ -590,14 +603,20 @@ void transferSwapCall(const CXXMemberCallExpr *E,
590
603
const MatchFinder::MatchResult &,
591
604
LatticeTransferState &State) {
592
605
assert (E->getNumArgs () == 1 );
593
- transferSwap (*E->getImplicitObjectArgument (), SkipPast::ReferenceThenPointer,
594
- *E->getArg (0 ), State.Env );
606
+ transferSwap (maybeSkipPointer (
607
+ State.Env .getStorageLocation (*E->getImplicitObjectArgument (),
608
+ SkipPast::Reference),
609
+ State.Env ),
610
+ State.Env .getStorageLocation (*E->getArg (0 ), SkipPast::Reference),
611
+ State.Env );
595
612
}
596
613
597
614
void transferStdSwapCall (const CallExpr *E, const MatchFinder::MatchResult &,
598
615
LatticeTransferState &State) {
599
616
assert (E->getNumArgs () == 2 );
600
- transferSwap (*E->getArg (0 ), SkipPast::Reference, *E->getArg (1 ), State.Env );
617
+ transferSwap (State.Env .getStorageLocation (*E->getArg (0 ), SkipPast::Reference),
618
+ State.Env .getStorageLocation (*E->getArg (1 ), SkipPast::Reference),
619
+ State.Env );
601
620
}
602
621
603
622
void transferStdForwardCall (const CallExpr *E, const MatchFinder::MatchResult &,
@@ -756,6 +775,17 @@ auto buildTransferMatchSwitch() {
756
775
})
757
776
758
777
// optional::operator*, optional::operator->
778
+ // FIXME: This does something slightly strange for `operator->`.
779
+ // `transferUnwrapCall()` may create a new value of type `T` for the
780
+ // `optional<T>`, and it associates that value with `E`. In the case of
781
+ // `operator->`, `E` is a pointer. As a result, we associate an
782
+ // expression of pointer type with a storage location of non-pointer type
783
+ // `T`. This can confound other code that expects expressions of
784
+ // pointer type to be associated with `PointerValue`s, such as the
785
+ // centrally provided accessors `getImplicitObjectLocation()` and
786
+ // `getBaseObjectLocation()`, and this is the reason we need to use our
787
+ // own 'maybeSkipPointer()` and `getValueBehindPossiblePointer()` instead
788
+ // of these accessors.
759
789
.CaseOfCFGStmt <CallExpr>(valueOperatorCall (std::nullopt),
760
790
[](const CallExpr *E,
761
791
const MatchFinder::MatchResult &,
@@ -837,8 +867,7 @@ auto buildTransferMatchSwitch() {
837
867
std::vector<SourceLocation> diagnoseUnwrapCall (const Expr *UnwrapExpr,
838
868
const Expr *ObjectExpr,
839
869
const Environment &Env) {
840
- if (auto *OptionalVal =
841
- Env.getValue (*ObjectExpr, SkipPast::ReferenceThenPointer)) {
870
+ if (auto *OptionalVal = getValueBehindPossiblePointer (*ObjectExpr, Env)) {
842
871
auto *Prop = OptionalVal->getProperty (" has_value" );
843
872
if (auto *HasValueVal = cast_or_null<BoolValue>(Prop)) {
844
873
if (Env.flowConditionImplies (*HasValueVal))
0 commit comments