Merge branch 'devel' into araq-icu

This commit is contained in:
Araq
2026-07-02 12:11:00 +02:00
11 changed files with 121 additions and 9 deletions

View File

@@ -2283,3 +2283,21 @@ proc genTypeSection(m: BModule, n: PNode) =
discard getTypeDescAux(m, s.typ, intSet, descKindFromSymKind(s.kind))
if m.g.generatedHeader != nil:
discard getTypeDescAux(m.g.generatedHeader, s.typ, intSet, descKindFromSymKind(s.kind))
# Unlike genCppInitializer which returns just the braced value list (e.g. "{a, b}"),
# genCppConstructorExpr returns a full type-prefixed expression (e.g. "Foo(a, b)").
# This is used when a standalone construction expression is needed — e.g. on the
# right-hand side of an assignment — whereas genCppInitializer is used in variable
# declarations where the type is already written separately before the initializer.
proc genCppConstructorExpr(m: BModule, prc: BProc; typ: PType; didGenTemp: var bool): Snippet =
var params = ""
if typ.itemId in m.g.graph.initializersPerType:
let call = m.g.graph.initializersPerType[typ.itemId]
if call != nil:
var p = prc
if p == nil:
p = BProc(module: m)
params = genCppParamsForCtor(p, call, didGenTemp)
if prc == nil:
assert p.blocks.len == 0, "BProc belongs to a struct doesnt have blocks"
result = getTypeDesc(m, typ, dkVar) & "(" & params & ")"

View File

@@ -613,7 +613,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
if isImportedCppType(typ):
var didGenTemp = false
let rl = rdLoc(loc)
let init = genCppInitializer(p.module, p, typ, didGenTemp)
let init = genCppConstructorExpr(p.module, p, typ, didGenTemp)
p.s(cpsStmts).addAssignment(rl, init)
return
if optSeqDestructors in p.config.globalOptions and typ.kind in {tyString, tySequence}:

View File

@@ -89,6 +89,18 @@ proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
changeType(c, x, formal, check=true)
result = arg
result = skipHiddenSubConv(result, c.graph, c.idgen)
# Walk through nested statement-list/block expressions to find the innermost
# value node. Empty containers (e.g. `@[]`) inside `nkStmtListExpr` wrappers
# need their type resolved to match the formal type, otherwise the C codegen
# cannot map `tyEmpty` to a concrete type (fixes #25945).
var tail = result
while tail.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkPragmaBlock} and tail.len > 0:
tail = tail.lastSon
if tail.typ != nil and tail.typ.isEmptyContainer and
formal.kind notin {tyUntyped, tyBuiltInTypeClass, tyAnything}:
changeType(c, tail, formal, check=true)
# mark inserted converter as used:
var a = result
if a.kind == nkHiddenDeref: a = a[0]

View File

@@ -93,6 +93,7 @@ type
graph: ModuleGraph
c: PContext
escapingParams: IntSet
inNimvmBranch: int
PEffects = var TEffects
const
@@ -1127,7 +1128,7 @@ proc trackCall(tracked: PEffects; n: PNode) =
# sfCompileTime` path in `semProcAux`.
if a.kind == nkSym and a.sym.magic in {mNLen..mNError, mSlurp..mQuoteAst} and
tracked.owner != nil and tracked.owner.kind in routineKinds and
tracked.config.cmd != cmdNimscript:
tracked.config.cmd != cmdNimscript and tracked.inNimvmBranch == 0:
# ...but NOT under `nim e`: nimscript has no codegen backend to protect, and
# marking a routine `sfCompileTime` makes `semExpr` eagerly fold calls to it
# at sem time (emConst), where module-level globals it reads have no VM slot
@@ -1483,7 +1484,9 @@ proc track(tracked: PEffects, n: PNode) =
of nkCaseStmt: trackCase(tracked, n)
of nkWhen: # This should be a "when nimvm" node.
let oldState = tracked.init.len
inc tracked.inNimvmBranch
track(tracked, n[0][1])
dec tracked.inNimvmBranch
tracked.init.setLen(oldState)
track(tracked, n[1][0])
of nkIfStmt, nkIfExpr: trackIf(tracked, n)

View File

