@@ -3133,8 +3133,7 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
3133
3133
3134
3134
// To avoid spurious auto parsing, let's check if the name as-is is
3135
3135
// known in the TClassTable.
3136
- DictFuncPtr_t dict = TClassTable::GetDictNorm (name);
3137
- if (dict) {
3136
+ if (DictFuncPtr_t dict = TClassTable::GetDictNorm (name)) {
3138
3137
// The name is normalized, so the result of the first search is
3139
3138
// authoritative.
3140
3139
if (!cl && !load)
@@ -3150,8 +3149,11 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
3150
3149
// continue as before ...
3151
3150
}
3152
3151
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.
3153
3155
std::string normalizedName;
3154
- Bool_t checkTable = kFALSE ;
3156
+ Bool_t nameChanged = kFALSE ;
3155
3157
3156
3158
if (!cl) {
3157
3159
{
@@ -3169,28 +3171,14 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
3169
3171
// we may pass here in case of a dummy class created by TVirtualStreamerInfo
3170
3172
load = kTRUE ;
3171
3173
}
3172
- checkTable = kTRUE ;
3174
+ nameChanged = kTRUE ;
3173
3175
}
3174
3176
} else {
3175
3177
normalizedName = cl->GetName (); // Use the fact that all TClass names are normalized.
3176
3178
}
3177
3179
3178
3180
if (!load)
3179
3181
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
- // }
3194
3182
3195
3183
// We want to avoid auto-parsing due to intentionally missing dictionary for std::pair.
3196
3184
// 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
3201
3189
const bool ispair = TClassEdit::IsStdPair (normalizedName) && !IsFromRootCling ();
3202
3190
const bool ispairbase = TClassEdit::IsStdPairBase (normalizedName) && !IsFromRootCling ();
3203
3191
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;
3223
3199
}
3224
- loadedcl = LoadClassDefault (normalizedName.c_str (),silent);
3225
3200
}
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
+ };
3243
3203
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;
3245
3247
}
3246
3248
}
3247
- if (loadedcl) return loadedcl;
3248
3249
3249
3250
// 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))
3252
3252
return loadedcl;
3253
3253
3254
3254
// We have not been able to find a loaded TClass, return the Emulated
0 commit comments