Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
In UpdateClassInfoWithDecl, avoid lookup when not needed.
Also improve error recovery (don't assign/keep an invalid ClassInfo).
We avoid the lookup by doing it only when we have a class with an opaque typedef (Double32_t) ... except
that we don't know how to find them yet (at least not in a performant way).
  • Loading branch information
pcanal committed Sep 6, 2019
commit 89a85847123ed43de33abf241d4ef74af2db0ff3
80 changes: 51 additions & 29 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6465,9 +6465,52 @@ Bool_t TCling::IsAutoLoadNamespaceCandidate(const clang::NamespaceDecl* nsDecl)
return fNSFromRootmaps.count(nsDecl) != 0;
}


////////////////////////////////////////////////////////////////////////////////
/// Internal function. Inform a TClass about its new TagDecl or NamespaceDecl.
/// Internal function. Actually do the update of the ClassInfo when seeing
// new TagDecl or NamespaceDecl.
void TCling::RefreshClassInfo(TClass *cl, const clang::TagDecl *tdDef, bool alias) {

TClingClassInfo *cci = ((TClingClassInfo *)cl->fClassInfo);
if (cci) {
// If we only had a forward declaration then update the
// TClingClassInfo with the definition if we have it now.
const TagDecl *tdOld = llvm::dyn_cast_or_null<TagDecl>(cci->GetDecl());
if (!tdOld || (tdDef && tdDef != tdOld)) {
cl->ResetCaches();
TClass::RemoveClassDeclId(cci->GetDeclId());
if (tdDef) {
// It's a tag decl, not a namespace decl.
cci->Init(*cci->GetType());
TClass::AddClassToDeclIdMap(cci->GetDeclId(), cl);
}
}
} else if (!cl->TestBit(TClass::kLoading) && !cl->fHasRootPcmInfo) {
cl->ResetCaches();
// yes, this is almost a waste of time, but we do need to lookup
// the 'type' corresponding to the TClass anyway in order to
// preserve the opaque typedefs (Double32_t)
if (!alias)
cl->fClassInfo = (ClassInfo_t *)new TClingClassInfo(fInterpreter, tdDef);
else
cl->fClassInfo = (ClassInfo_t *)new TClingClassInfo(fInterpreter, cl->GetName());
if (((TClingClassInfo *)cl->fClassInfo)->IsValid()) {
// We now need to update the state and bits.
if (cl->fState != TClass::kHasTClassInit) {
// if (!cl->fClassInfo->IsValid()) cl->fState = TClass::kForwardDeclared; else
cl->fState = TClass::kInterpreted;
cl->ResetBit(TClass::kIsEmulation);
}
TClass::AddClassToDeclIdMap(((TClingClassInfo *)(cl->fClassInfo))->GetDeclId(), cl);
} else {
delete ((TClingClassInfo *)cl->fClassInfo);
cl->fClassInfo = nullptr;
}
}
}

////////////////////////////////////////////////////////////////////////////////
/// Internal function. Inform a TClass about its new TagDecl or NamespaceDecl.
void TCling::UpdateClassInfoWithDecl(const void* vTD)
{
const NamedDecl* ND = static_cast<const NamedDecl*>(vTD);
Expand Down Expand Up @@ -6503,6 +6546,8 @@ void TCling::UpdateClassInfoWithDecl(const void* vTD)
name = ND->getQualifiedNameAsString();
}



// Supposedly we are being called while something is being
// loaded ... let's now tell the autoloader to do the work
// yet another time.
Expand All @@ -6511,35 +6556,12 @@ void TCling::UpdateClassInfoWithDecl(const void* vTD)
// for example vector<double> and vector<Double32_t>
TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name.c_str());
if (cl && GetModTClasses().find(cl) == GetModTClasses().end()) {
TClingClassInfo* cci = ((TClingClassInfo*)cl->fClassInfo);
if (cci) {
// If we only had a forward declaration then update the
// TClingClassInfo with the definition if we have it now.
const TagDecl* tdOld = llvm::dyn_cast_or_null<TagDecl>(cci->GetDecl());
if (!tdOld || (tdDef && tdDef != tdOld)) {
cl->ResetCaches();
TClass::RemoveClassDeclId(cci->GetDeclId());
if (td) {
// It's a tag decl, not a namespace decl.
cci->Init(*cci->GetType());
TClass::AddClassToDeclIdMap(cci->GetDeclId(), cl);
}
}
} else if (!cl->TestBit(TClass::kLoading) && !cl->fHasRootPcmInfo) {
cl->ResetCaches();
// yes, this is almost a waste of time, but we do need to lookup
// the 'type' corresponding to the TClass anyway in order to
// preserve the opaque typedefs (Double32_t)
cl->fClassInfo = (ClassInfo_t *)new TClingClassInfo(fInterpreter, cl->GetName());
// We now need to update the state and bits.
if (cl->fState != TClass::kHasTClassInit) {
// if (!cl->fClassInfo->IsValid()) cl->fState = TClass::kForwardDeclared; else
cl->fState = TClass::kInterpreted;
cl->ResetBit(TClass::kIsEmulation);
}
TClass::AddClassToDeclIdMap(((TClingClassInfo*)(cl->fClassInfo))->GetDeclId(), cl);
}
RefreshClassInfo(cl, tdDef, false);
}
// And here we should find the other 'aliases' (eg. vector<Double32_t>)
// and update them too:
// foreach(aliascl in gROOT->GetListOfClasses()->FindAliasesOf(name.c_str()))
// RefreshClassInfo(cl, tdDef, true);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions core/metacling/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace clang {
class EnumDecl;
class FunctionDecl;
class NamespaceDecl;
class TagDecl;
class Type;
class QualType;
}
Expand Down Expand Up @@ -313,6 +314,7 @@ class TCling final : public TInterpreter {

static void UpdateClassInfo(char* name, Long_t tagnum);
static void UpdateClassInfoWork(const char* name);
void RefreshClassInfo(TClass *cl, const clang::TagDecl *td, bool alias);
void UpdateClassInfoWithDecl(const void* vTD);
static void UpdateAllCanvases();

Expand Down