Fix code generation issues with TNimType.
This is an alternative attempt to fix issue #2841 in a way that does not rely on non-standard C compiler behavior. The underlying problem is that the typeinfo module includes system/hti.nim, but system/hti.nim is also included by system.nim. The result is that the compiler at any given point has two instances of TNimType with the same external name and will generate code either for one or both of them. Code generation for the second version is normally suppressed by using {.importc.}, but that results in a missing type declaration for modules that only use the second version. This happens for modules that import typeinfo, because the the second component of typeinfo.Any has type PNimType = ptr TNimType, which generates a "TNimType *" struct member. The previous solution was to have a typedef for TNimType in nimbase.h; however, this results in duplicate typedefs (specifically, but not only for the code generated for typeinfo.nim). Duplicate typedefs with the same type name are allowed in C++ and C11, but are explicitly forbidden in C89 and C99. Modern versions of gcc and clang accept them anyway, but this is not standard-compliant and may break for other C compilers or older versions of gcc and clang. This patch attempts to fix the issue by making the second component of typeinfo.Nim a pointer instead of a PNimType and casting back and forth as needed. Thus, the second version of TNimType occurs only within the code for typeinfo.nim, where it can be safely omitted.
This commit is contained in:
parent
31ebb11d73
commit
f664c576c2
2 changed files with 15 additions and 9 deletions
|
|
@ -61,7 +61,10 @@ type
|
||||||
## wrapped value and **must not** live longer than
|
## wrapped value and **must not** live longer than
|
||||||
## its wrapped value.
|
## its wrapped value.
|
||||||
value: pointer
|
value: pointer
|
||||||
rawType: PNimType
|
when defined(js):
|
||||||
|
rawType: PNimType
|
||||||
|
else:
|
||||||
|
rawTypePtr: pointer
|
||||||
|
|
||||||
ppointer = ptr pointer
|
ppointer = ptr pointer
|
||||||
pbyteArray = ptr array[0.. 0xffff, int8]
|
pbyteArray = ptr array[0.. 0xffff, int8]
|
||||||
|
|
@ -71,6 +74,14 @@ type
|
||||||
when defined(gogc):
|
when defined(gogc):
|
||||||
elemSize: int
|
elemSize: int
|
||||||
PGenSeq = ptr TGenericSeq
|
PGenSeq = ptr TGenericSeq
|
||||||
|
|
||||||
|
when not defined(js):
|
||||||
|
template rawType(x: Any): PNimType =
|
||||||
|
cast[PNimType](x.rawTypePtr)
|
||||||
|
|
||||||
|
template `rawType=`(x: var Any, p: PNimType) =
|
||||||
|
x.rawTypePtr = cast[pointer](p)
|
||||||
|
|
||||||
{.deprecated: [TAny: Any, TAnyKind: AnyKind].}
|
{.deprecated: [TAny: Any, TAnyKind: AnyKind].}
|
||||||
|
|
||||||
when defined(gogc):
|
when defined(gogc):
|
||||||
|
|
@ -108,7 +119,7 @@ proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =
|
||||||
else:
|
else:
|
||||||
result = n.sons[n.len]
|
result = n.sons[n.len]
|
||||||
|
|
||||||
proc newAny(value: pointer, rawType: PNimType): Any =
|
proc newAny(value: pointer, rawType: PNimType): Any {.inline.} =
|
||||||
result.value = value
|
result.value = value
|
||||||
result.rawType = rawType
|
result.rawType = rawType
|
||||||
|
|
||||||
|
|
@ -126,8 +137,7 @@ proc toAny*[T](x: var T): Any {.inline.} =
|
||||||
## constructs a ``Any`` object from `x`. This captures `x`'s address, so
|
## constructs a ``Any`` object from `x`. This captures `x`'s address, so
|
||||||
## `x` can be modified with its ``Any`` wrapper! The client needs to ensure
|
## `x` can be modified with its ``Any`` wrapper! The client needs to ensure
|
||||||
## that the wrapper **does not** live longer than `x`!
|
## that the wrapper **does not** live longer than `x`!
|
||||||
result.value = addr(x)
|
newAny(addr(x), cast[PNimType](getTypeInfo(x)))
|
||||||
result.rawType = cast[PNimType](getTypeInfo(x))
|
|
||||||
|
|
||||||
proc kind*(x: Any): AnyKind {.inline.} =
|
proc kind*(x: Any): AnyKind {.inline.} =
|
||||||
## get the type kind
|
## get the type kind
|
||||||
|
|
@ -345,7 +355,7 @@ proc `[]`*(x: Any, fieldName: string): Any =
|
||||||
result.value = x.value +!! n.offset
|
result.value = x.value +!! n.offset
|
||||||
result.rawType = n.typ
|
result.rawType = n.typ
|
||||||
elif x.rawType.kind == tyObject and x.rawType.base != nil:
|
elif x.rawType.kind == tyObject and x.rawType.base != nil:
|
||||||
return `[]`(Any(value: x.value, rawType: x.rawType.base), fieldName)
|
return `[]`(newAny(x.value, x.rawType.base), fieldName)
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "invalid field name: " & fieldName)
|
raise newException(ValueError, "invalid field name: " & fieldName)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -418,10 +418,6 @@ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(
|
||||||
# define NIM_EXTERNC
|
# define NIM_EXTERNC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* we have to tinker with TNimType as it's both part of system.nim and
|
|
||||||
typeinfo.nim but system.nim doesn't export it cleanly... */
|
|
||||||
typedef struct TNimType TNimType;
|
|
||||||
|
|
||||||
/* ---------------- platform specific includes ----------------------- */
|
/* ---------------- platform specific includes ----------------------- */
|
||||||
|
|
||||||
/* VxWorks related includes */
|
/* VxWorks related includes */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue