compiler: better error messages (#5613)
This commit is contained in:
parent
481d8ba24a
commit
d02486aa48
8 changed files with 37 additions and 29 deletions
|
|
@ -15,17 +15,28 @@ import
|
||||||
|
|
||||||
proc ensureNoMissingOrUnusedSymbols(scope: PScope)
|
proc ensureNoMissingOrUnusedSymbols(scope: PScope)
|
||||||
|
|
||||||
proc considerQuotedIdent*(n: PNode): PIdent =
|
proc noidentError(n, origin: PNode) =
|
||||||
|
var m = ""
|
||||||
|
if origin != nil:
|
||||||
|
m.add "in expression '" & origin.renderTree & "': "
|
||||||
|
m.add "identifier expected, but found '" & n.renderTree & "'"
|
||||||
|
localError(n.info, m)
|
||||||
|
|
||||||
|
proc considerQuotedIdent*(n: PNode, origin: PNode = nil): PIdent =
|
||||||
## Retrieve a PIdent from a PNode, taking into account accent nodes.
|
## Retrieve a PIdent from a PNode, taking into account accent nodes.
|
||||||
|
## ``origin`` can be nil. If it is not nil, it is used for a better
|
||||||
|
## error message.
|
||||||
|
template handleError(n, origin: PNode) =
|
||||||
|
noidentError(n, origin)
|
||||||
|
result = getIdent"<Error>"
|
||||||
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkIdent: result = n.ident
|
of nkIdent: result = n.ident
|
||||||
of nkSym: result = n.sym.name
|
of nkSym: result = n.sym.name
|
||||||
of nkAccQuoted:
|
of nkAccQuoted:
|
||||||
case n.len
|
case n.len
|
||||||
of 0:
|
of 0: handleError(n, origin)
|
||||||
localError(n.info, errIdentifierExpected, renderTree(n))
|
of 1: result = considerQuotedIdent(n.sons[0], origin)
|
||||||
result = getIdent"<Error>"
|
|
||||||
of 1: result = considerQuotedIdent(n.sons[0])
|
|
||||||
else:
|
else:
|
||||||
var id = ""
|
var id = ""
|
||||||
for i in 0.. <n.len:
|
for i in 0.. <n.len:
|
||||||
|
|
@ -33,14 +44,11 @@ proc considerQuotedIdent*(n: PNode): PIdent =
|
||||||
case x.kind
|
case x.kind
|
||||||
of nkIdent: id.add(x.ident.s)
|
of nkIdent: id.add(x.ident.s)
|
||||||
of nkSym: id.add(x.sym.name.s)
|
of nkSym: id.add(x.sym.name.s)
|
||||||
else:
|
else: handleError(n, origin)
|
||||||
localError(n.info, errIdentifierExpected, renderTree(n))
|
|
||||||
return getIdent"<Error>"
|
|
||||||
result = getIdent(id)
|
result = getIdent(id)
|
||||||
of nkOpenSymChoice, nkClosedSymChoice: result = n.sons[0].sym.name
|
of nkOpenSymChoice, nkClosedSymChoice: result = n.sons[0].sym.name
|
||||||
else:
|
else:
|
||||||
localError(n.info, errIdentifierExpected, renderTree(n))
|
handleError(n, origin)
|
||||||
result = getIdent"<Error>"
|
|
||||||
|
|
||||||
template addSym*(scope: PScope, s: PSym) =
|
template addSym*(scope: PScope, s: PSym) =
|
||||||
strTableAdd(scope.symbols, s)
|
strTableAdd(scope.symbols, s)
|
||||||
|
|
@ -353,7 +361,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
if n.sons[1].kind == nkIdent:
|
if n.sons[1].kind == nkIdent:
|
||||||
ident = n.sons[1].ident
|
ident = n.sons[1].ident
|
||||||
elif n.sons[1].kind == nkAccQuoted:
|
elif n.sons[1].kind == nkAccQuoted:
|
||||||
ident = considerQuotedIdent(n.sons[1])
|
ident = considerQuotedIdent(n.sons[1], n)
|
||||||
if ident != nil:
|
if ident != nil:
|
||||||
if o.m == c.module:
|
if o.m == c.module:
|
||||||
# a module may access its private members:
|
# a module may access its private members:
|
||||||
|
|
@ -363,8 +371,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
else:
|
else:
|
||||||
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
|
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
|
||||||
else:
|
else:
|
||||||
localError(n.sons[1].info, errIdentifierExpected,
|
noidentError(n.sons[1], n)
|
||||||
renderTree(n.sons[1]))
|
|
||||||
result = errorSym(c, n.sons[1])
|
result = errorSym(c, n.sons[1])
|
||||||
of nkClosedSymChoice, nkOpenSymChoice:
|
of nkClosedSymChoice, nkOpenSymChoice:
|
||||||
o.mode = oimSymChoice
|
o.mode = oimSymChoice
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ proc semOpAux(c: PContext, n: PNode) =
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||||
var info = a.sons[0].info
|
var info = a.sons[0].info
|
||||||
a.sons[0] = newIdentNode(considerQuotedIdent(a.sons[0]), info)
|
a.sons[0] = newIdentNode(considerQuotedIdent(a.sons[0], a), info)
|
||||||
a.sons[1] = semExprWithType(c, a.sons[1], flags)
|
a.sons[1] = semExprWithType(c, a.sons[1], flags)
|
||||||
a.typ = a.sons[1].typ
|
a.typ = a.sons[1].typ
|
||||||
else:
|
else:
|
||||||
|
|
@ -1076,7 +1076,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
|
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0], flags+{efDetermineType})
|
n.sons[0] = semExprWithType(c, n.sons[0], flags+{efDetermineType})
|
||||||
#restoreOldStyleType(n.sons[0])
|
#restoreOldStyleType(n.sons[0])
|
||||||
var i = considerQuotedIdent(n.sons[1])
|
var i = considerQuotedIdent(n.sons[1], n)
|
||||||
var ty = n.sons[0].typ
|
var ty = n.sons[0].typ
|
||||||
var f: PSym = nil
|
var f: PSym = nil
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -1160,7 +1160,7 @@ proc dotTransformation(c: PContext, n: PNode): PNode =
|
||||||
addSon(result, n.sons[1])
|
addSon(result, n.sons[1])
|
||||||
addSon(result, copyTree(n[0]))
|
addSon(result, copyTree(n[0]))
|
||||||
else:
|
else:
|
||||||
var i = considerQuotedIdent(n.sons[1])
|
var i = considerQuotedIdent(n.sons[1], n)
|
||||||
result = newNodeI(nkDotCall, n.info)
|
result = newNodeI(nkDotCall, n.info)
|
||||||
result.flags.incl nfDotField
|
result.flags.incl nfDotField
|
||||||
addSon(result, newIdentNode(i, n[1].info))
|
addSon(result, newIdentNode(i, n[1].info))
|
||||||
|
|
@ -1280,7 +1280,7 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
c.p.bracketExpr = oldBracketExpr
|
c.p.bracketExpr = oldBracketExpr
|
||||||
|
|
||||||
proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
|
proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
|
||||||
var id = considerQuotedIdent(a[1])
|
var id = considerQuotedIdent(a[1], a)
|
||||||
var setterId = newIdentNode(getIdent(id.s & '='), n.info)
|
var setterId = newIdentNode(getIdent(id.s & '='), n.info)
|
||||||
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
|
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
|
||||||
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
|
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
|
||||||
|
|
@ -1529,7 +1529,7 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
|
var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
|
||||||
if m != nil and m.kind == skModule:
|
if m != nil and m.kind == skModule:
|
||||||
let ident = considerQuotedIdent(n[1])
|
let ident = considerQuotedIdent(n[1], n)
|
||||||
if m == c.module:
|
if m == c.module:
|
||||||
result = strTableGet(c.topLevelScope.symbols, ident)
|
result = strTableGet(c.topLevelScope.symbols, ident)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1548,7 +1548,7 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
# we replace this node by a 'true' or 'false' node:
|
# we replace this node by a 'true' or 'false' node:
|
||||||
result = newIntNode(nkIntLit, 0)
|
result = newIntNode(nkIntLit, 0)
|
||||||
if not onlyCurrentScope and considerQuotedIdent(n[0]).s == "defined":
|
if not onlyCurrentScope and considerQuotedIdent(n[0], n).s == "defined":
|
||||||
if n.sons[1].kind != nkIdent:
|
if n.sons[1].kind != nkIdent:
|
||||||
localError(n.info, "obsolete usage of 'defined', use 'declared' instead")
|
localError(n.info, "obsolete usage of 'defined', use 'declared' instead")
|
||||||
elif condsyms.isDefined(n.sons[1].ident):
|
elif condsyms.isDefined(n.sons[1].ident):
|
||||||
|
|
@ -2097,7 +2097,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
if it.kind != nkExprColonExpr:
|
if it.kind != nkExprColonExpr:
|
||||||
localError(n.info, errNamedExprExpected)
|
localError(n.info, errNamedExprExpected)
|
||||||
break
|
break
|
||||||
let id = considerQuotedIdent(it.sons[0])
|
let id = considerQuotedIdent(it.sons[0], it)
|
||||||
|
|
||||||
if containsOrIncl(ids, id.id):
|
if containsOrIncl(ids, id.id):
|
||||||
localError(it.info, errFieldInitTwice, id.s)
|
localError(it.info, errFieldInitTwice, id.s)
|
||||||
|
|
|
||||||
|
|
@ -160,10 +160,11 @@ proc discardCheck(c: PContext, result: PNode) =
|
||||||
else:
|
else:
|
||||||
var n = result
|
var n = result
|
||||||
while n.kind in skipForDiscardable: n = n.lastSon
|
while n.kind in skipForDiscardable: n = n.lastSon
|
||||||
|
var s = "expression '" & $n & "' is of type '" &
|
||||||
|
result.typ.typeToString & "' and has to be discarded"
|
||||||
if result.typ.kind == tyProc:
|
if result.typ.kind == tyProc:
|
||||||
localError(n.info, "value of type '" & result.typ.typeToString & "' has to be discarded; for a function call use ()")
|
s.add "; for a function call use ()"
|
||||||
else:
|
localError(n.info, s)
|
||||||
localError(n.info, errDiscardValueX, result.typ.typeToString)
|
|
||||||
|
|
||||||
proc semIf(c: PContext, n: PNode): PNode =
|
proc semIf(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
discard """
|
discard """
|
||||||
line: 10
|
line: 10
|
||||||
errormsg: "value of type 'bool' has to be discarded"
|
errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc p =
|
proc p =
|
||||||
var f: TFile
|
var f: File
|
||||||
echo "hi"
|
echo "hi"
|
||||||
|
|
||||||
open(f, "arg.txt")
|
open(f, "arg.txt")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "value of type 'string' has to be discarded"
|
errormsg: '''expression '"invalid"' is of type 'string' and has to be discarded'''
|
||||||
line: 12
|
line: 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "value of type 'bool' has to be discarded"
|
errormsg: "expression 'true' is of type 'bool' and has to be discarded"
|
||||||
line: 13
|
line: 13
|
||||||
file: "tdont_show_system.nim"
|
file: "tdont_show_system.nim"
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
line: 10
|
line: 10
|
||||||
errormsg: "value of type 'string' has to be discarded"
|
errormsg: "expression 'result[1 .. -(len(result), 1)]' is of type 'string' and has to be discarded"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# bug #578
|
# bug #578
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tstmtexp.nim"
|
file: "tstmtexp.nim"
|
||||||
line: 8
|
line: 8
|
||||||
errormsg: "value of type 'int literal(5)' has to be discarded"
|
errormsg: "expression '5' is of type 'int literal(5)' and has to be discarded"
|
||||||
"""
|
"""
|
||||||
# Test 3
|
# Test 3
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue