@@ -608,6 +608,12 @@ class RegionStoreManager : public StoreManager {
608608 return getBinding (getRegionBindings (S), L, T);
609609 }
610610
611+ // / Returns the value of the default binding of region \p BaseR
612+ // / if and only if that is the unique binding in the cluster of \p BaseR.
613+ // / \p BaseR must be a base region.
614+ std::optional<SVal> getUniqueDefaultBinding (Store S,
615+ const MemRegion *BaseR) const ;
616+
611617 std::optional<SVal> getDefaultBinding (Store S, const MemRegion *R) override {
612618 RegionBindingsRef B = getRegionBindings (S);
613619 // Default bindings are always applied over a base region so look up the
@@ -2605,9 +2611,42 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
26052611 return NewB;
26062612}
26072613
2614+ std::optional<SVal>
2615+ RegionStoreManager::getUniqueDefaultBinding (Store S,
2616+ const MemRegion *BaseR) const {
2617+ assert (BaseR == BaseR->getBaseRegion () && " Expecting a base region" );
2618+ const auto *Cluster = getRegionBindings (S).lookup (BaseR);
2619+ if (!Cluster || !llvm::hasSingleElement (*Cluster))
2620+ return std::nullopt ;
2621+
2622+ const auto [Key, Value] = *Cluster->begin ();
2623+ return Key.isDirect () ? std::optional<SVal>{} : Value;
2624+ }
2625+
26082626std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct (
26092627 RegionBindingsConstRef B, const TypedValueRegion *R, const RecordDecl *RD,
26102628 nonloc::LazyCompoundVal LCV) {
2629+ // If we try to copy a Conjured value representing the value of the whole
2630+ // struct, don't try to element-wise copy each field.
2631+ // That would unnecessarily bind Derived symbols slicing off the subregion for
2632+ // the field from the whole Conjured symbol.
2633+ //
2634+ // struct Window { int width; int height; };
2635+ // Window getWindow(); <-- opaque fn.
2636+ // Window w = getWindow(); <-- conjures a new Window.
2637+ // Window w2 = w; <-- trivial copy "w", calling "tryBindSmallStruct"
2638+ //
2639+ // We should not end up with a new Store for "w2" like this:
2640+ // Direct [ 0..31]: Derived{Conj{}, w.width}
2641+ // Direct [32..63]: Derived{Conj{}, w.height}
2642+ // Instead, we should just bind that Conjured value instead.
2643+ if (LCV.getRegion ()->getBaseRegion () == LCV.getRegion ()) {
2644+ if (auto Val = getUniqueDefaultBinding (LCV.getStore (), LCV.getRegion ())) {
2645+ return B.addBinding (BindingKey::Make (R, BindingKey::Default),
2646+ Val.value ());
2647+ }
2648+ }
2649+
26112650 FieldVector Fields;
26122651
26132652 if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
0 commit comments