@@ -134,11 +134,11 @@ nimblepath="$home/.nimble/pkgs/"
# BSD got posix_spawn only recently, so we deactivate it for osproc:
define:useFork
@elif haiku:
gcc.options.linker = "-Wl,--as-needed -lnetwork"
gcc.cpp.options.linker = "-Wl,--as-needed -lnetwork"
clang.options.linker = "-Wl,--as-needed -lnetwork"
clang.cpp.options.linker = "-Wl,--as-needed -lnetwork"
tcc.options.linker = "-Wl,--as-needed -lnetwork"
gcc.options.linker = "-Wl,--as-needed -lnetwork -lbsd"
gcc.cpp.options.linker = "-Wl,--as-needed -lnetwork -lbsd"
clang.options.linker = "-Wl,--as-needed -lnetwork -lbsd"
clang.cpp.options.linker = "-Wl,--as-needed -lnetwork -lbsd"
tcc.options.linker = "-Wl,--as-needed -lnetwork -lbsd"
@elif not genode:
# -fopenmp
gcc.options.linker = "-ldl"

View File

@@ -28,6 +28,15 @@ elif defined(netbsd):
EVFILT_PROC* = 4 ## attached to struct proc
EVFILT_SIGNAL* = 5 ## attached to struct proc
EVFILT_TIMER* = 6 ## timers (in ms)
elif defined(haiku):
const
EVFILT_READ* = -1
EVFILT_WRITE* = -2
EVFILT_AIO* = -3 ## attached to aio requests
EVFILT_VNODE* = -4 ## attached to vnodes
EVFILT_PROC* = -5 ## attached to struct proc
EVFILT_SIGNAL* = -6 ## attached to struct proc
EVFILT_TIMER* = -7 ## timers
when defined(macosx):
const
EVFILT_MACHPORT* = -8 ## Mach portsets

View File

@@ -89,7 +89,7 @@ elif defined(emscripten) and not defined(StandaloneHeapSize):
var mmapDescrPos = cast[int](result) -% sizeof(EmscriptenMMapBlock)
var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
var mmapDescr = cast[PEmscriptenMMapBlock](mmapDescrPos)
mmapDescr.realSize = realSize
mmapDescr.realPointer = realPointer
@@ -99,7 +99,7 @@ elif defined(emscripten) and not defined(StandaloneHeapSize):
proc osDeallocPages(p: pointer, size: int) {.inline.} =
var mmapDescrPos = cast[int](p) -% sizeof(EmscriptenMMapBlock)
var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
var mmapDescr = cast[PEmscriptenMMapBlock](mmapDescrPos)
munmap(mmapDescr.realPointer, mmapDescr.realSize)
elif defined(genode) and not defined(StandaloneHeapSize):

View File

@@ -75,3 +75,15 @@ block: # importc type inheritance
doAssert(cast[cint](b) == 123)
var c = foo(b)
doAssert(cast[cint](c) == 123)
block: # bug #25945
var stateRefund = 0
let authCode =
if true:
if false:
stateRefund += 0
@[]
else:
@([1.byte])
discard (if true: (discard; @[]) else: @[0])

View File

@@ -0,0 +1,30 @@
#ifndef TCPP_DEFAULT_CTOR_ASSIGNMENT_H
#define TCPP_DEFAULT_CTOR_ASSIGNMENT_H
struct AmbiguousAssign {
int x;
const char* y;
AmbiguousAssign(): x(0), y(nullptr) {}
AmbiguousAssign(int x, const char* y): x(x), y(y) {}
AmbiguousAssign& operator=(int v) {
x = v;
y = nullptr;
return *this;
}
AmbiguousAssign& operator=(const char* s) {
x = 0;
y = s;
return *this;
}
AmbiguousAssign& operator=(const AmbiguousAssign& other) {
x = other.x;
y = other.y;
return *this;
}
};
#endif

View File

@@ -0,0 +1,14 @@
discard """
cmd: "nim cpp $file"
"""
type
AmbiguousAssign {.importcpp, header: "tcpp_default_ctor_assignment.h".} = object
x: cint
y: cstring
proc main =
var xs = newSeq[AmbiguousAssign](3)
doAssert xs.len == 3
main()

View File

@@ -855,3 +855,17 @@ block:
var r = Obj(x: 10)
r.value = 42
doAssert r.x == 42
block: # bug #25949
template loadFile(filename: string): auto =
when nimvm:
staticRead(filename)
else:
"something"
proc roundTrip(): bool =
let content = loadFile("tests/tomls/case.toml")
content == "something"
doAssert roundTrip()