diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index ff250aae7ef5a..e8c1a16339d47 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -307,7 +307,7 @@ friend class TStreamerInfo; void SetClassSize(Int_t sizof) { fSizeof = sizof; } TVirtualStreamerInfo* DetermineCurrentStreamerInfo(); - void SetStreamerImpl(); + void SetStreamerImpl(Int_t streamerType); void SetRuntimeProperties(); diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index 671f1ff6916bd..817e6ce4d7a47 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -6168,14 +6168,21 @@ Long_t TClass::Property() const // Avoid asking about the class when it is still building if (TestBit(kLoading)) return fProperty; + if (fStreamerType != kDefault && !HasInterpreterInfo()) { + // We have no interpreter information but we already set the streamer type + // so we have already been here and have no new information, then let's + // give up. See the code at this end of this routine (else branch of the + // `if (HasInterpreterInfo()` for the path we took before. + return 0; + } + // When called via TMapFile (e.g. Update()) make sure that the dictionary // gets allocated on the heap and not in the mapped file. TMmallocDescTemp setreset; TClass *kl = const_cast(this); - kl->fStreamerType = TClass::kDefault; - kl->fStreamerImpl = &TClass::StreamerDefault; + Int_t streamerType = TClass::kDefault; if (InheritsFrom(TObject::Class())) { kl->SetBit(kIsTObject); @@ -6184,8 +6191,7 @@ Long_t TClass::Property() const Int_t delta = kl->GetBaseClassOffsetRecurse(TObject::Class()); if (delta==0) kl->SetBit(kStartWithTObject); - kl->fStreamerType = kTObject; - kl->fStreamerImpl = &TClass::StreamerTObject; + streamerType = kTObject; } if (HasInterpreterInfo()) { @@ -6197,33 +6203,30 @@ Long_t TClass::Property() const if (!const_cast(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) { kl->SetBit(kIsForeign); - kl->fStreamerType = kForeign; - kl->fStreamerImpl = &TClass::StreamerStreamerInfo; + streamerType = kForeign; - } else if ( kl->fStreamerType == TClass::kDefault ) { + } else if (streamerType == TClass::kDefault) { if (kl->fConvStreamerFunc) { - kl->fStreamerType = kInstrumented; - kl->fStreamerImpl = &TClass::ConvStreamerInstrumented; + streamerType = kInstrumented; } else if (kl->fStreamerFunc) { - kl->fStreamerType = kInstrumented; - kl->fStreamerImpl = &TClass::StreamerInstrumented; + streamerType = kInstrumented; } else { // We have an automatic streamer using the StreamerInfo .. no need to go through the // Streamer method function itself. - kl->fStreamerType = kInstrumented; - kl->fStreamerImpl = &TClass::StreamerStreamerInfo; + streamerType = kInstrumented; } } if (fStreamer) { - kl->fStreamerType = kExternal; - kl->fStreamerImpl = &TClass::StreamerExternal; + streamerType = kExternal; } if (const_cast(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) { kl->SetBit(kHasLocalHashMember); } + kl->SetStreamerImpl(streamerType); + if (GetClassInfo()) { // In the case where the TClass for one of ROOT's core class // (eg TClonesArray for map) is requested @@ -6238,15 +6241,16 @@ Long_t TClass::Property() const // and think all test bits have been properly set. kl->fProperty = gCling->ClassInfo_Property(fClassInfo); } + } else { if (fStreamer) { - kl->fStreamerType = kExternal; - kl->fStreamerImpl = &TClass::StreamerExternal; + streamerType = kExternal; } - kl->fStreamerType |= kEmulatedStreamer; - kl->SetStreamerImpl(); + streamerType |= kEmulatedStreamer; + + kl->SetStreamerImpl(streamerType); // fProperty was *not* set so that it can be forced to be recalculated // next time. return 0; @@ -6281,8 +6285,9 @@ void TClass::SetRuntimeProperties() /// Internal routine to set fStreamerImpl based on the value of /// fStreamerType. -void TClass::SetStreamerImpl() +void TClass::SetStreamerImpl(Int_t StreamerType) { + fStreamerType = StreamerType; switch (fStreamerType) { case kTObject: fStreamerImpl = &TClass::StreamerTObject; break; case kForeign: fStreamerImpl = &TClass::StreamerStreamerInfo; break; diff --git a/core/meta/src/TProtoClass.cxx b/core/meta/src/TProtoClass.cxx index 26674c1cedd79..1c53d2c73f256 100644 --- a/core/meta/src/TProtoClass.cxx +++ b/core/meta/src/TProtoClass.cxx @@ -304,7 +304,6 @@ Bool_t TProtoClass::FillTClass(TClass* cl) { cl->fCanSplit = fCanSplit; cl->fProperty = fProperty; cl->fClassProperty = fClassProperty; - cl->fStreamerType = fStreamerType; // Update pointers to TClass if (cl->fBase.load()) { @@ -405,7 +404,7 @@ Bool_t TProtoClass::FillTClass(TClass* cl) { cl->fRealData = new TList(); // FIXME: this should really become a THashList! } - cl->SetStreamerImpl(); + cl->SetStreamerImpl(fStreamerType); // set to zero in order not to delete when protoclass is deleted fBase = nullptr;