Skip to content

Cppyy interop migration (draft PR for CI)#22810

Draft
guitargeek wants to merge 107 commits into
root-project:masterfrom
guitargeek:cppyy-interop-migration_jonas
Draft

Cppyy interop migration (draft PR for CI)#22810
guitargeek wants to merge 107 commits into
root-project:masterfrom
guitargeek:cppyy-interop-migration_jonas

Conversation

@guitargeek

Copy link
Copy Markdown
Contributor

Trying out some commits in the CI.

@guitargeek
guitargeek force-pushed the cppyy-interop-migration_jonas branch from 519ffb7 to 4ac6cd0 Compare July 14, 2026 15:03
@guitargeek guitargeek self-assigned this Jul 14, 2026
@guitargeek
guitargeek force-pushed the cppyy-interop-migration_jonas branch 2 times, most recently from 217c0d5 to 2dc76e4 Compare July 14, 2026 16:08
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

Test Results

    21 files      21 suites   3d 6h 5m 19s ⏱️
 3 852 tests  3 852 ✅ 0 💤 0 ❌
71 768 runs  71 768 ✅ 0 💤 0 ❌

Results for commit 179e404.

♻️ This comment has been updated with latest results.

@guitargeek
guitargeek force-pushed the cppyy-interop-migration_jonas branch 7 times, most recently from 0074d7c to 842481a Compare July 17, 2026 05:54
aaronj0 and others added 17 commits July 17, 2026 08:03
…stream]

Adapts upstream CppInterOp for use with ROOT & Cling:

- Add SynthesizingCodeRAII guard for scope/class reflection
- Call buildLookup in lookup paths, to populate Cling's lazy lookup tables
- Drop class_name:: scope qualification in make_narg_call so virtual
  dispatch works for pure-virtual methods (TInterpreter::Declare)
- Export CppGetProcAddress from libCling's linker script for dispatch mechanism
- GetTypeAsString: revert the PrintingPolicy ctor to
  PrintingPolicy((LangOptions())) instead of deriving it from the
  ASTContext. Using default LangOptions restores the string form
  (std::basic_string<char>) that the CPyCppyy factory expects
Source: compres forks cppyy-backend/master 597bcf4

Drops ROOT's old clingwrapper in favour of the CppInterOp-based implementation from the compres fork.
Replaces gInterpreter/ROOT-meta TCling API calls with CppInterOp via the dispatch mechanism (cppinterop_dispatch.cxx to load API)
Adds recursive_mutex thread safety, switches execution to JitCall. To be followed with ROOT-specific patches.
…patch]

CPPINTEROP_DIR is the include-root that contains the CppInterOp/ subdir
with Dispatch.h and the tablegen-generated CppInterOpAPI.inc. Pass it
straight to Cpp::AddIncludePath instead of concatenating "/include",
matching where the build system actually places those headers.
Based on ROOT:

- Load libCling via gSystem->DynamicPathName instead of the fork's
  CPPINTEROP_DIR/lib path
- include ROOT core headers and call TClass::GetClass in GetScope
  for dictionary/module autoloading.
- Guard GetActualClass and GetBaseOffset with Cpp::IsComplete to
  handle incomplete types (e.g. TCling with no public header)
- Initialise ROOT globals and required dylibs in ApplicationStarter
- Move precommondefs.h include into cpp_cppyy.h; use
  Cpp::TCppFuncAddr_t for proper alignment
- Update CMakeLists for ROOT build-tree integration
Dispatch.h transitively includes the tablegen-generated CppInterOpAPI.inc,
which lives in the build tree, not the source tree. ROOT stages CppInterOp's
public headers + .inc files into ${BINARY_DIR}/etc/cppinterop/CppInterOp/
via the CppInterOpEtc custom target. Point cppyy_backend's include dir
and the runtime CPPINTEROP_DIR macro at that staging dir, and depend on
CppInterOpEtc so staging completes before this library compiles.
Source: compres forks cppyy/master 273ed88

- Calls gCling.EnableAutoLoading()
- Adds cppyy.evaluate / cppyy.macro() / cppyy.ll.as_memoryview
- Numba pointer/reference support
- Metaclass naming fix, isinstance() idiom cleanup
- Bug fixes in basic_string / span / npos pythonizations
- Fallback decoding paths for non-UTF-8 compiler output

To be followed with ROOT-specific patches.
… [upstream]

Same as in Pythonize.cxx basic_string name from GetQualifiedCompleteName
so the NPOS object is registered for the canonical class name shapes.
ROOT-specific patches on top of the compres fork cppyy/master baseline:

__init__.py:
- set gInterpereter to gbl.TInterpreter.Instance()
- load_library(): use gSystem.Load/FindDynamicLibrary, add Windows winmode=0 for search path
- add_library_path(): use gSystem.AddDynamicPath
- Drop the CPPYY_API_PATH apipath_extra dispatcher-headers (ROOT installs CPyCppyy API headers)

_cpython_cppyy.py:
- Wrap `from cppyy_backend import loader` in try/except, fall back to
  c = None (ROOT does not ship cppyy_backend.so)
- Platform: `import libcppyy` vs `import cppyy.libcppyy`
  (standalone cppyy uses the former; ROOT exposes it as cppyy.libcppyy)
- load_reflection_info(): use gSystem.Load

ROOT/_facade.py:
- Store gInterpreter and gPad in __dict__
Source: compres forks CPyCppyy/master 482ccb7
Brings in fork-ahead developments missing from ROOT's old copy and compatibility with the CppInterOp based backend:

- CppInterOp-aligned type system (Cppyy.h)
- Type-based CreateConverter / CreateExecutor factory overloads
- Instance_FromVoidPtr(scope) overload
- PythonGILRAII for exception-safe GIL management
- PyError_t RAII rewrite (unique_ptr-based)
- GetTemplateArgsTypes for type-based template instantiation
- ReduceReturnType/LambdaClass handling
- Rvalue forwarding in Dispatcher
- GetFailureMsg in Converters
- STL string executor returns bound C++ object

ROOT-specific CPyCppyyModule.h and CPyCppyyPyModule.cxx are preserved from master.
…tream]

Source: ROOT master

- Move to using SetGlobalPolicy(ECallFlags, bool) + GlobalPolicyFlags()
- Drop the CallContext* argument from UseStrictOwnership()
- Guard PyMapping_GetOptionalItemString for Python>3.13 in Dispatcher.cxx
Source: master

- Deprecate __mempolicy__ getter/setter with a clear error pointing
  users to the SetOwnership() pythonization
- Drop the per-method memory policy from mp_call (referenced the
  removed sMemoryPolicy static)
- Use GlobalPolicyFlags() for the Clone heuristic
- Match the method name prefix before '<' only, so template
  arguments don't affect Clone detection
CallO allocates the buffer for a by-value return with
::operator new(SizeOfType(result_type)). If the result type is invalid or
incomplete, the size comes out as 0 and the JIT-compiled wrapper
constructs the returned object into a zero-sized allocation, corrupting
the heap (seen on Windows as an access violation on the first by-value
std::string return, in test_pythonify.py test19_keywords_and_defaults).
Fail the call with a clear message instead.
The Python version of this tutorial sporadically crashes on CI (e.g. on
opensuse16) with memory corruption detected in cling's JIT at interpreter
shutdown, as a segfault in llvm::Value::~Value() /
ReplaceableMetadataImpl::resolveAllUses() while ~IncrementalJIT destroys
the compiled modules. It is the same overlapping-heap-ownership problem
that was worked around for rf619_discrete_profiling.py in 49fb353:
with MALLOC_PERTURB_ poisoning enabled the crash becomes deterministic,
and the crashing reads then find the fresh-malloc fill pattern in live
LLVM metadata, i.e. the allocator handed the same memory to two owners.
An ASan-runtime preload run shows no double free, and disabling the glibc
tcache makes the crash disappear, so the corruption plausibly enters
through a stale write into the tcache header of a freed chunk.

The nll/pll pair used for the likelihood surface in pad 3 is not needed
after that plot. Deleting it right there tears down the NLL evaluation
machinery at a well-defined point instead of at interpreter shutdown,
where the order of cleanups is less controlled. With this change the
previously deterministic poisoned repro (4/4 crashing) passes 3/3, and
plain and ctest invocations pass as well.

This is a workaround at the tutorial level; the underlying overlapping
heap ownership still deserves an AddressSanitizer investigation (note the
CI ASan job currently excludes tutorials).
_find_used_classes() called str() on every variable of the target
namespace to detect class proxies by their string prefix. For a namespace
like cppyy.gbl that also holds bound C++ *instances* (e.g. gInterpreter),
str() of an instance triggers C++ overload resolution for operator<<,
which may attempt candidate implicit conversions via JIT-compiled
constructor calls.

On Windows this made every 'import ROOT' hang for many minutes: the MSVC
STL declares stream operators for its random-engine classes (present in
the AST via TRandomRanlux48), whose seed-sequence template constructor
accepts any class type, so str(gInterpreter) attempted to construct
std::_Swc_base<unsigned long long,5,12,...>(TInterpreter&). That wrapper
never compiles (unresolved _Swc_traits::_Reset<TInterpreter>), compile
failures are not cached, and the scan re-runs for every pythonization
module, adding up to hundreds of ~2 s JIT failures per process
(diagnosed via a temporary Python-stack tracer in CI; the flood made
python tutorials and the rootmv/rootcp/... CLI tools time out and the
whole Windows CI job exceed its time limit).

Skip bound instances entirely and only stringify actual types for the
class-proxy check. This is also a general speedup of pythonization
registration on all platforms.
Restructure the loop over namespace variables into mutually exclusive
if/elif branches, one per kind of value (class proxy, bound instance,
template proxy), and document why template proxies are recognized by
their repr: they are not Python types and cannot be reliably detected
with isinstance, since cppyy.types.Template is the backend proxy class,
which the cppyy.Template wrapper does not derive from.

No functional change.
GetParentScope() returned the raw decl context, so a declaration whose
canonical decl sits inside an `extern "C" / "C++"` linkage spec (or a
C++20 export block) got that block - which is not a NamedDecl - as its
parent scope, surfacing as an "<unnamed>" scope.

This broke all of std:: on Windows: the canonical declaration of
namespace std comes from an `extern "C++"` block in the MSVC CRT headers
(e.g. vcruntime_new.h), so every class proxy created from a type (rather
than through attribute access) was parented as
cppyy.gbl.<unnamed>.std.Klass. That created a second, distinct proxy
family for the same C++ classes, breaking proxy identity and instance
conversions, seen as the test_cpp11features failures on the Windows CI
(test04/test05/test21: shared_ptr<Derived> refusing to convert to
shared_ptr<Base>, smart-pointer downcast returning
"<unnamed>.std.shared_ptr<TestSmartPtr>").

Linkage specs and export blocks are transparent contexts, not scopes:
skip them when determining the parent. Reproduced platform-independently
with a namespace whose first declaration is inside `extern "C++"`.
@guitargeek
guitargeek force-pushed the cppyy-interop-migration_jonas branch from 69ee97c to 2e552ac Compare July 17, 2026 10:47
…[upstream]

make_narg_call decided whether a by-value argument must be moved with a
triviality heuristic (trivial copy constructor present but not simple,
plus a move constructor). Those triviality bits are not reliable across
standard libraries: MSVC's std::unique_ptr has a non-trivial deleted
copy constructor, so the wrapper passed the argument as an lvalue and
failed to compile with "call to deleted constructor" on Windows. Seen
in the Windows CI as pyunittests-tree-ntuple-ntuple-py-basics failures:
every RNTupleWriter::Append/Recreate(std::unique_ptr<RNTupleModel>, ...)
call errored with "nullptr result where temporary expected".

Use the IsCopyConstructorDeleted helper (ported from TClingCallFunc,
already used by make_narg_ctor) which inspects the actual copy
constructor instead, matching the old backend's battle-tested behavior.
GetEnumConstantValue round-tripped enum values above INT64_MAX through
a string and std::stoul. unsigned long is 32 bit on LLP64 platforms
(Windows), so any such value made std::stoul throw std::out_of_range,
which escaped through the bindings and took the process down. Seen on
the Windows CI in pyunittests-core-metacling-MetaClingTests
(test_GH_20925, enum value 1<<63: uncaught std::_Xout_of_range in
Cpp::GetEnumConstantValue via CPPEnum_New).

Return the zero-extended bit pattern with APSInt::getZExtValue instead;
values above INT64_MAX are exactly the unsigned 64-bit ones.
On Windows, the Dyld's library scan (used as last resort for symbols
that resolve neither in the JIT nor in the process) walks the search
path, which includes System32. Windows still ships the Visual C++ 6
runtime there (msvcp60.dll), which exports std::basic_string and other
std:: members whose mangled names match modern lookups - with a
pre-C++11, refcounted ABI. Binding JIT'd code to those exports silently
corrupts every object they touch.

Seen on the Windows CI of the CppInterOp migration branch: JIT'd
wrapper code calling outlined MSVC STL string methods (msvcp140.dll
exports almost none of basic_string, it is header-inline) landed in
msvcp60.dll, producing strings with NULL data pointers but positive
sizes (test_crossinheritance test37: "NULL string with positive size"
from call_fs building its result via operator+=), access violations in
string concatenation, streaming and default-argument materialization
(test_pythonify test10/test19, test_regression test18, test_stltypes
test09, test_streams, test_fragile test20, test_templates test16),
and a direct stack trace with msvcp60!basic_string::find under JIT
frames in tutorial-roofit-roostats-StandardHypoTestInvDemo-py.

Permanently ignore msvcp*/msvcr*/msvcirt* in the scan, in both cling's
Dyld and CppInterOp's port of it. The runtimes the process actually
links are already loaded and their exports are found in-process before
this scan is consulted, so this only removes the ABI-incompatible
legacy candidates; genuinely unresolved symbols now fail with a clear
"symbol unresolved" error instead of corrupting memory.

The CppInterOp part is [upstream] material.
GetSmartPtrInfo took the single operator-> returned by Cpp::GetOperator
and read the pointee type from its return type. MSVC's
std::shared_ptr::operator-> is a member template (SFINAE-constrained on
the element type not being an array), so the lookup yields the function
template pattern whose return type is dependent - the pointee scope came
back null and smart-pointer detection failed for every std::shared_ptr
on Windows. That disabled smart-pointer transparency, auto-downcasting
and derived-to-base conversions, seen in the Windows CI as the
test_cpp11features test04/test05/test21, test_pythonization
test04/05/06/10 and test_crossinheritance test11 failures.

Instantiate the operator with Cpp::BestOverloadFunctionMatch (it takes
no arguments; the defaulted template parameter supplies the element
type) before reading the return type, and hand the instantiation to the
caller so it is directly callable. Adds a CppInterOp unit test for the
zero-argument instantiation of such an operator [upstream].
…pstream]

When the address of a global variable could not be found in any loaded
binary, GetVariableOffset unconditionally replaced the declaration with
VarDecl::getDefinition(). For an extern declaration whose definition
lives in a binary that does not export the symbol, there is no
definition in the AST and that returned null, crashing on the following
hasInit() call.

This is Windows-only in practice: ELF shared libraries export their
globals, but on Windows bindexplib deliberately excludes read-only data
from a DLL's export table, so e.g. `extern const char my_global_string2[]`
from an ACLiC library takes exactly this path. Seen in the Windows CI as
the access violations in test_advancedcpp test21 (access to global
variables; the stack points into Cpp::GetVariableOffset), and most
likely also test_streams test02/test_fragile test20 (std::cout, whose
definition is in msvcp140.dll and not in the AST either).

Keep the declaration when there is no definition, and only attempt the
last-resort interpreter evaluation of `&::var` when CodeGen could
actually emit the variable (definition or initializer available in the
AST): otherwise the emitted reference can never resolve and the
evaluation is at best pointless. Such variables now fail with a clear
diagnostic, and the data member comes out as unavailable in the
bindings, matching the old backend's behavior.
…etails

MSVC's std::_Swc_base (the base class of its subtract-with-carry random
engines, for which <random> declares stream operators) has an
unconstrained generator constructor that accepts any lvalue. Whenever a
CPyCppyy overload walk involves such a candidate - e.g. resolving
operator<< during __str__/repr, or iterator protocol comparisons - the
implicit-conversion round tries to construct the engine from the given
argument. Each attempt JIT-compiles a constructor wrapper that fails
(~2 s, and failures are deliberately not cached), so any code path doing
this per call slows down by orders of magnitude: seen on the Windows CI
as 1500 s timeouts of the datatypes, stltypes, doc-features,
rdataframe-asnumpy and pyroot-roofit suites, with thousands of
"Failed to materialize symbols: ... _Swc_base ..." errors in the log.
libstdc++ constrains these constructors, which is why Linux never
triggers the conversion.

Implicit conversion to a reserved-name class (leading underscore, e.g.
std::_Swc_base, std::_Array_iterator, __gnu_cxx::...) is never what a
user-facing API expects: skip it outright.
On the Windows CI, gbl.gSystem (and likely most other class-typed
bindings) surfaces as an instance of an unusable proxy class printed as
'', i.e. the underlying C++ type was resolved to a nameless scope
(presumably the global scope, which Cpp::GetScope returns for an empty
name). The resolution chain that ends there is not reproducible on
Linux or macOS.

Report once per type, on stderr, whenever

- CreateConverter resolves a class type to a nameless scope,
- CreateExecutor resolves a class type to a nameless or null scope,
- BindCppObjectNoCast is asked to bind an instance to the global scope,

printing all intermediate type strings so the next Windows CI run
pinpoints which name-producing call goes wrong. To be reverted (or
turned into hard errors) once the Windows failure is understood.
On Windows, every PyROOT process ends up repeatedly attempting an implicit
conversion of a TInterpreter instance to std::_Swc_base<unsigned long long,
5, 12, ...> (the base class of std::ranlux48). Each attempt JIT-compiles a
constructor wrapper that fails to compile, costing ~2 s, and since the
failure is swallowed by overload resolution, the driving Python code turns
into an apparent hang (846 attempts in the 1500 s ctest timeout of
tutorial-hist-hist001_TH1_fillrandom-py).

Print the Python stack for the first few failed implicit conversions to a
_Swc_base target so the next CI log names the Python call site that drives
the loop. No output on healthy platforms, where no such conversion is ever
attempted.
…gExecutor

STLStringExecutor sizes the return buffer of by-value std::string calls
from whatever scope Cppyy::GetFullScope("std::string") yields. If that
resolution fails or picks the wrong scope, the call crashes with a wrong
sized buffer. Print the actual resolution once when it does not look like
a string type, to diagnose the access violation seen on Windows.
The previous run showed neither the STLStringExecutor nor the Cppyy::CallO
diagnostics firing before the access violation in
test_pythonify.py::test19_keywords_and_defaults (first by-value
std::string return), so the std::string resolution looks healthy and the
crash happens inside the call. Bracket every by-value return call with
enter/done markers (first 200, Windows only) and report the resolved
std::string scope with its computed size once, so the next CI log shows
exactly which call crashes and with what buffer size.
The Windows access violations in test_pythonify (test10 on x86, test19 on
x64) both fire in a JIT wrapper branch that has to materialize std::string
default-argument temporaries. To localize the crash within that branch:

- emit an "enter" marker into each nargs branch of wrappers for functions
  with class-type defaulted parameters (Windows always; elsewhere behind
  CPPINTEROP_WRAPPER_TRACE=1 for validation), and dump the exact wrapper
  source as generated on the target;
- print entry and argument sizes in the callees ArgPasser::stringRef
  (example01.cxx, DLL-compiled) and KeyWordsAndDefaults::bar
  (test_pythonify.py cppdef, JIT-compiled) on Windows.

Every generated branch body ends in `return;`, so the caller-side
"Cppyy::CallO done" print acts as the closing bracket: a crash between
branch "enter" and the callee print is in the construction of the default
temporaries; between the callee returning and "CallO done" only their
destruction runs (the return value is constructed directly into `ret`).
@guitargeek
guitargeek force-pushed the cppyy-interop-migration_jonas branch from 2e552ac to 8ced3e5 Compare July 17, 2026 14:08
The reserved-name guard in ConvertImplicit blocked all implicit
conversions to standard library implementation-detail classes. That is
too aggressive: on libc++, vector<T>::begin() returns
std::__wrap_iter<char*> while insert()/erase() take a const_iterator,
std::__wrap_iter<const char*>, and the iterator-to-const_iterator
conversion goes through __wrap_iter's converting constructor - exactly
the path the guard cut off. Seen on the macOS CI as
pyroot-pyz-stl-vector test_stl_vector_iadd and doc-features
test10_stl_algorithm failures ("could not convert argument 1:
[InstanceConverter]" for __wrap_iter arguments). MSVC and libstdc++
were unaffected: MSVC's iterator derives from its const_iterator
(inheritance, no implicit conversion needed).

Allow the conversion when the source is an instance of another
instantiation of the same template as the target. Cross-type
conversions into details (the Windows std::_Swc_base greedy-constructor
timeouts this guard exists for) remain blocked.
The RTTI probe in GetActualClass reads a vtable pointer at offset 0 of
the object. MSVC's iostream classes use virtual inheritance, which
places the vbptr - not a vfptr - at offset 0, so probing e.g. std::cout
follows a garbage pointer: seen on the Windows CI as access violations
in test_streams test02 (binding std::cout) and test_fragile test20
(capturing output), with GetActualClass under BindCppObject in the
stack. Port the filter from the old backend (added there originally for
a crash on Mac ARM): do not autocast std:: stream classes, it is
usually unnecessary anyway.
GetEnumConstantValue returned size_t, which is 32 bit on ILP32/LLP64
platforms: on the 32-bit Windows CI, the 1<<63 enumerator of
MetaClingTests test_GH_20925 came back as 0 (the crash on such values
was fixed previously; this fixes the truncation). Return the 64-bit
bit pattern as int64_t on all platforms, and propagate the width
through Cppyy::GetEnumDataValue (whose CPyCppyy caller already stores
into a long long).
…ream]

When a global's address is found in no loaded binary but its definition
with initializer is available in the AST (e.g. via a dictionary), force
its emission in the JIT instead of falling through to the
interpreter-evaluated `&::var` expression. On Windows, read-only data is
deliberately not exported from DLLs by bindexplib, so e.g.
`extern const char my_global_string2[]` from an ACLiC library was
unreachable and the evaluate fallback crashed in the value capture
(test_advancedcpp test21 access violations on the Windows CI, stack in
Cpp::GetVariableOffset via cling::runtime::internal::setValueWithAlloc).
The emitted copy of such a constant has the same value; writable
globals are exported and resolved earlier, so they cannot acquire a
diverging JIT copy through this path.
On the Windows CI, smart-pointer transparency now works but the smart
class proxies lack their plain named methods ('get', 'reset'):
test_pythonization test04/test06/test10. Report how many methods
Cpp::GetClassMethods finds for shared_ptr/unique_ptr instantiations and
how many survive the deleted-method filter, to tell whether enumeration
comes up empty (incomplete instantiation?) or IsFunctionDeleted
misfires on MSVC.
Fixes a sporadic crash of the
`pyunittests-roottest-python-distrdf-backends-all`
test (reported by CTest as "Subprocess aborted", i.e. the main pytest
process dies from a fatal signal, most often surfacing at
`TestInitialization::test_initialization_method[dask]`).

