Skip to content

meta: Allow global disabling of AutoParsing during TClass::GetClass #18402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion cmake/modules/RootMacros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function(REFLEX_GENERATE_DICTIONARY dictionary)
OUTPUT ${gensrcdict} ${rootmapname}
COMMAND ${ROOT_genreflex_CMD}
ARGS ${headerfiles} -o ${gensrcdict} ${rootmapopts} --select=${selectionfile}
--gccxmlpath=${GCCXML_home}/bin ${ARG_OPTIONS}
${ARG_OPTIONS}
"-I$<JOIN:$<REMOVE_DUPLICATES:$<FILTER:${include_dirs},EXCLUDE,^$>>,;-I>"
"$<$<BOOL:$<JOIN:${definitions},>>:-D$<JOIN:${definitions},;-D>>"
DEPENDS ${headerfiles} ${selectionfile} ${ARG_DEPENDS}
Expand Down
8 changes: 8 additions & 0 deletions config/rootrc.in
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,11 @@ Rint.Canvas.HighLightColor: 5
# 1 All Branches (default)
# Can be overridden by the environment variable ROOT_TTREECACHE_PREFILL
# TTreeCache.Prefill: 1

# Advanced Debug Settings
# Setting Root.TClass.GetClass.AutoParsing to false
# will disable any auto-parsing execution of `TClass::GetClass`. This will
# result in not being able to find TClass-es when the name requires not-already
# loaded interpreted information (eg. a typedef to be resolved).
#
# Root.TClass.GetClass.AutoParsing: true
3 changes: 3 additions & 0 deletions core/base/src/TROOT.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,9 @@ Int_t TROOT::LoadClass(const char * /*classname*/, const char *libname,
// TSystem::Load returns 1 when the library was already loaded, return success in this case.
if (err == 1)
err = 0;
if (err == 0)
// Register the Autoloading of the library
gCling->RegisterAutoLoadedLibrary(libname);
return err;
}
} else {
Expand Down
1 change: 1 addition & 0 deletions core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ class TInterpreter : public TNamed {
virtual void AddAvailableIndentifiers(TSeqCollection&) = 0;
virtual void RegisterTClassUpdate(TClass *oldcl,DictFuncPtr_t dict) = 0;
virtual void UnRegisterTClassUpdate(const TClass *oldcl) = 0;
virtual void RegisterAutoLoadedLibrary(const char *libname) = 0;
virtual Int_t SetClassSharedLibs(const char *cls, const char *libs) = 0;
virtual void SetGetline(const char*(*getlineFunc)(const char* prompt),
void (*histaddFunc)(const char* line)) = 0;
Expand Down
12 changes: 12 additions & 0 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ In order to access the name of a class within the ROOT type system, the method T
#include "TDataType.h"
#include "TDatime.h"
#include "TEnum.h"
#include "TEnv.h"
#include "TError.h"
#include "TExMap.h"
#include "TFunctionTemplate.h"
Expand Down Expand Up @@ -3153,6 +3154,17 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hi
// continue as before ...
}

bool disableAutoParsing = gInterpreter->IsAutoParsingSuspended();
// FIXME: We need to decided on the interface to disable auto-parsing only during TClass::GetClass.
#ifdef ROOT_DISABLE_TCLASS_GET_CLASS_AUTOPARSING
constexpr bool requestDisableAutoLoading = true;
#else
static const bool requestDisableAutoLoading = !gEnv->GetValue("Root.TClass.GetClass.AutoParsing", true);
#endif
if (requestDisableAutoLoading)
disableAutoParsing = true;
TInterpreter::SuspendAutoParsing autoparseFence(gInterpreter, disableAutoParsing);

// Note: this variable does not always holds the fully normalized name
// as there is information from a not yet loaded library or from header
// not yet parsed that may be needed to fully normalize the name.
Expand Down
43 changes: 43 additions & 0 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2662,6 +2662,34 @@ void TCling::PrintIntro()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Print information about the interpreter.
///\param[in] option Selects the type of information to print.
///
/// List of currently support options:
/// - autoparsed: Print the list of classes that triggered autoparsing.
void TCling::Print(Option_t *option) const
{
if (option && *option) {
if (!strcmp(option, "autoparsed")) {
std::cout << "Auto parsed classes:" << std::endl;
for (auto & cls : fAutoParseClasses) {
std::cout << " " << cls << std::endl;
}
} else if (!strcmp(option, "autoloaded")) {
std::cout << "Auto loaded libraries:" << std::endl;
for (auto & lib : fAutoLoadedLibraries) {
std::cout << " " << lib << std::endl;
}
} else {
::Error("TCling::Print", "Unknown option '%s'", option);
}
} else {
::Info("TCling::Print", "No options specified");
}
}


////////////////////////////////////////////////////////////////////////////////
/// \brief Add a directory to the list of directories in which the
/// interpreter looks for include files.
Expand Down Expand Up @@ -3432,6 +3460,14 @@ static bool StartsWithStrLit(const char *haystack, const char (&needle)[N]) {
}
}

////////////////////////////////////////////////////////////////////////////////
/// Register that a library was autoloaded either to provide a 'missing' symbol
/// or to provide a class (see TClass::GetClass and TROOT::LoadClass).
void TCling::RegisterAutoLoadedLibrary(const char *libname)
{
fAutoLoadedLibraries.insert(libname);
}

////////////////////////////////////////////////////////////////////////////////
/// Register a new shared library name with the interpreter; add it to
/// fSharedLibs.
Expand Down Expand Up @@ -6536,6 +6572,12 @@ UInt_t TCling::AutoParseImplRecurse(const char *cls, bool topLevel)
}
}

if (nHheadersParsed) {
// Register that we did autoparsing for this class.
fAutoParseClasses.insert(cls);
if (gDebug)
Info("AutoParse", "Parsed %d headers for %s", nHheadersParsed, cls);
}
return nHheadersParsed;

}
Expand Down Expand Up @@ -6642,6 +6684,7 @@ void* TCling::LazyFunctionCreatorAutoload(const std::string& mangled_name) {
if (!LibLoader(libName))
return nullptr;

fAutoLoadedLibraries.insert(libName);
return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(dlsym_mangled_name);
}

Expand Down
6 changes: 6 additions & 0 deletions core/metacling/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class TCling final : public TInterpreter {
std::set<size_t> fLookedUpClasses; // Set of classes for which headers were looked up already
std::set<size_t> fPayloads; // Set of payloads
std::set<const char*> fParsedPayloadsAddresses; // Set of payloads which were parsed
std::set<std::string> fAutoParseClasses; // Set of classes for which we autoparsed a header
std::set<std::string> fAutoLoadedLibraries; // Set of libraries that were autoloaded
std::hash<std::string> fStringHashFunction; // A simple hashing function
std::unordered_set<const clang::NamespaceDecl*> fNSFromRootmaps; // Collection of namespaces fwd declared in the rootmaps
TObjArray* fRootmapFiles; // Loaded rootmap files.
Expand Down Expand Up @@ -200,6 +202,7 @@ class TCling final : public TInterpreter {
Int_t AutoLoad(const char *classname, Bool_t knowDictNotLoaded = kFALSE) final;
Int_t AutoLoad(const std::type_info& typeinfo, Bool_t knowDictNotLoaded = kFALSE) final;
Int_t AutoParse(const char* cls) final;
const std::set<std::string>& GetAutoParseClasses() const { return fAutoParseClasses; }
void* LazyFunctionCreatorAutoload(const std::string& mangled_name);
bool LibraryLoadingFailed(const std::string&, const std::string&, bool, bool);
Bool_t IsAutoLoadNamespaceCandidate(const clang::NamespaceDecl* nsDecl);
Expand Down Expand Up @@ -240,6 +243,7 @@ class TCling final : public TInterpreter {
Longptr_t ProcessLineAsynch(const char* line, EErrorCode* error = nullptr);
Longptr_t ProcessLineSynch(const char* line, EErrorCode* error = nullptr) final;
void PrintIntro() final;
void Print(Option_t *option="") const final;
bool RegisterPrebuiltModulePath(const std::string& FullPath,
const std::string& ModuleMapName = "module.modulemap") const final;
void RegisterModule(const char* modulename,
Expand All @@ -256,6 +260,8 @@ class TCling final : public TInterpreter {
void RegisterTClassUpdate(TClass *oldcl,DictFuncPtr_t dict) final;
void UnRegisterTClassUpdate(const TClass *oldcl) final;

void RegisterAutoLoadedLibrary(const char *libname) final;

Int_t SetClassSharedLibs(const char *cls, const char *libs) final;
void SetGetline(const char * (*getlineFunc)(const char* prompt),
void (*histaddFunc)(const char* line)) final;
Expand Down
Loading