diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-12-27 12:23:17 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-12-27 12:23:17 +0100 |
commit | c19c6b1fae5640edcf1a522f526b786a3f0482e1 (patch) | |
tree | 310d69f3fc79ea6a7b165744fb7998f214012b48 /compiler | |
parent | 7b5448c755885d61b5213ad91ca95f630bbd6d28 (diff) | |
parent | b3732e23716166dfa7c77e8dc1ee9b4571853aed (diff) | |
download | Nim-c19c6b1fae5640edcf1a522f526b786a3f0482e1.tar.gz |
Merge branch 'devel' of github.com:nim-lang/Nim into devel
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/msgs.nim | 6 | ||||
-rw-r--r-- | compiler/pragmas.nim | 2 | ||||
-rw-r--r-- | compiler/sem.nim | 13 | ||||
-rw-r--r-- | compiler/semstmts.nim | 24 |
4 files changed, 32 insertions, 13 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 2668c72ae..4e6226122 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -26,7 +26,8 @@ type errAtPopWithoutPush, errEmptyAsm, errInvalidIndentation, errExceptionExpected, errExceptionAlreadyHandled, errYieldNotAllowedHere, errYieldNotAllowedInTryStmt, - errInvalidNumberOfYieldExpr, errCannotReturnExpr, errAttemptToRedefine, + errInvalidNumberOfYieldExpr, errCannotReturnExpr, + errNoReturnWithReturnTypeNotAllowed, errAttemptToRedefine, errStmtInvalidAfterReturn, errStmtExpected, errInvalidLabel, errInvalidCmdLineOption, errCmdLineArgExpected, errCmdLineNoArgExpected, errInvalidVarSubstitution, errUnknownVar, errUnknownCcompiler, @@ -179,8 +180,9 @@ const errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator", errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expressions", errCannotReturnExpr: "current routine cannot return an expression", + errNoReturnWithReturnTypeNotAllowed: "routines with NoReturn pragma are not allowed to have return type", errAttemptToRedefine: "redefinition of \'$1\'", - errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\', \'raise\' or \'continue'", + errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\', \'raise\', \'continue\' or proc call with noreturn pragma", errStmtExpected: "statement expected", errInvalidLabel: "\'$1\' is no label", errInvalidCmdLineOption: "invalid command line option: \'$1\'", diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 6f38def4f..bdaecf91d 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -771,6 +771,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, of wNoreturn: noVal(it) incl(sym.flags, sfNoReturn) + if sym.typ[0] != nil: + localError(sym.ast[paramsPos][0].info, errNoReturnWithReturnTypeNotAllowed) of wDynlib: processDynLib(c, it, sym) of wCompilerProc, wCore: diff --git a/compiler/sem.nim b/compiler/sem.nim index bc994201d..ababbd303 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -165,6 +165,19 @@ proc commonType*(x, y: PType): PType = result = newType(k, r.owner) result.addSonSkipIntLit(r) +proc endsInNoReturn(n: PNode): bool = + # check if expr ends in raise exception or call of noreturn proc + var it = n + while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0: + it = it.lastSon + result = it.kind == nkRaiseStmt or + it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags + +proc commonType*(x: PType, y: PNode): PType = + # ignore exception raising branches in case/if expressions + if endsInNoReturn(y): return x + commonType(x, y.typ) + proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info) when defined(nimsuggest): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8ed120c98..b1fa8c19b 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -165,14 +165,14 @@ proc semIf(c: PContext, n: PNode): PNode = it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) when not newScopeForIf: openScope(c) it.sons[1] = semExprBranch(c, it.sons[1]) - typ = commonType(typ, it.sons[1].typ) + typ = commonType(typ, it.sons[1]) closeScope(c) elif it.len == 1: hasElse = true it.sons[0] = semExprBranchScope(c, it.sons[0]) - typ = commonType(typ, it.sons[0].typ) + typ = commonType(typ, it.sons[0]) else: illFormedAst(it) - if isEmptyType(typ) or typ.kind == tyNil or not hasElse: + if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: for it in n: discardCheck(c, it.lastSon) result.kind = nkIfStmt # propagate any enforced VoidContext: @@ -180,7 +180,8 @@ proc semIf(c: PContext, n: PNode): PNode = else: for it in n: let j = it.len-1 - it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) + if not endsInNoReturn(it.sons[j]): + it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) result.kind = nkIfExpr result.typ = typ @@ -213,7 +214,7 @@ proc semCase(c: PContext, n: PNode): PNode = semCaseBranch(c, n, x, i, covered) var last = sonsLen(x)-1 x.sons[last] = semExprBranchScope(c, x.sons[last]) - typ = commonType(typ, x.sons[last].typ) + typ = commonType(typ, x.sons[last]) of nkElifBranch: chckCovered = false checkSonsLen(x, 2) @@ -221,13 +222,13 @@ proc semCase(c: PContext, n: PNode): PNode = x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) when not newScopeForIf: openScope(c) x.sons[1] = semExprBranch(c, x.sons[1]) - typ = commonType(typ, x.sons[1].typ) + typ = commonType(typ, x.sons[1]) closeScope(c) of nkElse: chckCovered = false checkSonsLen(x, 1) x.sons[0] = semExprBranchScope(c, x.sons[0]) - typ = commonType(typ, x.sons[0].typ) + typ = commonType(typ, x.sons[0]) hasElse = true else: illFormedAst(x) @@ -237,7 +238,7 @@ proc semCase(c: PContext, n: PNode): PNode = else: localError(n.info, errNotAllCasesCovered) closeScope(c) - if isEmptyType(typ) or typ.kind == tyNil or not hasElse: + if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) # propagate any enforced VoidContext: if typ == enforceVoidContext: @@ -246,7 +247,8 @@ proc semCase(c: PContext, n: PNode): PNode = for i in 1..n.len-1: var it = n.sons[i] let j = it.len-1 - it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) + if not endsInNoReturn(it.sons[j]): + it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) result.typ = typ proc semTry(c: PContext, n: PNode): PNode = @@ -1851,8 +1853,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = else: n.typ = n.sons[i].typ if not isEmptyType(n.typ): n.kind = nkStmtListExpr - case n.sons[i].kind - of LastBlockStmts: + if n.sons[i].kind in LastBlockStmts or + n.sons[i].kind in nkCallKinds and n.sons[i][0].kind == nkSym and sfNoReturn in n.sons[i][0].sym.flags: for j in countup(i + 1, length - 1): case n.sons[j].kind of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr, |