exportc now mangles same as importc, fixes #10578 (#12144)

* fixes #10578
* add tests
* add changelog
* add {.exportcpp.}
This commit is contained in:
Timothee Cour
2019-09-06 03:54:44 -07:00
committed by Andreas Rumpf
parent 8397554315
commit 32769c478b
7 changed files with 76 additions and 34 deletions

View File

@@ -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

View File

@@ -239,6 +239,7 @@ type
sfForward, # symbol is forward declared
sfImportc, # symbol is external; imported
sfExportc, # symbol is exported (under a specified name)
sfMangleCpp, # mangle as cpp (combines with `sfExportc`)
sfVolatile, # variable is volatile
sfRegister, # variable should be placed in a register
sfPure, # object is "pure" that means it has no type-information

View File

@@ -1039,7 +1039,8 @@ proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
result = (sfCompileToCpp in m.module.flags and
sfCompileToCpp notin sym.getModule().flags and
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
m.config.cmd == cmdCompileToCpp)

View File

@@ -19,25 +19,27 @@ const
LastCallConv* = wNoconv
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,
wCompilerProc, wNonReloadable, wCore, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wCodegenDecl,
wCompilerProc, wNonReloadable, wCore, wProcVar, wVarargs, wCompileTime, wMerge,
wBorrow, wImportCompilerProc, wThread,
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wConstructor, wExportNims, wUsed, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
converterPragmas* = procPragmas - {wNoDestroy}
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
wDelegator, wExportNims, wUsed, wPragma}
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
wNodecl, wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
wExportNims, wUsed}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe, wExportNims, wUsed}
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore,
wDiscardable, wGensym, wInject, wDelegator}
iteratorPragmas* = declPragmas + {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
wMagic, wBorrow,
wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
wBoundChecks, wOverflowChecks, wNilChecks, wStyleChecks, wAssertions,
@@ -49,25 +51,25 @@ const
wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental, wThis, wUsed}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wInjectStmt, wExperimental, wThis, wUsed}
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wThread, wAsmNoStackFrame,
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
typePragmas* = declPragmas + {wMagic, wAcyclic,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wPackage}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerProc, wCore, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed, wCursor}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
wIntDefine, wStrDefine, wBoolDefine, wUsed, wCompilerProc, wCore}
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
fieldPragmas* = declPragmas + {
wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
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 != {}:
checkPragmaUse(c.config, key.info, k, ident.s)
case k
of wExportc:
of wExportc, wExportCpp:
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
of wImportc:
let name = getOptionalStr(c, it, "$1")

View File

@@ -42,7 +42,7 @@ type
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
wImportc, wExportc, wExportCpp, wExportNims, wIncompleteStruct, wRequiresInit,
wAlign, wNodecl, wPure, wSideEffect, wHeader,
wNoSideEffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
wCompilerProc, wCore, wProcVar, wBase, wUsed,
@@ -129,7 +129,7 @@ const
"immediate", "constructor", "destructor", "delegator", "override",
"importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "exportnims",
"importcompilerproc", "importc", "exportc", "exportcpp", "exportnims",
"incompletestruct",
"requiresinit", "align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",

9
tests/cpp/mexportc.nim Normal file
View 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
View 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