diff --git a/core/base/inc/TMemberInspector.h b/core/base/inc/TMemberInspector.h index c47a8fdc32f33..b6e4979944a29 100644 --- a/core/base/inc/TMemberInspector.h +++ b/core/base/inc/TMemberInspector.h @@ -39,6 +39,7 @@ class TMemberInspector { class TParentBuf; TParentBuf* fParent; // current inspection "path" EObjectPointerState fObjectPointerState; // whether the address is valid or only an offset + UInt_t fNestedTransient; TMemberInspector(const TMemberInspector &) = delete; TMemberInspector &operator=(const TMemberInspector &) = delete; @@ -76,6 +77,10 @@ class TMemberInspector { void GenericShowMembers(const char *topClassName, const void *obj, Bool_t transientMember); + void DecrementNestedTransient() { --fNestedTransient; } + void IncrementNestedTransient() { ++fNestedTransient; } + bool IsNestedTransient() { return fNestedTransient != 0; } + ClassDef(TMemberInspector,0) //ABC for inspecting class data members }; diff --git a/core/base/src/TMemberInspector.cxx b/core/base/src/TMemberInspector.cxx index cbd70eb208f27..466298f904611 100644 --- a/core/base/src/TMemberInspector.cxx +++ b/core/base/src/TMemberInspector.cxx @@ -60,7 +60,7 @@ void TMemberInspector::TParentBuf::Remove(Ssiz_t startingAt) ClassImp(TMemberInspector); TMemberInspector::TMemberInspector(): - fObjectPointerState(kUnset) + fObjectPointerState(kUnset), fNestedTransient(0) { // Construct a member inspector diff --git a/core/meta/inc/TProtoClass.h b/core/meta/inc/TProtoClass.h index 45e2b437e7e3e..4aee2a489cad2 100644 --- a/core/meta/inc/TProtoClass.h +++ b/core/meta/inc/TProtoClass.h @@ -56,7 +56,7 @@ class TProtoClass: public TNamed { TProtoRealData() : fOffset(0), fDMIndex(-1), fLevel(0), fClassIndex(-1), fStatusFlag(0) {} TProtoRealData(const TRealData *rd); virtual ~TProtoRealData(); - TRealData *CreateRealData(TClass *currentClass, TClass *parent, TRealData * parentData, int prevLevel) const; + TRealData *CreateRealData(TClass *currentClass, TClass *parent, TRealData * parentData, int prevLevel, bool quiet) const; Bool_t TestFlag(UInt_t f) const { return (Bool_t) ((fStatusFlag & f) != 0); } void SetFlag(UInt_t f, Bool_t on = kTRUE) { @@ -91,7 +91,7 @@ class TProtoClass: public TNamed { // compute index of data member in the list static Int_t DataMemberIndex(TClass * cl, const char * name); // find data member given an index - static TDataMember * FindDataMember(TClass * cl, Int_t index); + static TDataMember * FindDataMember(TClass * cl, Int_t index, bool quiet); public: TProtoClass(): diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index 4ea5f8dcac0e8..a0da33404b9a9 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -824,6 +824,8 @@ void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, c TRealData::GetName(rdName,dm); rname += rdName; TRealData* rd = new TRealData(rname.Data(), offset, dm); + if (isTransientMember || IsNestedTransient()) + rd->SetBit(TRealData::kTransient); fRealDataClass->GetListOfRealData()->Add(rd); return; } @@ -833,12 +835,14 @@ void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, c if (dm->IsaPointer()) { // Data member is a pointer. TRealData* rd = new TRealData(rname, offset, dm); - if (isTransientMember) { rd->SetBit(TRealData::kTransient); }; + if (isTransientMember || IsNestedTransient()) + rd->SetBit(TRealData::kTransient); fRealDataClass->GetListOfRealData()->Add(rd); } else { // Data Member is a basic data type. TRealData* rd = new TRealData(rname, offset, dm); - if (isTransientMember) { rd->SetBit(TRealData::kTransient); }; + if (isTransientMember || IsNestedTransient()) + rd->SetBit(TRealData::kTransient); if (!dm->IsBasic()) { rd->SetIsObject(kTRUE); diff --git a/core/meta/src/TProtoClass.cxx b/core/meta/src/TProtoClass.cxx index 26674c1cedd79..1f96ee2957e70 100644 --- a/core/meta/src/TProtoClass.cxx +++ b/core/meta/src/TProtoClass.cxx @@ -378,7 +378,7 @@ Bool_t TProtoClass::FillTClass(TClass* cl) { //TProtoRealData* prd = (TProtoRealData*)element; // pass a previous real data only if depth - if (TRealData* rd = element.CreateRealData(currentRDClass, cl,prevRealData, prevLevel)) { + if (TRealData* rd = element.CreateRealData(currentRDClass, cl,prevRealData, prevLevel, element.TestFlag(TProtoRealData::kIsTransient))) { if (first) { //LM: need to do here because somehow fRealData is destroyed when calling TClass::GetListOfDataMembers() if (cl->fRealData) { @@ -461,15 +461,23 @@ TProtoClass::TProtoRealData::~TProtoRealData() } //////////////////////////////////////////////////////////////////////////////// -/// Create a TRealData from this, with its data member coming from dmClass. +/// \brief Create a TRealData from this, with its data member coming from dmClass. /// find data member from protoclass +/// +/// \return the created TRealData +/// +/// \param [in] dmClass Class where the data member is declared +/// \param [in] parent Parent class +/// \param [in] prevData the previous 'real' data member (might be part of another class) +/// \param [in] prevLevel nesting level +/// \param [in] quiet Whether we should not warn about missing information (usually set to true for transient members) TRealData* TProtoClass::TProtoRealData::CreateRealData(TClass* dmClass, - TClass* parent, TRealData *prevData, int prevLevel) const + TClass* parent, TRealData *prevData, int prevLevel, bool quiet) const { //TDataMember* dm = (TDataMember*)dmClass->GetListOfDataMembers()->FindObject(fName); - TDataMember* dm = TProtoClass::FindDataMember(dmClass, fDMIndex); + TDataMember* dm = TProtoClass::FindDataMember(dmClass, fDMIndex, quiet); if (!dm && dmClass->GetState()!=TClass::kForwardDeclared && !dmClass->fIsSyntheticPair) { ::Error("CreateRealData", @@ -557,8 +565,16 @@ Int_t TProtoClass::DataMemberIndex(TClass * cl, const char * name) return -1; } //////////////////////////////////////////////////////////////////////////////// - -TDataMember * TProtoClass::FindDataMember(TClass * cl, Int_t index) +//////////////////////////////////////////////////////////////////////////////// +/// \brief Find the requested TDataMember +/// +/// \return the requested TDataMember if found +/// +/// \param [in] cl TClass to search for the data member +/// \param [in] index Numerical index of the object's data member +/// \param [in] quiet Whether we should not warn about missing information (usually set to true for transient members) + +TDataMember * TProtoClass::FindDataMember(TClass * cl, Int_t index, bool quiet) { TList * dmList = cl->GetListOfDataMembers(false); @@ -572,7 +588,7 @@ TDataMember * TProtoClass::FindDataMember(TClass * cl, Int_t index) return dm; i++; } - if (cl->GetState()!=TClass::kForwardDeclared && !cl->fIsSyntheticPair) + if (cl->GetState()!=TClass::kForwardDeclared && !cl->fIsSyntheticPair && !quiet) ::Error("TProtoClass::FindDataMember","data member with index %d is not found in class %s",index,cl->GetName()); return nullptr; } diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 3fcc4e698d0c8..db93236d66740 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -2980,9 +2980,12 @@ void TCling::InspectMembers(TMemberInspector& insp, const void* obj, // if we can not find the member (which should not really happen), // let's consider it transient. Bool_t transient = isTransient || !mbr || !mbr->IsPersistent(); - + if (!mbr || !mbr->IsPersistent()) + insp.IncrementNestedTransient(); insp.InspectMember(sFieldRecName.c_str(), cobj + fieldOffset, (fieldName + '.').c_str(), transient); + if (!mbr || !mbr->IsPersistent()) + insp.DecrementNestedTransient(); } } @@ -6660,6 +6663,18 @@ void TCling::RefreshClassInfo(TClass *cl, const clang::NamedDecl *def, bool alia } } else if (!cl->TestBit(TClass::kLoading) && !cl->fHasRootPcmInfo) { cl->ResetCaches(); + if (strncmp(cl->GetName(),"tuple<",strlen("tuple<"))==0) { + // We need to use the Emulated Tuple but we should not trigger parsing + // yet, so delay the creation of the ClassInfo + delete ((TClingClassInfo *)cl->fClassInfo); + cl->fClassInfo = nullptr; + cl->fCanLoadClassInfo = true; + cl->RemoveStreamerInfo(cl->fClassVersion); + if (cl->fState != TClass::kHasTClassInit) { + cl->fState = TClass::kInterpreted; + } + return; + } // yes, this is almost a waste of time, but we do need to lookup // the 'type' corresponding to the TClass anyway in order to // preserve the opaque typedefs (Double32_t)