Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 8 additions & 2 deletions core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,20 @@ class TInterpreter : public TNamed {
virtual void UpdateListOfGlobals() = 0;
virtual void UpdateListOfGlobalFunctions() = 0;
virtual void UpdateListOfTypes() = 0;
virtual void SetClassInfo(TClass *cl, Bool_t reload = kFALSE, Bool_t silent = kFALSE) = 0;
virtual void SetClassInfo(TClass *cl,
Bool_t reload = kFALSE,
Bool_t silent = kFALSE,
ClassInfo_t *classInfo = nullptr) = 0;

enum ECheckClassInfo {
kUnknown = 0, // backward compatible with false
kKnown = 1,
kWithClassDefInline = 2
};
virtual ECheckClassInfo CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamespaceOnly = kFALSE) = 0;
virtual ECheckClassInfo CheckClassInfo(const char *name,
Bool_t autoload,
Bool_t isClassOrNamespaceOnly = kFALSE,
ClassInfo_t **classInfo = nullptr) = 0;

virtual Bool_t CheckClassTemplate(const char *name) = 0;
virtual Longptr_t Calc(const char *line, EErrorCode* error = nullptr) = 0;
Expand Down
9 changes: 7 additions & 2 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1483,8 +1483,13 @@ void TClass::Init(const char *name, Version_t cversion,
if (proto)
proto->FillTClass(this);
}
if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE)) {
gInterpreter->SetClassInfo(this, kFALSE, silent); // sets fClassInfo pointer
ClassInfo_t *checkedInfo = nullptr;
if (!fHasRootPcmInfo &&
gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE, /* isClassOrNamespaceOnly = */ kFALSE,
/* classInfo = */ &checkedInfo)) {
// Pass along the class info that CheckClassInfo may have found, so that
// SetClassInfo (which takes its ownership) does not repeat the lookup.
gInterpreter->SetClassInfo(this, kFALSE, silent, checkedInfo); // sets fClassInfo pointer
if (fClassInfo) {
// This should be moved out of GetCheckSum itself however the last time
// we tried this cause problem, in particular in the end-of-process operation.
Expand Down
57 changes: 47 additions & 10 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4205,9 +4205,20 @@ static std::string AlternateTuple(const char *classname, const cling::LookupHelp
/// Set pointer to the TClingClassInfo in TClass.
/// If 'reload' is true, (attempt to) generate a new ClassInfo even if we
/// already have one.
/// If 'classInfo' is non-null, take ownership of it and use it instead of
/// looking up the class again; it must have been obtained from a call to
/// CheckClassInfo(cl->GetName(), ...).

void TCling::SetClassInfo(TClass* cl, Bool_t reload, Bool_t silent)
void TCling::SetClassInfo(TClass *cl, Bool_t reload, Bool_t silent, ClassInfo_t *classInfo)
{
// Whether we use it below or not, we own the passed class info.
std::unique_ptr<TClingClassInfo> providedInfo{(TClingClassInfo *)classInfo};

// A provided class info is a cached lookup result; honoring it would defeat
// the point of a reload, which is to redo the lookup.
if (reload)
providedInfo.reset();

// We are shutting down, there is no point in reloading, it only triggers
// redundant deserializations.
if (fIsShuttingDown) {
Expand Down Expand Up @@ -4252,6 +4263,9 @@ void TCling::SetClassInfo(TClass* cl, Bool_t reload, Bool_t silent)
// details and just overlay a 'simpler'/'simplistic' version that is easy
// for the I/O to understand and handle.
if (strncmp(cl->GetName(),"tuple<",std::char_traits<char>::length("tuple<"))==0) {
// A provided class info would describe the real std::tuple, not the
// alternate version overlaid below: it cannot be used.
providedInfo.reset();
if (!reload)
name = AlternateTuple(cl->GetName(), fInterpreter->getLookupHelper(), silent);
if (reload || name.empty()) {
Expand All @@ -4266,7 +4280,8 @@ void TCling::SetClassInfo(TClass* cl, Bool_t reload, Bool_t silent)
// that is currently in the caller (like SetUnloaded) that disable AutoLoading and AutoParsing and
// code is in the callee (disabling template instantiation) and end up with a more explicit class:
// TClingClassInfoReadOnly.
TClingClassInfo* info = new TClingClassInfo(GetInterpreterImpl(), name.c_str(), instantiateTemplate);
TClingClassInfo *info = providedInfo ? providedInfo.release()
: new TClingClassInfo(GetInterpreterImpl(), name.c_str(), instantiateTemplate);
if (!info->IsValid()) {
SetWithoutClassInfoState(cl);
delete info;
Expand Down Expand Up @@ -4340,11 +4355,20 @@ void TCling::SetClassInfo(TClass* cl, Bool_t reload, Bool_t silent)
/// specifically check that each level of nesting is already loaded.
/// In case of templates the idea is that everything between the outer
/// '<' and '>' has to be skipped, e.g.: `aap<pippo<noot>::klaas>::a_class`
///
/// If 'classInfo' is non-null and the lookup found a declaration (which
/// findScope only returns if it points to a complete definition, i.e. when no
/// template instantiation would be needed to create it), '*classInfo' is set
/// to a newly allocated TClingClassInfo for that declaration, owned by the
/// caller. Passing it to SetClassInfo() avoids repeating the lookup there.

TInterpreter::ECheckClassInfo
TCling::CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamespaceOnly /* = kFALSE*/)
TInterpreter::ECheckClassInfo TCling::CheckClassInfo(const char *name, Bool_t autoload,
Bool_t isClassOrNamespaceOnly /* = kFALSE*/,
ClassInfo_t **classInfo /* = nullptr*/)
{
R__LOCKGUARD(gInterpreterMutex);
if (classInfo)
*classInfo = nullptr;
static const char *anonEnum = "anonymous enum ";
static const int cmplen = strlen(anonEnum);

Expand Down Expand Up @@ -4416,13 +4440,24 @@ TCling::CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamesp
: cling::LookupHelper::NoDiagnostics,
&type, /* intantiateTemplate= */ false );
if (!decl) {
// Use a separate output type for the retry: findScope does not write it
// on every path (e.g. when finding a namespace), and the type left over
// from the lookup above must not be paired with this lookup's decl.
const clang::Type *typeFromStd = nullptr;
std::string buf = TClassEdit::InsertStd(classname);
decl = lh.findScope(buf,
gDebug > 5 ? cling::LookupHelper::WithDiagnostics
: cling::LookupHelper::NoDiagnostics,
&type,false);
decl = lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics : cling::LookupHelper::NoDiagnostics,
&typeFromStd, false);
if (decl || typeFromStd)
type = typeFromStd;
}

// If requested and an entity was found by the lookup above, hand a class
// info for it out to the caller (see the function documentation).
auto provideClassInfo = [this, classInfo, &decl, &type] {
if (classInfo && decl && !decl->isInvalidDecl())
*classInfo = (ClassInfo_t *)new TClingClassInfo(GetInterpreterImpl(), decl, type);
};

if (type) {
// If decl==0 and the type is valid, then we have a forward declaration.
if (!decl) {
Expand Down Expand Up @@ -4477,6 +4512,7 @@ TCling::CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamesp
// , hasClassDefInline);

// We are now sure that the entry is not in fact an autoload entry.
provideClassInfo();
if (hasClassDefInline)
return kWithClassDefInline;
else
Expand All @@ -4487,9 +4523,10 @@ TCling::CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamesp
}
}

if (decl)
if (decl) {
provideClassInfo();
return kKnown;
else
} else
return kUnknown;

// Setting up iterator part of TClingTypedefInfo is too slow.
Expand Down
12 changes: 9 additions & 3 deletions core/metacling/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,15 @@ class TCling final : public TInterpreter {
void UpdateListOfGlobals() final;
void UpdateListOfGlobalFunctions() final;
void UpdateListOfTypes() final;
void SetClassInfo(TClass* cl, Bool_t reload = kFALSE, Bool_t silent = kFALSE) final;

ECheckClassInfo CheckClassInfo(const char *name, Bool_t autoload, Bool_t isClassOrNamespaceOnly = kFALSE) final;
void SetClassInfo(TClass *cl,
Bool_t reload = kFALSE,
Bool_t silent = kFALSE,
ClassInfo_t *classInfo = nullptr) final;

ECheckClassInfo CheckClassInfo(const char *name,
Bool_t autoload,
Bool_t isClassOrNamespaceOnly = kFALSE,
ClassInfo_t **classInfo = nullptr) final;

Bool_t CheckClassTemplate(const char *name) final;
Longptr_t Calc(const char* line, EErrorCode* error = nullptr) final;
Expand Down
15 changes: 11 additions & 4 deletions core/metacling/src/TClingClassInfo.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,19 @@ TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
Init(tag);
}

TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
const Decl *D)
: TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
fIsIter(false), fOffsetCache(0)
TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const Decl *D, const Type *T)
: TClingDeclInfo(nullptr),
fInterp(interp),
fFirstTime(true),
fDescend(false),
fIterAll(kTRUE),
fIsIter(false),
fOffsetCache(0)
{
Init(D);
// The type as found by the lookup, conserving typedefs like Double32_t
// (may be null).
fType = T;
}

void TClingClassInfo::AddBaseOffsetValue(const clang::Decl* decl, ptrdiff_t offset)
Expand Down
2 changes: 1 addition & 1 deletion core/metacling/src/TClingClassInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class TClingClassInfo final : public TClingDeclInfo {
explicit TClingClassInfo(cling::Interpreter *, Bool_t all = kTRUE);
explicit TClingClassInfo(cling::Interpreter *, const char *classname, bool intantiateTemplate = kTRUE);
explicit TClingClassInfo(cling::Interpreter *interp, const clang::Type &tag);
explicit TClingClassInfo(cling::Interpreter *interp, const clang::Decl *D);
explicit TClingClassInfo(cling::Interpreter *interp, const clang::Decl *D, const clang::Type *T = nullptr);
TClingClassInfo &operator=(const TClingClassInfo &rhs)
{
// Copy all but the mutex
Expand Down
Loading