Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Do not generate TClass for pair of unknown type(s).
Except in the case where we know the type did exist at some point and thus is an enum (because
it was not then we would have information about in the form of TStreamerInfo).

The exception to the exception is the case of a custom Streamer that does not use TStreamerInfo
underneath.  In that case, we don't know about the class then we don't have access to the custom
Streamer and thus can't read the object.
  • Loading branch information
pcanal committed Sep 30, 2020
commit 9b1058ade5f5320f4d155b239aeb7d7fa53ec79a
2 changes: 1 addition & 1 deletion core/meta/src/TListOfEnums.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ TEnum *TListOfEnums::GetObject(const char *name) const
void TListOfEnums::UnmapObject(TObject *obj)
{
TEnum *e = dynamic_cast<TEnum *>(obj);
if (e) {
if (e && e->GetDeclId()) {
fIds->Remove((Long64_t)e->GetDeclId());
}
}
Expand Down
48 changes: 43 additions & 5 deletions io/io/src/TEmulatedCollectionProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ the class TEmulatedMapProxy.
#include "TStreamerInfo.h"
#include "TClassEdit.h"
#include "TError.h"
#include "TEnum.h"
#include "TROOT.h"
#include <iostream>

Expand Down Expand Up @@ -139,18 +140,55 @@ TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx(Bool_t silent)
constexpr size_t kSizeOfPtr = sizeof(void*);
return in + (kSizeOfPtr - in%kSizeOfPtr)%kSizeOfPtr;
};
struct GenerateTemporaryTEnum
{
TEnum *fTemporaryTEnum = nullptr;

GenerateTemporaryTEnum(UInt_t typecase, const std::string &enumname)
{
if (typecase == kIsEnum && !TEnum::GetEnum(enumname.c_str())) {
fTemporaryTEnum = new TEnum();
fTemporaryTEnum->SetName(enumname.c_str());
gROOT->GetListOfEnums()->Add(fTemporaryTEnum);
}
}

~GenerateTemporaryTEnum()
{
if (fTemporaryTEnum) {
gROOT->GetListOfEnums()->Remove(fTemporaryTEnum);
delete fTemporaryTEnum;
}
}
};
switch ( fSTL_type ) {
case ROOT::kSTLmap:
case ROOT::kSTLmultimap:
nam = "pair<"+inside[1]+","+inside[2];
nam += (nam[nam.length()-1]=='>') ? " >" : ">";
if (0==TClass::GetClass(nam.c_str())) {
// We need to emulate the pair
R__GenerateTClassForPair(inside[1],inside[2]);
}
fValue = new Value(nam,silent);
fKey = new Value(inside[1],silent);
fVal = new Value(inside[2],silent);
{
// We have the case of an on-file enum or an unknown class, since
// this comes from a file, we also know that the type was valid but
// since we have no information it was either
// a. an enum
// b. a class of type that was never stored
// c. a class with a custom streamer
// We can "safely" pretend that it is an enum in all 3 case because
// a. obviously
// b. it will not be used anyway (no object of that type on the file)
// c. since we don't know the class we don't have the Streamer and thus can read it anyway
// So let's temporarily pretend it is an enum.
GenerateTemporaryTEnum keyEnum(fKey->fCase, inside[1]);
GenerateTemporaryTEnum valueEnum(fVal->fCase, inside[2]);

if (0==TClass::GetClass(nam.c_str())) {
// We need to emulate the pair
R__GenerateTClassForPair(inside[1],inside[2]);
}
}
fValue = new Value(nam,silent);
if ( !(*fValue).IsValid() || !fKey->IsValid() || !fVal->IsValid() ) {
return 0;
}
Expand Down
10 changes: 8 additions & 2 deletions io/io/src/TStreamerInfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ element type.
#include "TArrayS.h"
#include "TArrayL.h"
#include "TError.h"
#include "TEnum.h"
#include "TRef.h"
#include "TProcessID.h"
#include "TSystem.h"
Expand Down Expand Up @@ -5585,10 +5586,15 @@ static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const std:
}
TClass *clm = TClass::GetClass(dmType);
if (!clm) {
if (TEnum::GetEnum(dmType, TEnum::kNone)) {
Int_t dtype = kInt_t;
return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull.c_str());
}
return nullptr;
// either we have an Emulated enum or a really unknown class!
// let's just claim its an enum :(
Int_t dtype = kInt_t;
return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull.c_str());
//Int_t dtype = kInt_t;
//return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull.c_str());
}
// a pointer to a class
if ( dmIsPtr ) {
Expand Down