Skip to content

Commit

Permalink
suppress warnings and errors when lookup succeeds on a subsequent try
Browse files Browse the repository at this point in the history
  • Loading branch information
bendavid committed Oct 4, 2024
1 parent 4d438e9 commit 8b22039
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
4 changes: 2 additions & 2 deletions bindings/pyroot/cppyy/CPyCppyy/src/Cppyy.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ namespace Cppyy {
CPPYY_IMPORT
bool IsMethodTemplate(TCppScope_t scope, TCppIndex_t imeth);
CPPYY_IMPORT
TCppMethod_t
GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto, std::ostream &diagnostics);
TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto,
std::ostringstream &diagnostics);

CPPYY_IMPORT
TCppIndex_t GetGlobalOperator(
Expand Down
8 changes: 7 additions & 1 deletion bindings/pyroot/cppyy/CPyCppyy/src/TemplateProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,14 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname,
pos = proto.find("initializer_list", pos + 6);
}

Cppyy::TCppMethod_t m2 = Cppyy::GetMethodTemplate(scope, fname, proto, diagnostics);
std::ostringstream diagnostics2;
Cppyy::TCppMethod_t m2 = Cppyy::GetMethodTemplate(scope, fname, proto, diagnostics2);
if (m2 && m2 != cppmeth) {
// replace if the new method with vector was found; otherwise just continue
// with the previously found method with initializer_list.
cppmeth = m2;
resname = Cppyy::GetMethodFullName(cppmeth);
diagnostics = std::move(diagnostics2);
}
}

Expand All @@ -241,6 +243,10 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname,
Py_DECREF(pyol);
Py_DECREF(pycachename);
Py_DECREF(dct);

PyErr_Format(PyExc_TypeError, "Failed to instantiate \"%s(%s)\"\n%s", fname.c_str(), proto.c_str(),
diagnostics.str().c_str());

return nullptr;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1837,7 +1837,7 @@ bool Cppyy::IsMethodTemplate(TCppScope_t scope, TCppIndex_t idx)
static std::map<TDictionary::DeclId_t, CallWrapper*> gMethodTemplates;

Cppyy::TCppMethod_t Cppyy::GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto,
std::ostream &diagnostics)
std::ostringstream &diagnostics)
{
// There is currently no clean way of extracting a templated method out of ROOT/meta
// for a variety of reasons, none of them fundamental. The game played below is to
Expand All @@ -1854,6 +1854,7 @@ Cppyy::TCppMethod_t Cppyy::GetMethodTemplate(TCppScope_t scope, const std::strin
// redirect diagnostics, taking the lock to make sure no other calls pollute the results
R__WRITE_LOCKGUARD(ROOT::gCoreMutex);

const std::string diagnosticsold = diagnostics.str();
TInterpreter::RedirectDiagnostics redirectRAII(gInterpreter, diagnostics, /*enableColors*/ true, /*indent*/ 4);

TFunction *func = nullptr;
Expand Down Expand Up @@ -1885,15 +1886,25 @@ if (scope == (cppyy_scope_t)GLOBAL_HANDLE) {

if (!func && name.back() == '>' && (cl || scope == (cppyy_scope_t)GLOBAL_HANDLE)) {
// try again, ignoring proto in case full name is complete template
auto declid = gInterpreter->GetFunction(cl, name.c_str());
if (declid) {
auto existing = gMethodTemplates.find(declid);
if (existing == gMethodTemplates.end()) {
auto cw = new_CallWrapper(declid, name);
existing = gMethodTemplates.insert(std::make_pair(declid, cw)).first;
}
return (TCppMethod_t)existing->second;
std::ostringstream diagnostics2;
TInterpreter::RedirectDiagnostics redirectRAII2(gInterpreter, diagnostics2, /*enableColors*/ true, /*indent*/ 4);

auto declid = gInterpreter->GetFunction(cl, name.c_str());
if (declid) {
auto existing = gMethodTemplates.find(declid);
if (existing == gMethodTemplates.end()) {
auto cw = new_CallWrapper(declid, name);
existing = gMethodTemplates.insert(std::make_pair(declid, cw)).first;
}
// replace diagnostics to suppress spurious errors or warnings from the previous
// failed lookup
diagnostics = std::ostringstream();
diagnostics << diagnosticsold;
diagnostics << diagnostics2.str();

return (TCppMethod_t)existing->second;
}
diagnostics << diagnostics2.str();
}

if (func) {
Expand All @@ -1909,16 +1920,24 @@ if (scope == (cppyy_scope_t)GLOBAL_HANDLE) {
if (name.back() == '>') {
auto pos = name.find('<');
if (pos != std::string::npos) {
TCppMethod_t cppmeth = GetMethodTemplate(scope, name.substr(0, pos), proto, diagnostics);
std::ostringstream diagnostics2;
TCppMethod_t cppmeth = GetMethodTemplate(scope, name.substr(0, pos), proto, diagnostics2);
if (cppmeth) {
// allow if requested template names match up to the result
const std::string &alt = GetMethodFullName(cppmeth);
if (name.size() < alt.size() && alt.find('<') == pos) {
const std::string &partial = name.substr(pos, name.size() - 1 - pos);
if (strncmp(partial.c_str(), alt.substr(pos, alt.size() - 1 - pos).c_str(), partial.size()) == 0)
if (strncmp(partial.c_str(), alt.substr(pos, alt.size() - 1 - pos).c_str(), partial.size()) == 0) {
// replace diagnostics to suppress spurious errors or warnings
// from the previous failed lookup
diagnostics = std::ostringstream();
diagnostics << diagnosticsold;
diagnostics << diagnostics2.str();
return cppmeth;
}
}
}
diagnostics << diagnostics2.str();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ namespace Cppyy {
RPY_EXPORTED
bool IsMethodTemplate(TCppScope_t scope, TCppIndex_t imeth);
RPY_EXPORTED
TCppMethod_t
GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto, std::ostream &diagnostics);
TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto,
std::ostringstream &diagnostics);

RPY_EXPORTED
TCppIndex_t GetGlobalOperator(
Expand Down

0 comments on commit 8b22039

Please sign in to comment.