* hangle static generic params when used in the importcpp pragma * importcpp works for generic types with fields; fixes #6415 * revert a too agressive safety check that ended up breaking the tests
This commit is contained in:
parent
63c28b973e
commit
cbd059aa85
4 changed files with 71 additions and 6 deletions
|
|
@ -25,3 +25,8 @@
|
||||||
### Compiler changes
|
### Compiler changes
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
- The `importcpp` pragma now allows importing the listed fields of generic
|
||||||
|
C++ types. Support for numeric parameters have also been added through
|
||||||
|
the use of `static[T]` types.
|
||||||
|
(#6415)
|
||||||
|
|
|
||||||
|
|
@ -617,8 +617,10 @@ proc scanCppGenericSlot(pat: string, cursor, outIdx, outStars: var int): bool =
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
||||||
# XXX: we should catch this earlier and report it as a semantic error
|
# Make sure the index refers to one of the generic params of the type.
|
||||||
if idx >= typ.len: internalError "invalid apostrophe type parameter index"
|
# XXX: we should catch this earlier and report it as a semantic error.
|
||||||
|
if idx >= typ.len:
|
||||||
|
internalError "invalid apostrophe type parameter index"
|
||||||
|
|
||||||
result = typ.sons[idx]
|
result = typ.sons[idx]
|
||||||
for i in 1..stars:
|
for i in 1..stars:
|
||||||
|
|
@ -820,6 +822,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||||
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
||||||
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
||||||
result.add(~"void")
|
result.add(~"void")
|
||||||
|
elif typeInSlot.kind == tyStatic:
|
||||||
|
internalAssert typeInSlot.n != nil
|
||||||
|
result.add typeInSlot.n.renderTree
|
||||||
else:
|
else:
|
||||||
result.add getTypeDescAux(m, typeInSlot, check)
|
result.add getTypeDescAux(m, typeInSlot, check)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -632,16 +632,18 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
else:
|
else:
|
||||||
typ = semTypeNode(c, n.sons[length-2], nil)
|
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||||
propagateToOwner(rectype, typ)
|
propagateToOwner(rectype, typ)
|
||||||
let rec = rectype.sym
|
var fieldOwner = if c.inGenericContext > 0: c.getCurrOwner
|
||||||
|
else: rectype.sym
|
||||||
for i in countup(0, sonsLen(n)-3):
|
for i in countup(0, sonsLen(n)-3):
|
||||||
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||||
suggestSym(n.sons[i].info, f, c.graph.usageSym)
|
suggestSym(n.sons[i].info, f, c.graph.usageSym)
|
||||||
f.typ = typ
|
f.typ = typ
|
||||||
f.position = pos
|
f.position = pos
|
||||||
if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and
|
if fieldOwner != nil and
|
||||||
(f.loc.r == nil):
|
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
||||||
|
f.loc.r == nil:
|
||||||
f.loc.r = rope(f.name.s)
|
f.loc.r = rope(f.name.s)
|
||||||
f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags)
|
f.flags = f.flags + ({sfImportc, sfExportc} * fieldOwner.flags)
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if containsOrIncl(check, f.name.id):
|
if containsOrIncl(check, f.name.id):
|
||||||
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
||||||
|
|
|
||||||
53
tests/statictypes/tstaticimportcpp.nim
Normal file
53
tests/statictypes/tstaticimportcpp.nim
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
discard """
|
||||||
|
targets: "cpp"
|
||||||
|
output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest"
|
||||||
|
"""
|
||||||
|
|
||||||
|
{.emit: """
|
||||||
|
|
||||||
|
template <int N, class T>
|
||||||
|
struct GenericIntType {
|
||||||
|
T data[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct GenericTType {
|
||||||
|
T field;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SimpleStruct {
|
||||||
|
int field;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
""" .}
|
||||||
|
|
||||||
|
type
|
||||||
|
GenericIntType {.importcpp: "GenericIntType<'0, '1>".} [N: static[int]; T] = object
|
||||||
|
data: array[N, T]
|
||||||
|
|
||||||
|
GenericTType {.importcpp: "GenericTType<'0>".} [T] = object
|
||||||
|
field: T
|
||||||
|
|
||||||
|
GenInt4 = GenericIntType[4, int]
|
||||||
|
|
||||||
|
SimpleStruct {.importcpp: "SimpleStruct"} = object
|
||||||
|
field: int
|
||||||
|
|
||||||
|
var
|
||||||
|
a = GenInt4()
|
||||||
|
b = SimpleStruct()
|
||||||
|
c = GenericTType[float]()
|
||||||
|
d = SimpleStruct(field: 15)
|
||||||
|
e = GenericTType[string](field: "test")
|
||||||
|
|
||||||
|
a.data[2] = 10
|
||||||
|
b.field = 5
|
||||||
|
c.field = 1.2
|
||||||
|
|
||||||
|
echo a.data
|
||||||
|
echo b.field
|
||||||
|
echo c.field
|
||||||
|
echo d.field
|
||||||
|
echo e.field
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue