* fixes #10578 * add tests * add changelog * add {.exportcpp.}
This commit is contained in:
parent
8397554315
commit
32769c478b
7 changed files with 76 additions and 34 deletions
|
|
@ -31,6 +31,8 @@ type
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `exportc` now uses C instead of C++ mangling with `nim cpp`, matching behavior of `importc`, see #10578
|
||||||
|
Use the new `exportcpp` to mangle as C++ when using `nim cpp`.
|
||||||
|
|
||||||
### Breaking changes in the compiler
|
### Breaking changes in the compiler
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ type
|
||||||
sfForward, # symbol is forward declared
|
sfForward, # symbol is forward declared
|
||||||
sfImportc, # symbol is external; imported
|
sfImportc, # symbol is external; imported
|
||||||
sfExportc, # symbol is exported (under a specified name)
|
sfExportc, # symbol is exported (under a specified name)
|
||||||
|
sfMangleCpp, # mangle as cpp (combines with `sfExportc`)
|
||||||
sfVolatile, # variable is volatile
|
sfVolatile, # variable is volatile
|
||||||
sfRegister, # variable should be placed in a register
|
sfRegister, # variable should be placed in a register
|
||||||
sfPure, # object is "pure" that means it has no type-information
|
sfPure, # object is "pure" that means it has no type-information
|
||||||
|
|
|
||||||
|
|
@ -1039,7 +1039,8 @@ proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
|
||||||
result = (sfCompileToCpp in m.module.flags and
|
result = (sfCompileToCpp in m.module.flags and
|
||||||
sfCompileToCpp notin sym.getModule().flags and
|
sfCompileToCpp notin sym.getModule().flags and
|
||||||
m.config.cmd != cmdCompileToCpp) or (
|
m.config.cmd != cmdCompileToCpp) or (
|
||||||
sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
|
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
|
||||||
|
sym.flags * {sfImportc, sfExportc} != {} and
|
||||||
sym.magic == mNone and
|
sym.magic == mNone and
|
||||||
m.config.cmd == cmdCompileToCpp)
|
m.config.cmd == cmdCompileToCpp)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,27 @@ const
|
||||||
LastCallConv* = wNoconv
|
LastCallConv* = wNoconv
|
||||||
|
|
||||||
const
|
const
|
||||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
declPragmas = {wImportc, wImportObjC, wImportCpp, wExportc, wExportCpp,
|
||||||
|
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
|
||||||
|
## common pragmas for declarations, to a good approximation
|
||||||
|
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||||
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
||||||
wCompilerProc, wNonReloadable, wCore, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
wCompilerProc, wNonReloadable, wCore, wProcVar, wVarargs, wCompileTime, wMerge,
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wImportCompilerProc, wThread,
|
||||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wCodegenDecl,
|
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
|
||||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||||
wConstructor, wExportNims, wUsed, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
||||||
converterPragmas* = procPragmas - {wNoDestroy}
|
converterPragmas* = procPragmas - {wNoDestroy}
|
||||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
|
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
|
||||||
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
||||||
wDelegator, wExportNims, wUsed, wPragma}
|
wDelegator, wExportNims, wUsed, wPragma}
|
||||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
|
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||||
wNodecl, wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
|
wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore,
|
||||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
|
wDiscardable, wGensym, wInject, wDelegator}
|
||||||
wExportNims, wUsed}
|
iteratorPragmas* = declPragmas + {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
|
||||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
|
wMagic, wBorrow,
|
||||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
wDiscardable, wGensym, wInject, wRaises,
|
||||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
wTags, wLocks, wGcSafe}
|
||||||
wTags, wLocks, wGcSafe, wExportNims, wUsed}
|
|
||||||
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
|
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
|
||||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
||||||
wBoundChecks, wOverflowChecks, wNilChecks, wStyleChecks, wAssertions,
|
wBoundChecks, wOverflowChecks, wNilChecks, wStyleChecks, wAssertions,
|
||||||
|
|
@ -49,25 +51,25 @@ const
|
||||||
wDeprecated,
|
wDeprecated,
|
||||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||||
wInjectStmt, wDeprecated, wExperimental, wThis, wUsed}
|
wInjectStmt, wExperimental, wThis, wUsed}
|
||||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||||
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
||||||
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
|
wThread, wAsmNoStackFrame,
|
||||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl}
|
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
|
||||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
typePragmas* = declPragmas + {wMagic, wAcyclic,
|
||||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wExtern, wShallow,
|
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
|
||||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
wIncompleteStruct, wByCopy, wByRef,
|
||||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||||
wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wPackage}
|
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
|
||||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
fieldPragmas* = declPragmas + {
|
||||||
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
|
wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
|
||||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
|
||||||
wMagic, wHeader, wDeprecated, wCompilerProc, wCore, wDynlib, wExtern,
|
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
|
||||||
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
wNoInit, wCompileTime, wGlobal,
|
||||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed, wCursor}
|
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor}
|
||||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
constPragmas* = declPragmas + {wHeader, wMagic,
|
||||||
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
wGensym, wInject,
|
||||||
wIntDefine, wStrDefine, wBoolDefine, wUsed, wCompilerProc, wCore}
|
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
||||||
wThread, wRaises, wLocks, wTags, wGcSafe}
|
wThread, wRaises, wLocks, wTags, wGcSafe}
|
||||||
|
|
@ -775,8 +777,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||||
checkPragmaUse(c.config, key.info, k, ident.s)
|
checkPragmaUse(c.config, key.info, k, ident.s)
|
||||||
case k
|
case k
|
||||||
of wExportc:
|
of wExportc, wExportCpp:
|
||||||
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
|
if k == wExportCpp:
|
||||||
|
if c.config.cmd != cmdCompileToCpp:
|
||||||
|
localError(c.config, it.info, "exportcpp requires `nim cpp`, got " & $c.config.cmd)
|
||||||
|
else:
|
||||||
|
incl(sym.flags, sfMangleCpp)
|
||||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||||
of wImportc:
|
of wImportc:
|
||||||
let name = getOptionalStr(c, it, "$1")
|
let name = getOptionalStr(c, it, "$1")
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ type
|
||||||
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
|
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
|
||||||
wImportCpp, wImportObjC,
|
wImportCpp, wImportObjC,
|
||||||
wImportCompilerProc,
|
wImportCompilerProc,
|
||||||
wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
|
wImportc, wExportc, wExportCpp, wExportNims, wIncompleteStruct, wRequiresInit,
|
||||||
wAlign, wNodecl, wPure, wSideEffect, wHeader,
|
wAlign, wNodecl, wPure, wSideEffect, wHeader,
|
||||||
wNoSideEffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
|
wNoSideEffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
|
||||||
wCompilerProc, wCore, wProcVar, wBase, wUsed,
|
wCompilerProc, wCore, wProcVar, wBase, wUsed,
|
||||||
|
|
@ -129,7 +129,7 @@ const
|
||||||
|
|
||||||
"immediate", "constructor", "destructor", "delegator", "override",
|
"immediate", "constructor", "destructor", "delegator", "override",
|
||||||
"importcpp", "importobjc",
|
"importcpp", "importobjc",
|
||||||
"importcompilerproc", "importc", "exportc", "exportnims",
|
"importcompilerproc", "importc", "exportc", "exportcpp", "exportnims",
|
||||||
"incompletestruct",
|
"incompletestruct",
|
||||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
||||||
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
|
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
|
||||||
|
|
|
||||||
9
tests/cpp/mexportc.nim
Normal file
9
tests/cpp/mexportc.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{.used.} # ideally, would not be needed
|
||||||
|
|
||||||
|
var fun0 {.exportc.} = 10
|
||||||
|
proc fun1() {.exportc.} = discard
|
||||||
|
proc fun2() {.exportc: "$1".} = discard
|
||||||
|
proc fun3() {.exportc: "fun3Bis".} = discard
|
||||||
|
|
||||||
|
when defined cpp:
|
||||||
|
proc funx1() {.exportcpp.} = discard
|
||||||
22
tests/cpp/texportc.nim
Normal file
22
tests/cpp/texportc.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
discard """
|
||||||
|
targets: "c cpp"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var fun0 {.importc.}: int
|
||||||
|
proc fun1() {.importc.}
|
||||||
|
proc fun2() {.importc: "$1".}
|
||||||
|
proc fun3() {.importc: "fun3Bis".}
|
||||||
|
|
||||||
|
when defined cpp:
|
||||||
|
# proc funx1() {.importcpp.} # this does not work yet
|
||||||
|
proc funx1() {.importc: "_Z5funx1v".}
|
||||||
|
|
||||||
|
doAssert fun0 == 10
|
||||||
|
fun1()
|
||||||
|
fun2()
|
||||||
|
fun3()
|
||||||
|
|
||||||
|
when defined cpp:
|
||||||
|
funx1()
|
||||||
|
|
||||||
|
import ./mexportc
|
||||||
Loading…
Add table
Add a link
Reference in a new issue