improve the error message for 'attempt to redefine X'; fixes #447
This commit is contained in:
parent
3467c455c0
commit
539fc5d58b
4 changed files with 29 additions and 18 deletions
|
|
@ -549,7 +549,8 @@ proc strTableAdd*(t: var TStrTable, n: PSym) =
|
||||||
strTableRawInsert(t.data, n)
|
strTableRawInsert(t.data, n)
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.discardable.} =
|
proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
|
||||||
|
onConflictKeepOld = false): PSym =
|
||||||
# returns true if n is already in the string table:
|
# returns true if n is already in the string table:
|
||||||
# It is essential that `n` is written nevertheless!
|
# It is essential that `n` is written nevertheless!
|
||||||
# This way the newest redefinition is picked by the semantic analyses!
|
# This way the newest redefinition is picked by the semantic analyses!
|
||||||
|
|
@ -564,13 +565,13 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
|
||||||
# So it is possible the very same sym is added multiple
|
# So it is possible the very same sym is added multiple
|
||||||
# times to the symbol table which we allow here with the 'it == n' check.
|
# times to the symbol table which we allow here with the 'it == n' check.
|
||||||
if it.name.id == n.name.id:
|
if it.name.id == n.name.id:
|
||||||
if it == n: return false
|
if it == n: return nil
|
||||||
replaceSlot = h
|
replaceSlot = h
|
||||||
h = nextTry(h, high(t.data))
|
h = nextTry(h, high(t.data))
|
||||||
if replaceSlot >= 0:
|
if replaceSlot >= 0:
|
||||||
if not onConflictKeepOld:
|
if not onConflictKeepOld:
|
||||||
t.data[replaceSlot] = n # overwrite it with newer definition!
|
t.data[replaceSlot] = n # overwrite it with newer definition!
|
||||||
return true # found it
|
return t.data[replaceSlot] # found it
|
||||||
elif mustRehash(len(t.data), t.counter):
|
elif mustRehash(len(t.data), t.counter):
|
||||||
strTableEnlarge(t)
|
strTableEnlarge(t)
|
||||||
strTableRawInsert(t.data, n)
|
strTableRawInsert(t.data, n)
|
||||||
|
|
@ -578,7 +579,11 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
|
||||||
assert(t.data[h] == nil)
|
assert(t.data[h] == nil)
|
||||||
t.data[h] = n
|
t.data[h] = n
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
result = false
|
result = nil
|
||||||
|
|
||||||
|
proc strTableIncl*(t: var TStrTable, n: PSym;
|
||||||
|
onConflictKeepOld = false): bool {.discardable.} =
|
||||||
|
result = strTableInclReportConflict(t, n, onConflictKeepOld) != nil
|
||||||
|
|
||||||
proc strTableGet*(t: TStrTable, name: PIdent): PSym =
|
proc strTableGet*(t: TStrTable, name: PIdent): PSym =
|
||||||
var h: Hash = name.h and high(t.data)
|
var h: Hash = name.h and high(t.data)
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,8 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
|
||||||
template addSym*(scope: PScope, s: PSym) =
|
template addSym*(scope: PScope, s: PSym) =
|
||||||
strTableAdd(scope.symbols, s)
|
strTableAdd(scope.symbols, s)
|
||||||
|
|
||||||
proc addUniqueSym*(scope: PScope, s: PSym): bool =
|
proc addUniqueSym*(scope: PScope, s: PSym): PSym =
|
||||||
result = not strTableIncl(scope.symbols, s)
|
result = strTableInclReportConflict(scope.symbols, s)
|
||||||
|
|
||||||
proc openScope*(c: PContext): PScope {.discardable.} =
|
proc openScope*(c: PContext): PScope {.discardable.} =
|
||||||
result = PScope(parent: c.currentScope,
|
result = PScope(parent: c.currentScope,
|
||||||
|
|
@ -177,24 +177,30 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
|
||||||
message(c.config, s.info, hintXDeclaredButNotUsed, getSymRepr(c.config, s))
|
message(c.config, s.info, hintXDeclaredButNotUsed, getSymRepr(c.config, s))
|
||||||
s = nextIter(it, scope.symbols)
|
s = nextIter(it, scope.symbols)
|
||||||
|
|
||||||
proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string) =
|
proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string;
|
||||||
|
conflictsWith: TLineInfo) =
|
||||||
if c.config.cmd != cmdInteractive:
|
if c.config.cmd != cmdInteractive:
|
||||||
localError(c.config, info, "redefinition of '$1'" % s)
|
localError(c.config, info,
|
||||||
|
"redefinition of '$1'; previous declaration here: $2" %
|
||||||
|
[s, c.config $ conflictsWith])
|
||||||
|
|
||||||
proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) =
|
proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) =
|
||||||
if not c.currentScope.addUniqueSym(sym):
|
let conflict = c.currentScope.addUniqueSym(sym)
|
||||||
wrongRedefinition(c, info, sym.name.s)
|
if conflict != nil:
|
||||||
|
wrongRedefinition(c, info, sym.name.s, conflict.info)
|
||||||
|
|
||||||
proc addDecl*(c: PContext, sym: PSym) =
|
proc addDecl*(c: PContext, sym: PSym) =
|
||||||
if not c.currentScope.addUniqueSym(sym):
|
let conflict = c.currentScope.addUniqueSym(sym)
|
||||||
wrongRedefinition(c, sym.info, sym.name.s)
|
if conflict != nil:
|
||||||
|
wrongRedefinition(c, sym.info, sym.name.s, conflict.info)
|
||||||
|
|
||||||
proc addPrelimDecl*(c: PContext, sym: PSym) =
|
proc addPrelimDecl*(c: PContext, sym: PSym) =
|
||||||
discard c.currentScope.addUniqueSym(sym)
|
discard c.currentScope.addUniqueSym(sym)
|
||||||
|
|
||||||
proc addDeclAt*(c: PContext; scope: PScope, sym: PSym) =
|
proc addDeclAt*(c: PContext; scope: PScope, sym: PSym) =
|
||||||
if not scope.addUniqueSym(sym):
|
let conflict = scope.addUniqueSym(sym)
|
||||||
wrongRedefinition(c, sym.info, sym.name.s)
|
if conflict != nil:
|
||||||
|
wrongRedefinition(c, sym.info, sym.name.s, conflict.info)
|
||||||
|
|
||||||
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
|
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||||
if sfExported in sym.flags:
|
if sfExported in sym.flags:
|
||||||
|
|
@ -212,7 +218,7 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) =
|
||||||
return
|
return
|
||||||
let check = strTableGet(scope.symbols, fn.name)
|
let check = strTableGet(scope.symbols, fn.name)
|
||||||
if check != nil and check.kind notin OverloadableSyms:
|
if check != nil and check.kind notin OverloadableSyms:
|
||||||
wrongRedefinition(c, fn.info, fn.name.s)
|
wrongRedefinition(c, fn.info, fn.name.s, check.info)
|
||||||
else:
|
else:
|
||||||
scope.addSym(fn)
|
scope.addSym(fn)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1604,7 +1604,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
|
localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
|
||||||
("'" & proto.name.s & "' from " & c.config$proto.info))
|
("'" & proto.name.s & "' from " & c.config$proto.info))
|
||||||
if sfForward notin proto.flags and proto.magic == mNone:
|
if sfForward notin proto.flags and proto.magic == mNone:
|
||||||
wrongRedefinition(c, n.info, proto.name.s)
|
wrongRedefinition(c, n.info, proto.name.s, proto.info)
|
||||||
excl(proto.flags, sfForward)
|
excl(proto.flags, sfForward)
|
||||||
closeScope(c) # close scope with wrong parameter symbols
|
closeScope(c) # close scope with wrong parameter symbols
|
||||||
openScope(c) # open scope for old (correct) parameter symbols
|
openScope(c) # open scope for old (correct) parameter symbols
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if sfGenSym notin e.flags:
|
if sfGenSym notin e.flags:
|
||||||
if not isPure: addDecl(c, e)
|
if not isPure: addDecl(c, e)
|
||||||
else: importPureEnumField(c, e)
|
else: importPureEnumField(c, e)
|
||||||
if isPure and strTableIncl(symbols, e):
|
if isPure and (let conflict = strTableInclReportConflict(symbols, e); conflict != nil):
|
||||||
wrongRedefinition(c, e.info, e.name.s)
|
wrongRedefinition(c, e.info, e.name.s, conflict.info)
|
||||||
inc(counter)
|
inc(counter)
|
||||||
if not hasNull: incl(result.flags, tfNeedsInit)
|
if not hasNull: incl(result.flags, tfNeedsInit)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue