diff --git a/.github/valgrind/cppinterop-clang23-valgrind.supp b/.github/valgrind/cppinterop-clang23-valgrind.supp new file mode 100644 index 00000000..75cd0158 --- /dev/null +++ b/.github/valgrind/cppinterop-clang23-valgrind.supp @@ -0,0 +1,467 @@ +# Upstream LLVM write(buf) uninit-bytes via the EPC transport, still +# present in release/23.x. No llvm/llvm-project issue filed yet; if you +# touch this file, please file one and add a reference here. +{ + Clang 23 Out of Process: uninitialised bytes in FDSimpleRemoteEPCTransport::sendMessage + Memcheck:Param + write(buf) + fun:__libc_write + fun:write + fun:_ZN4llvm3orc26FDSimpleRemoteEPCTransport11sendMessageENS0_21SimpleRemoteEPCOpcodeEmNS0_12ExecutorAddrENS_8ArrayRefIcEE + ... +} + +# llvm/llvm-project#194147: clang-23 still reads uninitialised bytes in many +# AST/Sema/CodeGen paths (regression vs clang-20). Was x86_64-only at +# first; aarch64 caught up after a release/22.x advance and now trips +# its own set (TreeTransform, SemaCUDA, AsmPrinter, ValueEnumerator). +# The blocks below started as a copy of clang22-valgrind.supp. +# Drop the whole #194147 family of blocks once the upstream issue lands. + +{ + llvm/llvm-project#194147: InitListExpr::isTransparent + Memcheck:Cond + fun:_ZNK5clang12InitListExpr13isTransparentEv + ... +} +{ + llvm/llvm-project#194147: InitListExpr::getInit + Memcheck:Cond + fun:_ZN5clang12InitListExpr7getInitEj + ... +} +{ + llvm/llvm-project#194147: InitListExpr::getInit const + Memcheck:Cond + fun:_ZNK5clang12InitListExpr7getInitEj + ... +} +{ + llvm/llvm-project#194147: InitListExpr::setInit + Memcheck:Cond + fun:_ZN5clang12InitListExpr7setInitEjPNS_4ExprE + ... +} +{ + llvm/llvm-project#194147: InitListExpr::resizeInits + Memcheck:Cond + fun:_ZN5clang12InitListExpr11resizeInitsERKNS_10ASTContextEj + ... +} +{ + llvm/llvm-project#194147: InitListExpr::resizeInits via memset + Memcheck:Cond + fun:memset + fun:_ZN5clang12InitListExpr11resizeInitsERKNS_10ASTContextEj + ... +} + +{ + llvm/llvm-project#194147: Sema::CheckForIntOverflow Cond + Memcheck:Cond + fun:_ZN5clang4Sema19CheckForIntOverflowEPKNS_4ExprE + ... +} +{ + llvm/llvm-project#194147: Sema::CheckForIntOverflow Value8 + Memcheck:Value8 + fun:_ZN5clang4Sema19CheckForIntOverflowEPKNS_4ExprE + ... +} +{ + llvm/llvm-project#194147: SequenceChecker::SequenceExpressionsInOrder + Memcheck:Cond + fun:*SequenceChecker*SequenceExpressionsInOrder* + ... +} + +{ + llvm/llvm-project#194147: Stmt::children via AnalyzeImplicitConversions + Memcheck:Cond + fun:_ZN5clang4Stmt8childrenEv + fun:*AnalyzeImplicitConversions* + ... +} +{ + llvm/llvm-project#194147: AnalyzeImplicitConversions leaf + Memcheck:Cond + fun:*AnalyzeImplicitConversions* + ... +} +{ + llvm/llvm-project#194147: CFGBuilder::Visit Cond + Memcheck:Cond + fun:*CFGBuilder*Visit* + ... +} +{ + llvm/llvm-project#194147: CFGBuilder::Visit Value8 + Memcheck:Value8 + fun:*CFGBuilder*Visit* + ... +} + +{ + llvm/llvm-project#194147: RecordExprEvaluator::VisitCXXParenListOrInitListExpr + Memcheck:Cond + fun:*RecordExprEvaluator*VisitCXXParenListOrInitListExpr* + ... +} +{ + llvm/llvm-project#194147: AggExprEmitter init-list visits + Memcheck:Cond + fun:*AggExprEmitter*Visit*InitListExpr* + ... +} + +{ + llvm/llvm-project#194147: InitListChecker::FillInEmptyInitForField + Memcheck:Cond + fun:*InitListChecker*FillInEmptyInitForField* + ... +} +{ + llvm/llvm-project#194147: InitListChecker::FillInEmptyInitializations + Memcheck:Cond + fun:*InitListChecker*FillInEmptyInitializations* + ... +} + +# llvm/llvm-project#194147 (continued): symbols newly tripped after +# release/22.x advanced and the llvm-release recipe republished. The +# FunctionProtoType ctor is the dominant top frame on x86_64; the +# CodeGen + EHScope entries cover the lower-frequency paths. +# +# Earlier iterations of this file carried ~17 more blocks targeting +# symbols extracted from "Uninitialised value was created by" +# allocation-origin frames; valgrind's matcher only considers the +# read-site top frame, so every one of those blocks was dead. +# Removed. (See the matching comment in clang21-valgrind.supp for +# why the over-broad `*FunctionProtoType*` is the only pattern that +# matches the constructor in valgrind's wildcard matcher.) +{ + llvm/llvm-project#194147: FunctionProtoType (any method, see comment) + Memcheck:Cond + fun:*FunctionProtoType* + ... +} +{ + llvm/llvm-project#194147: CodeGenFunction::EmitCall + Memcheck:Cond + fun:*CodeGenFunction*EmitCall* + ... +} +{ + llvm/llvm-project#194147: EHScopeStack::requiresLandingPad + Memcheck:Cond + fun:*EHScopeStack*requiresLandingPad* + ... +} +{ + # Top frame for every unsuppressed error in the llvm22-vg + # x86_64 row after FunctionProtoType started being silenced -- + # 21->173 errors all surfaced here, across 3->5 contexts + # depending on which CppInterOpTests' OutOfProcessJIT subtests + # ran. Origin frame is llvm::Module::setDataLayout (stack + # allocation) but valgrind matches read-site, so suppress + # by the read-site symbol. + llvm/llvm-project#194147: CodeGenModule::SetLLVMFunctionAttributesForDefinition + Memcheck:Cond + fun:*CodeGenModule*SetLLVMFunctionAttributesForDefinition* + ... +} + +# llvm/llvm-project#194147 (continued): symbols newly tripped on +# the arm64 cell after recipe republish. The aarch64 cell was +# previously documented as clean for #194147 (per the existing +# top-of-file note); that's now stale. Different code paths than +# x86_64 trips, mainly TreeTransform / SemaCUDA / AsmPrinter / +# bitcode writer. +{ + llvm/llvm-project#194147: TreeTransform::TransformIfStmt + Memcheck:Cond + fun:*TreeTransform*TransformIfStmt* + ... +} +{ + llvm/llvm-project#194147: SemaCUDA::inferTargetForImplicitSpecialMember + Memcheck:Cond + fun:*SemaCUDA*inferTargetForImplicitSpecialMember* + ... +} +{ + llvm/llvm-project#194147: AsmPrinter::emitPatchableFunctionEntries + Memcheck:Cond + fun:*AsmPrinter*emitPatchableFunctionEntries* + ... +} +{ + llvm/llvm-project#194147: ValueEnumerator::getAttributeGroupID Cond + Memcheck:Cond + fun:*ValueEnumerator*getAttributeGroupID* + ... +} +{ + # Same symbol, different error class: BitcodeWriter reads an + # 8-byte uninit field (AttributeSet pointer pair) when the + # ModuleBitcodeWriter::write() path serializes the module. Cond + # alone doesn't catch Memcheck:Value8 — value-load errors are + # tracked separately by valgrind. + llvm/llvm-project#194147: ValueEnumerator::getAttributeGroupID Value8 + Memcheck:Value8 + fun:*ValueEnumerator*getAttributeGroupID* + ... +} +{ + llvm/llvm-project#194147: TargetLowering::LowerCallTo + Memcheck:Cond + fun:*TargetLowering*LowerCallTo* + ... +} + +# llvm/llvm-project#194147 (continued): new in release/23.x on x86_64. +# The uninitialised bytes come from the heap allocation of X86TargetMachine +# and are read during SelectionDAG load combining. Fires in every test that +# JITs code; the forked children of the JitPthreadAtfork*/JitAtQuickExit* +# tests then exit through --error-exitcode=1 and the tests fail. +{ + llvm/llvm-project#194147: APInt::setLowBits via computeKnownBits + Memcheck:Cond + fun:_ZN4llvm5APInt10setLowBitsEj + fun:*computeKnownBits* + ... +} + +# llvm/llvm-project#194147 (continued): new in release/23.x on aarch64. +# +# In-process JIT: MachineFunction::getPreferredAlignment reads an +# uninitialised field. It fires in every test that JITs code, and the +# forked children of the JitPthreadAtfork*/JitAtQuickExit* tests then exit +# through --error-exitcode=1. +{ + llvm/llvm-project#194147: MachineFunction::getPreferredAlignment + Memcheck:Cond + fun:*MachineFunction*getPreferredAlignment* + ... +} + +# Out-of-process JIT: ORC runs with concurrent compilation, so +# BasicIRLayerMaterializationUnit::materialize calls cloneToNewContext, +# which writes the module to bitcode and reads it back. On aarch64 the +# serialized bytes are already uninitialised (origins: the heap slots of +# BitstreamWriter::EnterSubblock's Block vector and of CloneModule's +# Users), so every reader of the reloaded module trips valgrind: the +# bitcode reader itself, then the whole backend that compiles the module, +# then the destruction of its LLVMContext. The read sites run to hundreds +# of symbols, so these blocks key on a frame anywhere in the recorded +# stack (leading `...`) instead of on the top frame. + +# aarch64, ORC bitcode round trip (serialize/deserialize). +{ + llvm/llvm-project#194147 aarch64: orc::serializeModule Cond + Memcheck:Cond + ... + fun:*orc*serializeModule* +} +{ + llvm/llvm-project#194147 aarch64: orc::serializeModule Value8 + Memcheck:Value8 + ... + fun:*orc*serializeModule* +} +{ + llvm/llvm-project#194147 aarch64: orc::deserializeModule Cond + Memcheck:Cond + ... + fun:*orc*deserializeModule* +} +{ + llvm/llvm-project#194147 aarch64: orc::deserializeModule Value8 + Memcheck:Value8 + ... + fun:*orc*deserializeModule* +} +{ + llvm/llvm-project#194147 aarch64: BitcodeReader Cond + Memcheck:Cond + ... + fun:*BitcodeReader* +} +{ + llvm/llvm-project#194147 aarch64: BitcodeReader Value8 + Memcheck:Value8 + ... + fun:*BitcodeReader* +} +{ + llvm/llvm-project#194147 aarch64: BitstreamCursor Cond + Memcheck:Cond + ... + fun:*BitstreamCursor* +} +{ + llvm/llvm-project#194147 aarch64: BitstreamCursor Value8 + Memcheck:Value8 + ... + fun:*BitstreamCursor* +} +{ + llvm/llvm-project#194147 aarch64: MetadataLoader Cond + Memcheck:Cond + ... + fun:*MetadataLoader* +} +{ + llvm/llvm-project#194147 aarch64: MetadataLoader Value8 + Memcheck:Value8 + ... + fun:*MetadataLoader* +} + +# aarch64, codegen of the reloaded module. +{ + llvm/llvm-project#194147 aarch64: IRTranslator Cond + Memcheck:Cond + ... + fun:*IRTranslator* +} +{ + llvm/llvm-project#194147 aarch64: IRTranslator Value8 + Memcheck:Value8 + ... + fun:*IRTranslator* +} +{ + llvm/llvm-project#194147 aarch64: GISelCSE Cond + Memcheck:Cond + ... + fun:*GISelCSE* +} +{ + llvm/llvm-project#194147 aarch64: GISelCSE Value8 + Memcheck:Value8 + ... + fun:*GISelCSE* +} +{ + llvm/llvm-project#194147 aarch64: GISelInstProfileBuilder Cond + Memcheck:Cond + ... + fun:*GISelInstProfileBuilder* +} +{ + llvm/llvm-project#194147 aarch64: GISelInstProfileBuilder Value8 + Memcheck:Value8 + ... + fun:*GISelInstProfileBuilder* +} +{ + llvm/llvm-project#194147 aarch64: MachineCSE Cond + Memcheck:Cond + ... + fun:*MachineCSE* +} +{ + llvm/llvm-project#194147 aarch64: MachineCSE Value8 + Memcheck:Value8 + ... + fun:*MachineCSE* +} +{ + llvm/llvm-project#194147 aarch64: SelectionDAGISel Cond + Memcheck:Cond + ... + fun:*SelectionDAGISel* +} +{ + llvm/llvm-project#194147 aarch64: SelectionDAGISel Value8 + Memcheck:Value8 + ... + fun:*SelectionDAGISel* +} +{ + llvm/llvm-project#194147 aarch64: ScheduleDAGSDNodes Cond + Memcheck:Cond + ... + fun:*ScheduleDAGSDNodes* +} +{ + llvm/llvm-project#194147 aarch64: ScheduleDAGSDNodes Value8 + Memcheck:Value8 + ... + fun:*ScheduleDAGSDNodes* +} +{ + llvm/llvm-project#194147 aarch64: BranchProbabilityInfo Cond + Memcheck:Cond + ... + fun:*BranchProbabilityInfo* +} +{ + llvm/llvm-project#194147 aarch64: BranchProbabilityInfo Value8 + Memcheck:Value8 + ... + fun:*BranchProbabilityInfo* +} +{ + llvm/llvm-project#194147 aarch64: AllocaInst::getAllocationSize Cond + Memcheck:Cond + ... + fun:*AllocaInst*getAllocationSize* +} +{ + llvm/llvm-project#194147 aarch64: AllocaInst::getAllocationSize Value8 + Memcheck:Value8 + ... + fun:*AllocaInst*getAllocationSize* +} +{ + llvm/llvm-project#194147 aarch64: AsmPrinter Cond + Memcheck:Cond + ... + fun:*AsmPrinter* +} +{ + llvm/llvm-project#194147 aarch64: AsmPrinter Value8 + Memcheck:Value8 + ... + fun:*AsmPrinter* +} +{ + llvm/llvm-project#194147 aarch64: AArch64 Cond + Memcheck:Cond + ... + fun:*AArch64* +} +{ + llvm/llvm-project#194147 aarch64: AArch64 Value8 + Memcheck:Value8 + ... + fun:*AArch64* +} + +# aarch64, teardown of the reloaded module's context. +{ + llvm/llvm-project#194147 aarch64: LLVMContextImpl Cond + Memcheck:Cond + ... + fun:*LLVMContextImpl* +} +{ + llvm/llvm-project#194147 aarch64: LLVMContextImpl Value8 + Memcheck:Value8 + ... + fun:*LLVMContextImpl* +} +{ + llvm/llvm-project#194147 aarch64: removeDeadConstantUsers Cond + Memcheck:Cond + ... + fun:*removeDeadConstantUsers* +} +{ + llvm/llvm-project#194147 aarch64: removeDeadConstantUsers Value8 + Memcheck:Value8 + ... + fun:*removeDeadConstantUsers* +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26225103..a126c35c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,24 +20,24 @@ jobs: name: ${{ matrix.os }}/llvm${{ matrix.llvm }}/py${{ matrix.py }}/c++${{ matrix.cxx }}${{ matrix.vg && '/vg' || '' }}${{ matrix.flavor == 'cling' && '/cling' || '' }} strategy: fail-fast: false - # LLVM 22 is the primary target: every supported Python on ubuntu and + # LLVM 23 is the primary target: every supported Python on ubuntu and # macOS, a C++23 cell (test_cpp23features runs only there), a valgrind - # cell, and a cling cell. Linux uses the llvm-release recipe (apt-llvm.org - # can't supply the >=22 OOP-JIT runtime for flavor=system); macOS uses - # brew llvm@22. When CppInterOp supports LLVM 23 these cells move to 23. - # Remaining breadth (C++17, LLVM 20, arm) lives in nightly. + # cell, and a cling cell. Linux uses the llvm-release recipe. Arm macOS + # uses brew llvm@23. The Intel runner has no llvm@23 formula. Its brew + # cell stays on LLVM 22, and a recipe cell covers 23. The cling cell + # stays on LLVM 22. Breadth (C++17, LLVM 22, and arm) lives in nightly. matrix: include: - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20', vg: true } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '23' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.13', cxx: '20' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.12', cxx: '20' } - - { os: macos-26, llvm: '22', flavor: system, py: '3.14', cxx: '20' } - - { os: macos-26, llvm: '22', flavor: '', py: '3.13', cxx: '20' } - - { os: macos-26, llvm: '22', flavor: system, py: '3.12', cxx: '20' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '20', vg: true } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '20' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '23' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.13', cxx: '20' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.12', cxx: '20' } + - { os: macos-26, llvm: '23', flavor: system, py: '3.14', cxx: '20' } + - { os: macos-26, llvm: '23', flavor: '', py: '3.13', cxx: '20' } + - { os: macos-26, llvm: '23', flavor: system, py: '3.12', cxx: '20' } - { os: macos-26-intel, llvm: '22', flavor: system, py: '3.14', cxx: '20' } - - { os: macos-26-intel, llvm: '22', flavor: '', py: '3.12', cxx: '20' } + - { os: macos-26-intel, llvm: '23', flavor: '', py: '3.12', cxx: '20' } # cling backend, against the cached llvm-root (cling-llvm22) recipe cell. - { os: ubuntu-24.04, llvm: '22', flavor: cling, flavor_version: cling-llvm22, py: '3.14', cxx: '20' } uses: compiler-research/ci-workflows/.github/workflows/cppjit.yml@main @@ -60,7 +60,7 @@ jobs: # twice without failing. A failed find_package caches _DIR as -NOTFOUND, # and the reconfigure reads that as unset and searches again. reconfigure: - name: reconfigure/ubuntu-24.04/llvm22 + name: reconfigure/ubuntu-24.04/llvm23 runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 @@ -69,7 +69,7 @@ jobs: python-version: '3.14' - uses: compiler-research/ci-workflows/actions/setup-llvm@main with: - version: '22' + version: '23' os: ubuntu-24.04 - name: Prepare a CppInterOp for the override flows run: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5c3255f0..7913ef78 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -24,21 +24,21 @@ jobs: strategy: fail-fast: false matrix: - # Breadth beyond the PR matrix (C++17, LLVM 20, arm) and one cling - # cell. valgrind runs on LLVM 22 (x86 and arm) against the vendored - # clang22 suppressions under .github/valgrind/; the LLVM 20 cells carry + # Breadth beyond the PR matrix (C++17, LLVM 22, arm) and one cling + # cell. valgrind runs on LLVM 23 (x86 and arm) against the vendored + # clang23 suppressions under .github/valgrind/. The LLVM 22 cells carry # the older-major breadth. include: - - { os: ubuntu-24.04, llvm: '20', flavor: system, py: '3.12', cxx: '17' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '23' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.13', cxx: '20', vg: true } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20', vg: true } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20' } - - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.12', cxx: '20', vg: true } - - { os: ubuntu-24.04-arm, llvm: '22', flavor: '', py: '3.13', cxx: '20', vg: true } - - { os: ubuntu-24.04-arm, llvm: '20', flavor: system, py: '3.12', cxx: '17' } - - { os: macos-26, llvm: '22', flavor: system, py: '3.12', cxx: '20' } - - { os: macos-26, llvm: '22', flavor: system, py: '3.14', cxx: '23' } + - { os: ubuntu-24.04, llvm: '22', flavor: system, py: '3.12', cxx: '17' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '23' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.13', cxx: '20', vg: true } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '20', vg: true } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.14', cxx: '20' } + - { os: ubuntu-24.04, llvm: '23', flavor: '', py: '3.12', cxx: '20', vg: true } + - { os: ubuntu-24.04-arm, llvm: '23', flavor: '', py: '3.13', cxx: '20', vg: true } + - { os: ubuntu-24.04-arm, llvm: '22', flavor: system, py: '3.12', cxx: '17' } + - { os: macos-26, llvm: '23', flavor: system, py: '3.12', cxx: '20' } + - { os: macos-26, llvm: '23', flavor: system, py: '3.14', cxx: '23' } - { os: macos-26-intel, llvm: '22', flavor: system, py: '3.12', cxx: '20' } # cling backend, against the cached llvm-root (cling-llvm22) recipe cell. - { os: ubuntu-24.04, llvm: '22', flavor: cling, flavor_version: cling-llvm22, py: '3.13', cxx: '20' } diff --git a/CMakeLists.txt b/CMakeLists.txt index ac5fe0b7..bfffdc0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,9 +27,9 @@ if(NOT Python_Development.Module_FOUND) message(FATAL_ERROR "Python development headers not found") endif() -# The LLVM range the pinned CppInterOp supports; update together with the tag. -set(CPPJIT_LLVM_VERSION_MIN 20) -set(CPPJIT_LLVM_VERSION_MAX 22) +# The LLVM range the pinned CppInterOp supports. Update it with the tag. +set(CPPJIT_LLVM_VERSION_MIN 22) +set(CPPJIT_LLVM_VERSION_MAX 23) # Runtime fallback anchor for the dispatch (see cppinterop_paths()): the # installed package under scikit-build-core, the build tree otherwise -- diff --git a/test/support.py b/test/support.py index 94c47383..2f92319d 100644 --- a/test/support.py +++ b/test/support.py @@ -129,6 +129,8 @@ def setup_make(targetname, optional=False): == 1 ) IS_CLING = not IS_CLANG_REPL +# The interpreter's clang major, which tracks the LLVM major. +CLANG_MAJOR = cppjit.evaluate("__clang_major__") IS_CPP23 = ( cppjit.evaluate("""#if __cplusplus >= 202302L true diff --git a/test/test_fragile.py b/test/test_fragile.py index b72a5b3b..71b9501c 100644 --- a/test/test_fragile.py +++ b/test/test_fragile.py @@ -4,6 +4,7 @@ import py from pytest import mark, raises, skip from support import ( + CLANG_MAJOR, IS_CLANG_REPL, IS_LINUX, IS_MAC, @@ -646,7 +647,10 @@ def test25_cppdef_error_reporting(self): int add42(int i) { return i + 42; } }""") - @mark.xfail(condition=IS_CLANG_REPL, reason="Fails on ClangRepl") + @mark.xfail( + condition=IS_CLANG_REPL and CLANG_MAJOR < 23, + reason="Macro access fails on clang-repl before LLVM 23", + ) def test26_macro(self): """Test access to C++ pre-processor macro's"""