Skip to content

Commit 760ff54

Browse files
committed
meta: simplify and clarify the TClass::GetClass flow
1 parent abde073 commit 760ff54

File tree

1 file changed

+59
-59
lines changed

1 file changed

+59
-59
lines changed

Diff for: core/meta/src/TClass.cxx

+59-59
Original file line numberDiff line numberDiff line change
@@ -3133,8 +3133,7 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
31333133

31343134
// To avoid spurious auto parsing, let's check if the name as-is is
31353135
// known in the TClassTable.
3136-
DictFuncPtr_t dict = TClassTable::GetDictNorm(name);
3137-
if (dict) {
3136+
if (DictFuncPtr_t dict = TClassTable::GetDictNorm(name)) {
31383137
// The name is normalized, so the result of the first search is
31393138
// authoritative.
31403139
if (!cl && !load)
@@ -3150,8 +3149,11 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
31503149
// continue as before ...
31513150
}
31523151

3152+
// Note: this variable does not always holds the fully normalized name
3153+
// as there is information from a not yet loaded library or from header
3154+
// not yet parsed that may be needed to fully normalize the name.
31533155
std::string normalizedName;
3154-
Bool_t checkTable = kFALSE;
3156+
Bool_t nameChanged = kFALSE;
31553157

31563158
if (!cl) {
31573159
{
@@ -3169,28 +3171,14 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
31693171
//we may pass here in case of a dummy class created by TVirtualStreamerInfo
31703172
load = kTRUE;
31713173
}
3172-
checkTable = kTRUE;
3174+
nameChanged = kTRUE;
31733175
}
31743176
} else {
31753177
normalizedName = cl->GetName(); // Use the fact that all TClass names are normalized.
31763178
}
31773179

31783180
if (!load)
31793181
return nullptr;
3180-
// This assertion currently fails because of
3181-
// TClass *c1 = TClass::GetClass("basic_iostream<char,char_traits<char> >");
3182-
// TClass *c2 = TClass::GetClass("std::iostream");
3183-
// where the TClassEdit normalized name of iostream is basic_iostream<char>
3184-
// i.e missing the addition of the default parameter. This is because TClingLookupHelper
3185-
// uses only 'part' of TMetaUtils::GetNormalizedName.
3186-
3187-
// if (!cl) {
3188-
// TDataType* dataType = (TDataType*)gROOT->GetListOfTypes()->FindObject(name);
3189-
// TClass *altcl = dataType ? (TClass*)gROOT->GetListOfClasses()->FindObject(dataType->GetFullTypeName()) : 0;
3190-
// if (altcl && normalizedName != altcl->GetName())
3191-
// ::Fatal("TClass::GetClass","The existing name (%s) for %s is different from the normalized name: %s\n",
3192-
// altcl->GetName(), name, normalizedName.c_str());
3193-
// }
31943182

31953183
// We want to avoid auto-parsing due to intentionally missing dictionary for std::pair.
31963184
// However, we don't need this special treatement in rootcling (there is no auto-parsing)
@@ -3201,54 +3189,66 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
32013189
const bool ispair = TClassEdit::IsStdPair(normalizedName) && !IsFromRootCling();
32023190
const bool ispairbase = TClassEdit::IsStdPairBase(normalizedName) && !IsFromRootCling();
32033191

3204-
TClass *loadedcl = nullptr;
3205-
if (checkTable) {
3206-
loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
3207-
} else {
3208-
if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
3209-
// Check if we just loaded the necessary dictionary.
3210-
loadedcl = LoadClassDefault(normalizedName.c_str(), silent);
3211-
if (loadedcl)
3212-
return loadedcl;
3213-
// At this point more information has been loaded. This
3214-
// information might be pertinent to the normalization of the name.
3215-
// For example it might contain or be a typedef for which we don't
3216-
// have a forward declaration (eg. typedef to instance of class
3217-
// template with default parameters). So let's redo the normalization
3218-
// as the new information (eg. typedef in TROOT::GetListOfTypes) might
3219-
// lead to a different value.
3220-
{
3221-
TInterpreter::SuspendAutoLoadingRAII autoloadOff(gInterpreter);
3222-
TClassEdit::GetNormalizedName(normalizedName, name);
3192+
auto loadClass = [](const char *requestedname) -> TClass* {
3193+
DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
3194+
if (dict) {
3195+
TClass *loadedcl = (dict)();
3196+
if (loadedcl) {
3197+
loadedcl->PostLoadCheck();
3198+
return loadedcl;
32233199
}
3224-
loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
32253200
}
3226-
auto e = TEnum::GetEnum(normalizedName.c_str(), TEnum::kNone);
3227-
if (e)
3228-
return nullptr;
3229-
// Maybe this was a typedef: let's try to see if this is the case
3230-
if (!loadedcl && !ispair && !ispairbase) {
3231-
if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3232-
// We have a typedef: we get the name of the underlying type
3233-
auto underlyingTypeName = theDataType->GetTypeName();
3234-
// We see if we can bootstrap a class with it
3235-
auto underlyingTypeDict = TClassTable::GetDictNorm(underlyingTypeName.Data());
3236-
if (underlyingTypeDict){
3237-
loadedcl = underlyingTypeDict();
3238-
if (loadedcl) {
3239-
loadedcl->PostLoadCheck();
3240-
return loadedcl;
3241-
}
3242-
}
3201+
return nullptr;
3202+
};
32433203

3244-
}
3204+
// Check with the changed name first.
3205+
if (nameChanged) {
3206+
if(TClass *loadedcl = loadClass(normalizedName.c_str()))
3207+
return loadedcl;
3208+
}
3209+
if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
3210+
// Check if we just loaded the necessary dictionary.
3211+
if (TClass *loadedcl = loadClass(normalizedName.c_str()))
3212+
return loadedcl;
3213+
3214+
// At this point more information has been loaded. This
3215+
// information might be pertinent to the normalization of the name.
3216+
// For example it might contain or be a typedef for which we don't
3217+
// have a forward declaration (eg. typedef to instance of class
3218+
// template with default parameters). So let's redo the normalization
3219+
// as the new information (eg. typedef in TROOT::GetListOfTypes) might
3220+
// lead to a different value.
3221+
{
3222+
TInterpreter::SuspendAutoLoadingRAII autoloadOff(gInterpreter);
3223+
std::string normalizedNameAfterAutoLoad;
3224+
TClassEdit::GetNormalizedName(normalizedNameAfterAutoLoad, name);
3225+
nameChanged = normalizedNameAfterAutoLoad != normalizedName;
3226+
normalizedName = normalizedNameAfterAutoLoad;
3227+
}
3228+
if (nameChanged) {
3229+
// Try to load with an attempt to autoload with the new name
3230+
if (TClass *loadedcl = LoadClassDefault(normalizedName.c_str(), silent))
3231+
return loadedcl;
3232+
}
3233+
}
3234+
3235+
// If name is known to be an enum, we don't need to try to load it.
3236+
if (TEnum::GetEnum(normalizedName.c_str(), TEnum::kNone))
3237+
return nullptr;
3238+
3239+
// Maybe this was a typedef: let's try to see if this is the case
3240+
if (!ispair && !ispairbase) {
3241+
if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3242+
// We have a typedef: we get the name of the underlying type
3243+
auto underlyingTypeName = theDataType->GetTypeName();
3244+
// We see if we can bootstrap a class with it
3245+
if (TClass *loadedcl = LoadClassDefault(underlyingTypeName, silent))
3246+
return loadedcl;
32453247
}
32463248
}
3247-
if (loadedcl) return loadedcl;
32483249

32493250
// See if the TClassGenerator can produce the TClass we need.
3250-
loadedcl = LoadClassCustom(normalizedName.c_str(),silent);
3251-
if (loadedcl)
3251+
if (TClass *loadedcl = LoadClassCustom(normalizedName.c_str(), silent))
32523252
return loadedcl;
32533253

32543254
// We have not been able to find a loaded TClass, return the Emulated

0 commit comments

Comments
 (0)