diff options
author | Grzegorz Adam Hankiewicz <gradha@imap.cc> | 2014-02-21 00:32:28 +0100 |
---|---|---|
committer | Grzegorz Adam Hankiewicz <gradha@imap.cc> | 2014-02-21 00:32:28 +0100 |
commit | adb390af4bfbb3549672280007e9c46bf7a223c2 (patch) | |
tree | 4099a8066940c1a8b79a831618fce1ef8d7bc455 /compiler | |
parent | 1a6d05515ff96e8bba294b352493cb7da2794a96 (diff) | |
download | Nim-adb390af4bfbb3549672280007e9c46bf7a223c2.tar.gz |
Checks that exported symbols are valid C identifiers. Refs #800.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/msgs.nim | 3 | ||||
-rw-r--r-- | compiler/pragmas.nim | 25 |
2 files changed, 24 insertions, 4 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 0140d1ac4..8c41a8191 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -105,7 +105,7 @@ type errThreadvarCannotInit, errWrongSymbolX, errIllegalCaptureX, errXCannotBeClosure, errXMustBeCompileTime, errCannotInferTypeOfTheLiteral, - errUser, + errBadExport, errUser warnCannotOpenFile, warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, warnDeprecated, warnConfigDeprecated, @@ -350,6 +350,7 @@ const errXCannotBeClosure: "'$1' cannot have 'closure' calling convention", errXMustBeCompileTime: "'$1' can only be used in compile-time context", errCannotInferTypeOfTheLiteral: "cannot infer the type of the $1", + errBadExport: "invalid exported symbol, $1", errUser: "$1", warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]", warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d9ed50cfe..6e21a85b9 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -97,8 +97,27 @@ proc makeExternImport(s: PSym, extname: string) = incl(s.flags, sfImportc) excl(s.flags, sfForward) -proc makeExternExport(s: PSym, extname: string) = +const invalidIdentChars = AllChars - IdentChars + +proc validateExternName(s: PSym, info: TLineInfo) = + ## Validates that the symbol name in s.loc.r is a valid C identifier. + ## + ## Valid identifiers are those alphanumeric including the underscore not + ## starting with a number. If the check fails, a friendly error will be + ## displayed to the user. + let target = ropeToStr(s.loc.r) + if target.len < 1: + localError(info, errBadExport, "can't be zero length") + if not (target[0] in IdentStartChars): + localError(info, errBadExport, "'" & target & "' can't start with a number") + if not target.allCharsInSet(IdentChars): + let pos = target.find(invalidIdentChars, 1) + localError(info, errBadExport, "'" & target & + "' contains bad character at byte " & $pos) + +proc makeExternExport(s: PSym, extname: string, info: TLineInfo) = setExternName(s, extname) + validateExternName(s, info) incl(s.flags, sfExportc) proc processImportCompilerProc(s: PSym, extname: string) = @@ -515,7 +534,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if k in validPragmas: case k of wExportc: - makeExternExport(sym, getOptionalStr(c, it, "$1")) + makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info) incl(sym.flags, sfUsed) # avoid wrong hints of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1")) of wImportCompilerProc: @@ -601,7 +620,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, processDynLib(c, it, sym) of wCompilerproc: noVal(it) # compilerproc may not get a string! - makeExternExport(sym, "$1") + makeExternExport(sym, "$1", it.info) incl(sym.flags, sfCompilerProc) incl(sym.flags, sfUsed) # suppress all those stupid warnings registerCompilerProc(sym) |