Skip to content

Commit 261f1a5

Browse files
committed
[core] avoid using VLA in TListOfTypes
The current code goes through different codepaths depending on the platform. One of the codepaths relies on a non-standard extension (variable-length arrays) and the other manually allocates and frees a char array. Using a std::string, while losing a bit of performance on Linux/Mac, simplifies and unifies the codepaths and avoids using non-standard C++ (which in turns enable building with -Werror). The perf hit is most likely negligible, especially given the use of dynamic_cast in the same block.
1 parent 34301dd commit 261f1a5

File tree

3 files changed

+15
-36
lines changed

3 files changed

+15
-36
lines changed

core/base/src/TListOfTypes.cxx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,19 @@ static bool NameExistsElsewhere(const char* name){
6363
// We have a scope
6464
const auto enName = lastPos + 1;
6565
const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)name) / sizeof(decltype(*lastPos)) - 1;
66-
#ifdef R__WIN32
67-
char *scopeName = new char[scopeNameSize + 1];
68-
#else
69-
char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
70-
#endif
71-
strncpy(scopeName, name, scopeNameSize);
72-
scopeName[scopeNameSize] = '\0';
66+
std::string scopeName{name, scopeNameSize};
7367
// We have now an enum name and a scope name
7468
// We look first in the classes
75-
if(auto scope = dynamic_cast<TClass*>(gROOT->GetListOfClasses()->FindObject(scopeName))){
69+
if (auto scope = dynamic_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName.c_str()))) {
7670
theEnum = ((TListOfEnums*)scope->GetListOfEnums(false))->THashList::FindObject(enName);
7771
}
7872
// And then if not found in the protoclasses
7973
if (!theEnum){
80-
if (auto scope = TClassTable::GetProtoNorm(scopeName)){
74+
if (auto scope = TClassTable::GetProtoNorm(scopeName.c_str())) {
8175
if (auto listOfEnums = (TListOfEnums*)scope->GetListOfEnums())
8276
theEnum = listOfEnums->THashList::FindObject(enName);
8377
}
8478
}
85-
#ifdef R__WIN32
86-
delete [] scopeName;
87-
#endif
8879
} else { // Here we look in the global scope
8980
theEnum = ((TListOfEnums*)gROOT->GetListOfEnums())->THashList::FindObject(name);
9081
}

core/meta/src/TEnum.cxx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -296,35 +296,25 @@ TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
296296

297297
if (lastPos != enumName) {
298298
// We have a scope
299-
// All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck)
300299
const auto enName = lastPos;
301300
const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
302-
#ifdef R__WIN32
303-
char *scopeName = new char[scopeNameSize + 1];
304-
#else
305-
char scopeName[scopeNameSize + 1]; // on the stack, +1 for the terminating character '\0'
306-
#endif
307-
strncpy(scopeName, enumName, scopeNameSize);
308-
scopeName[scopeNameSize] = '\0';
301+
std::string scopeName{enumName, scopeNameSize};
309302
// Three levels of search
310-
theEnum = searchEnum(scopeName, enName, kNone);
303+
theEnum = searchEnum(scopeName.c_str(), enName, kNone);
311304
if (!theEnum && (sa & kAutoload)) {
312-
const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
305+
const auto libsLoaded = gInterpreter->AutoLoad(scopeName.c_str());
313306
// It could be an enum in a scope which is not selected
314307
if (libsLoaded == 0){
315308
gInterpreter->AutoLoad(enumName);
316309
}
317-
theEnum = searchEnum(scopeName, enName, kAutoload);
310+
theEnum = searchEnum(scopeName.c_str(), enName, kAutoload);
318311
}
319312
if (!theEnum && (sa & kALoadAndInterpLookup)) {
320313
if (gDebug > 0) {
321314
printf("TEnum::GetEnum: Header Parsing - The enumerator %s is not known to the typesystem: an interpreter lookup will be performed. This can imply parsing of headers. This can be avoided selecting the numerator in the linkdef/selection file.\n", enumName);
322315
}
323-
theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
316+
theEnum = searchEnum(scopeName.c_str(), enName, kALoadAndInterpLookup);
324317
}
325-
#ifdef R__WIN32
326-
delete [] scopeName;
327-
#endif
328318
} else {
329319
// We don't have any scope: this is a global enum
330320
theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);

core/metacling/src/TCling.cxx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -960,26 +960,24 @@ bool TClingLookupHelper__ExistingTypeCheck(const std::string &tname,
960960
if (lastPos != inner) // Main switch: case 1 - scoped enum, case 2 global enum
961961
{
962962
// We have a scope
963-
// All of this C gymnastic is to avoid allocations on the heap
964963
const auto enName = lastPos;
965964
const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)inner) / sizeof(decltype(*lastPos)) - 2;
966-
char *scopeName = new char[scopeNameSize + 1];
967-
strncpy(scopeName, inner, scopeNameSize);
968-
scopeName[scopeNameSize] = '\0';
965+
std::string scopeName{inner, scopeNameSize};
969966
// Check if the scope is in the list of classes
970-
if (auto scope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
967+
if (auto scope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName.c_str()))) {
971968
auto enumTable = dynamic_cast<const THashList *>(scope->GetListOfEnums(false));
972-
if (enumTable && enumTable->THashList::FindObject(enName)) { delete [] scopeName; return true; }
969+
if (enumTable && enumTable->THashList::FindObject(enName))
970+
return true;
973971
}
974972
// It may still be in one of the loaded protoclasses
975-
else if (auto scope = static_cast<TProtoClass *>(gClassTable->GetProtoNorm(scopeName))) {
973+
else if (auto scope = static_cast<TProtoClass *>(gClassTable->GetProtoNorm(scopeName.c_str()))) {
976974
auto listOfEnums = scope->GetListOfEnums();
977975
if (listOfEnums) { // it could be null: no enumerators in the protoclass
978976
auto enumTable = dynamic_cast<const THashList *>(listOfEnums);
979-
if (enumTable && enumTable->THashList::FindObject(enName)) { delete [] scopeName; return true; }
977+
if (enumTable && enumTable->THashList::FindObject(enName))
978+
return true;
980979
}
981980
}
982-
delete [] scopeName;
983981
} else
984982
{
985983
// We don't have any scope: this could only be a global enum

0 commit comments

Comments
 (0)