diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim index 1dd481ec0b..fecc6fdd22 100644 --- a/compiler/sizealignoffsetimpl.nim +++ b/compiler/sizealignoffsetimpl.nim @@ -394,9 +394,10 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = accum.offset = 1 computeObjectOffsetsFoldFunction(conf, typ.n, false, accum) let paddingAtEnd = int16(accum.finish()) - if typ.sym != nil and - typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc} and - tfCompleteStruct notin typ.flags: + if (typ.sym != nil and + typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc} and + tfCompleteStruct notin typ.flags) or + tfIncompleteStruct in typ.flags: typ.size = szUnknownSize typ.align = szUnknownSize typ.paddingAtEnd = szUnknownSize diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index dd8b8365ca..56458f077d 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -786,8 +786,12 @@ proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = c.freeTemp(tmp2) c.freeTemp(tmp3) -template sizeOfLikeMsg(name): string = - "'$1' requires '.importc' types to be '.completeStruct'" % [name] +template sizeOfLikeMsg(name, incompleteStruct): string = + block: + if incompleteStruct: + "'$1' cannot be used with '.incompleteStruct' types" % [name] + else: + "'$1' requires '.importc' types to be '.completeStruct'" % [name] proc genNarrow(c: PCtx; n: PNode; dest: TDest) = let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) @@ -1476,11 +1480,14 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag else: globalError(c.config, n.info, "expandToAst requires a call expression") of mSizeOf: - globalError(c.config, n.info, sizeOfLikeMsg("sizeof")) + let arg = n[1].typ.skipTypes({tyTypeDesc}) + globalError(c.config, n.info, sizeOfLikeMsg("sizeof", tfIncompleteStruct in arg.flags)) of mAlignOf: - globalError(c.config, n.info, sizeOfLikeMsg("alignof")) + let arg = n[1].typ.skipTypes({tyTypeDesc}) + globalError(c.config, n.info, sizeOfLikeMsg("alignof", tfIncompleteStruct in arg.flags)) of mOffsetOf: - globalError(c.config, n.info, sizeOfLikeMsg("offsetof")) + let arg = n[1].typ.skipTypes({tyTypeDesc}) + globalError(c.config, n.info, sizeOfLikeMsg("offsetof", tfIncompleteStruct in arg.flags)) of mRunnableExamples: discard "just ignore any call to runnableExamples" of mDestroy, mTrace: discard "ignore calls to the default destructor" diff --git a/doc/manual.md b/doc/manual.md index 0970d0f5b8..046ef33c4b 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -7996,6 +7996,9 @@ underlying C `struct`:c: in a `sizeof` expression: pure, incompleteStruct.} = object ``` +Attempting to use `sizeof` on an `incompleteStruct` type at compile-time +will error with "'sizeof' cannot be used with '.incompleteStruct' types". + CompleteStruct pragma --------------------- diff --git a/tests/misc/tsizeof_incompleteStruct.nim b/tests/misc/tsizeof_incompleteStruct.nim new file mode 100644 index 0000000000..f3256ccc82 --- /dev/null +++ b/tests/misc/tsizeof_incompleteStruct.nim @@ -0,0 +1,12 @@ +discard """ +errormsg: "'sizeof' cannot be used with '.incompleteStruct' types" +line: 10 +""" + +type + MyStruct {.incompleteStruct.} = object + field: int + +const i = sizeof(MyStruct) + +echo i