Cpp codegen: handling of imported exceptions. Fixes #3571 (#7360)

This commit is contained in:
cooldome 2018-04-10 11:14:59 +01:00 • committed by Andreas Rumpf
commit 16c1a90857
12 changed files with 267 additions and 42 deletions

View file

@ -257,13 +257,19 @@ proc semCase(c: PContext, n: PNode): PNode =
proc semTry(c: PContext, n: PNode): PNode =
var check = initIntSet()
template semExceptBranchType(typeNode: PNode): PNode =
template semExceptBranchType(typeNode: PNode): bool =
# returns true if exception type is imported type
let typ = semTypeNode(c, typeNode, nil).toObject()
if typ.kind != tyObject:
localError(typeNode.info, errExprCannotBeRaised)
var is_imported = false
if isImportedException(typ):
is_imported = true
elif not isException(typ):
localError(typeNode.info, errExprCannotBeRaised)
if containsOrIncl(check, typ.id):
localError(typeNode.info, errExceptionAlreadyHandled)
newNodeIT(nkType, typeNode.info, typ)
typeNode = newNodeIT(nkType, typeNode.info, typ)
is_imported
result = n
inc c.p.inTryStmt
@ -286,18 +292,24 @@ proc semTry(c: PContext, n: PNode): PNode =
if a.len == 2 and a[0].isInfixAs():
# support ``except Exception as ex: body``
a[0][1] = semExceptBranchType(a[0][1])
let is_imported = semExceptBranchType(a[0][1])
let symbol = newSymG(skLet, a[0][2], c)
symbol.typ = a[0][1].typ.toRef()
symbol.typ = if is_imported: a[0][1].typ
else: a[0][1].typ.toRef()
addDecl(c, symbol)
# Overwrite symbol in AST with the symbol in the symbol table.
a[0][2] = newSymNode(symbol, a[0][2].info)
else:
# support ``except KeyError, ValueError, ... : body``
var is_native, is_imported: bool
for j in 0..a.len-2:
a[j] = semExceptBranchType(a[j])
let tmp = semExceptBranchType(a[j])
if tmp: is_imported = true
else: is_native = true
if is_native and is_imported:
localError(a[0].info, "Mix of imported and native exception types is not allowed in one except branch")
elif a.kind != nkFinally:
illFormedAst(n)
@ -731,16 +743,19 @@ proc semFor(c: PContext, n: PNode): PNode =
proc semRaise(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
if n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0])
var typ = n.sons[0].typ
if typ.kind != tyRef or typ.lastSon.kind != tyObject:
localError(n.info, errExprCannotBeRaised)
if n[0].kind != nkEmpty:
n[0] = semExprWithType(c, n[0])
let typ = n[0].typ
# check if the given object inherits from Exception
if not typ.lastSon.isException():
if not isImportedException(typ):
if typ.kind != tyRef or typ.lastSon.kind != tyObject:
localError(n.info, errExprCannotBeRaised)
if not isException(typ.lastSon):
localError(n.info, "raised object of type $1 does not inherit from Exception",
[typeToString(typ)])
[typeToString(typ)])
proc addGenericParamListToScope(c: PContext, n: PNode) =