@@ -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