The problem was that the DistRDF client (the user's main process) drives
ROOT from more than one thread without ROOT thread safety being enabled.
The default-argument access violations on Windows are understood and
fixed (msvcp60 ABI poisoning, excluded in the dynamic library lookup),
and the pythonify suite passes on the Windows CI. Beyond being obsolete,
the prints polluted the output of reference-comparing tests.
The Windows default-argument access violations this instrumented are
understood and fixed (msvcp60 ABI poisoning, excluded in the dynamic
library lookup). Beyond being obsolete, dumping the wrapper source broke
reference-comparing tests (roottest-python-regression-gh_16406).
cling's Interpreter::process() can return success even though error
diagnostics were emitted during parsing; on Windows this made
cppyy.cppexec() of invalid code return cleanly instead of raising
(cppyy test_fragile test22_cppexec: "DID NOT RAISE SyntaxError"; on
Linux/macOS an interpreter exception happens to preempt the return
code, so the problem was masked). Cpp::Declare already guards against
exactly this with a DiagnosticErrorTrap; give Cpp::Process the same
treatment.
…ffset [upstream]

On Windows, bindexplib deliberately does not export read-only data from
DLLs, so const globals like cppyy test_advancedcpp's

    const char my_global_string2[] = "zus jet teun";

cannot be resolved from the defining library. The previous ForceCodeGen
extension did not make the symbol resolvable on the Windows CI either,
and the subsequent "&::var" evaluate fallback crashes there in cling's
value capture (access violation in test21_access_to_global_variables).

When the initializer is available in the AST (the ACLiC dictionary
provides it), the variable's value can be reproduced without any JIT
involvement: evaluate the initializer to an APValue and copy it into a
per-decl host-side buffer, exactly like the existing getRawData
early-return does for integral constants. Handles constant-size arrays
of integral/enum/floating elements, which covers const char string
arrays; arrays of pointers still fall through to the existing paths.
All prints are Windows-gated and marked [jc-TEMP] for later removal:

- CollectUniqueBases/BuildCppClassBases: report base enumeration and
  base proxy creation for smart pointer classes and std::_Ptr_base.
  windows_6 shows shared_ptr proxies lack exactly the methods MSVC
  declares in the _Ptr_base base ('get', 'use_count') while methods
  declared in shared_ptr itself (incl. member templates like
  reset(U*)) work, pointing at a dropped or empty base proxy
  (pythonization test04/test06, ntuple-py-basics).
- GetClassMethods: include std::_Ptr_base scopes and print the method
  names, to see whether 'get' is enumerated on the base.
- CPPDataMember::Set: print dims for array-like members. The
  regression test38_char16_arrays garbage matches a char16_t[6] member
  being read through the pointer-style converter path without the
  kIsArrayType indirection, i.e. lost dimensions (also suspected for
  the asnumpy flat std::array read and datatypes test38).
- CallO: compile the wrapper before invoking (cached) with a marker in
  between, to tell whether the stltypes (TestSTLLIST) and pyroot-roofit
  (std::map iteration via std::_Tree::begin) timeouts hang in wrapper
  JIT compilation or in the call itself.
- ConvertImplicit: report same-template reserved-name conversions, in
  case the allowance re-opened a slow implicit-conversion flood on
  MSVC container internals.
- GetVariableOffset: report the state when the post-ForceCodeGen
  symbol lookup still fails (advancedcpp test21 family; the const
  array materialization should now serve those before this point).
Cpp::GetName takes a ConstDeclRef and there is no conversion from
Cpp::FuncRef, so the method-name loop added for the shared_ptr
diagnostics failed to compile on Windows (C2664 at clingwrapper.cxx
:1651). Construct the DeclRef from the FuncRef's data pointer, the
same pattern used in GetTemplatedMethodName.

The diagnostics are _WIN32-gated and thus were never compiled by the
Linux builds; all blocks from the previous diagnostics commit have now
been compile-tested with the guards flipped on Linux.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants