Merge remote-tracking branch 'upstream/devel' into pr_object

This commit is contained in:
ringabout
2023-03-24 23:29:14 +08:00
29 changed files with 188 additions and 64 deletions

View File

@@ -510,7 +510,7 @@ type
nfLastRead # this node is a last read
nfFirstWrite # this node is a first write
nfHasComment # node has a comment
nfUseDefaultField # node has a default value (object constructor)
nfSkipFieldChecking # node skips field visable checking
TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 46)
@@ -1081,7 +1081,7 @@ const
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
nfFromTemplate, nfDefaultRefsParam,
nfExecuteOnReload, nfLastRead,
nfFirstWrite, nfUseDefaultField}
nfFirstWrite, nfSkipFieldChecking}
namePos* = 0
patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2

View File

@@ -572,7 +572,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
let asgnExpr = defaultNodeField(c, recNode, recNode.typ)
if asgnExpr != nil:
hasDefault = true
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
return
@@ -582,7 +582,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)),
newNodeIT(nkType, recNode.info, asgnType)
)
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
asgnExpr.typ = recType
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
else:
@@ -604,7 +604,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
defaultValue.typ = discriminator.typ
selectedBranch = recNode.pickCaseBranchIndex defaultValue
defaultValue.flags.incl nfUseDefaultField
defaultValue.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1])
of nkSym:
@@ -616,7 +616,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
let asgnExpr = defaultNodeField(c, recNode, recType)
if asgnExpr != nil:
asgnExpr.typ = recType
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
else:
doAssert false

View File

@@ -338,7 +338,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
if n[0].kind in nkIdentKinds:
let ident = considerQuotedIdent(c, n[0], n).s
localError(c.config, n.info, errUndeclaredRoutine % ident)
else:
else:
localError(c.config, n.info, "expression '$1' cannot be called" % n[0].renderTree)
return
@@ -630,7 +630,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
if efExplain notin flags:
# repeat the overload resolution,
# this time enabling all the diagnostic output (this should fail again)
discard semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
result = semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
elif efNoUndeclared notin flags:
notFoundError(c, n, errors)

View File

@@ -302,7 +302,7 @@ proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
result = newNodeI(nkConv, n.info)
var targetType = semTypeNode(c, n[0], nil)
case targetType.kind
case targetType.skipTypes({tyDistinct}).kind
of tyTypeDesc:
internalAssert c.config, targetType.len > 0
if targetType.base.kind == tyNone:
@@ -787,7 +787,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
else:
result = newHiddenAddrTaken(c, n, isOutParam)
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
proc analyseIfAddressTakenInCall(c: PContext, n: PNode, isConverter = false) =
checkMinSonsLen(n, 1, c.config)
const
FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl,
@@ -795,10 +795,15 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove,
mWasMoved}
template checkIfConverterCalled(c: PContext, n: PNode) =
## Checks if there is a converter call which wouldn't be checked otherwise
# Call can sometimes be wrapped in a deref
let node = if n.kind == nkHiddenDeref: n[0] else: n
if node.kind == nkHiddenCallConv:
analyseIfAddressTakenInCall(c, node, true)
# get the real type of the callee
# it may be a proc var with a generic alias type, so we skip over them
var t = n[0].typ.skipTypes({tyGenericInst, tyAlias, tySink})
if n[0].kind == nkSym and n[0].sym.magic in FakeVarParams:
# BUGFIX: check for L-Value still needs to be done for the arguments!
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
@@ -813,6 +818,8 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
discard "allow access within a cast(unsafeAssign) section"
else:
localError(c.config, it.info, errVarForOutParamNeededX % $it)
# Make sure to still check arguments for converters
c.checkIfConverterCalled(n[i])
# bug #5113: disallow newSeq(result) where result is a 'var T':
if n[0].sym.magic in {mNew, mNewFinalize, mNewSeq}:
var arg = n[1] #.skipAddr
@@ -824,15 +831,14 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
return
for i in 1..<n.len:
let n = if n.kind == nkHiddenDeref: n[0] else: n
if n[i].kind == nkHiddenCallConv:
# we need to recurse explicitly here as converters can create nested
# calls and then they wouldn't be analysed otherwise
analyseIfAddressTakenInCall(c, n[i])
c.checkIfConverterCalled(n[i])
if i < t.len and
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind in {tyVar}:
if n[i].kind != nkHiddenAddr:
n[i] = analyseIfAddressTaken(c, n[i], isOutParam(skipTypes(t[i], abstractInst-{tyTypeDesc})))
# Converters wrap var parameters in nkHiddenAddr but they haven't been analysed yet.
# So we need to make sure we are checking them still when in a converter call
if n[i].kind != nkHiddenAddr or isConverter:
n[i] = analyseIfAddressTaken(c, n[i].skipAddr(), isOutParam(skipTypes(t[i], abstractInst-{tyTypeDesc})))
include semmagic
proc evalAtCompileTime(c: PContext, n: PNode): PNode =

View File

@@ -78,14 +78,18 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
if macroToExpandSym(s):
onUse(n.info, s)
result = semTemplateExpr(c, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, {}, ctx)
discard c.friendModules.pop()
else:
result = symChoice(c, n, s, scOpen)
of skMacro:
if macroToExpandSym(s):
onUse(n.info, s)
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, {}, ctx)
discard c.friendModules.pop()
else:
result = symChoice(c, n, s, scOpen)
of skGenericParam:
@@ -245,7 +249,9 @@ proc semGenericStmt(c: PContext, n: PNode,
if macroToExpand(s) and sc.safeLen <= 1:
onUse(fn.info, s)
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, flags, ctx)
discard c.friendModules.pop()
else:
n[0] = sc
result = n
@@ -254,7 +260,9 @@ proc semGenericStmt(c: PContext, n: PNode,
if macroToExpand(s) and sc.safeLen <= 1:
onUse(fn.info, s)
result = semTemplateExpr(c, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, flags, ctx)
discard c.friendModules.pop()
else:
n[0] = sc
result = n
@@ -493,6 +501,20 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkExprColonExpr, nkExprEqExpr:
checkMinSonsLen(n, 2, c.config)
result[1] = semGenericStmt(c, n[1], flags, ctx)
of nkObjConstr:
for i in 0..<n.len:
result[i] = semGenericStmt(c, n[i], flags, ctx)
if result[0].kind == nkSym:
let fmoduleId = getModule(result[0].sym).id
var isVisable = false
for module in c.friendModules:
if module.id == fmoduleId:
isVisable = true
break
if isVisable:
for i in 1..<result.len:
if result[i].kind == nkExprColonExpr:
result[i][1].flags.incl nfSkipFieldChecking
else:
for i in 0..<n.len:
result[i] = semGenericStmt(c, n[i], flags, ctx)

View File

@@ -76,7 +76,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
let assignment = locateFieldInInitExpr(c, field, initExpr)
if assignment != nil:
if nfSem in assignment.flags: return assignment[1]
if nfUseDefaultField in assignment[1].flags:
if nfSkipFieldChecking in assignment[1].flags:
discard
elif not fieldVisible(c, field):
localError(c.config, initExpr.info,
@@ -178,7 +178,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
newSymNode(getSysMagic(c.graph, constrCtx.initExpr.info, "zeroDefault", mZeroDefault)),
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
)
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
asgnExpr.typ = recTyp
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)

View File

@@ -519,7 +519,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
let fSym = newSymNode(field)
if hasDefaultField:
fSym.sym.ast = a[^1]
fSym.sym.ast.flags.incl nfUseDefaultField
fSym.sym.ast.flags.incl nfSkipFieldChecking
result.n.add fSym
addSonSkipIntLit(result, typ, c.idgen)
styleCheckDef(c, a[j].info, field)
@@ -868,7 +868,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
let fSym = newSymNode(f)
if hasDefaultField:
fSym.sym.ast = n[^1]
fSym.sym.ast.flags.incl nfUseDefaultField
fSym.sym.ast.flags.incl nfSkipFieldChecking
if a.kind == nkEmpty: father.add fSym
else: a.add fSym
styleCheckDef(c, f)

View File

@@ -1979,8 +1979,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
if srca == isSubtype:
param = implicitConv(nkHiddenSubConv, src, copyTree(arg), m, c)
elif src.kind in {tyVar}:
# Analyse the converter return type
arg.sym.flags.incl sfAddrTaken
# Analyse the converter return type.
param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1])
param.add copyTree(arg)
else:

View File

@@ -1829,7 +1829,7 @@ proc getNullValueAux(t: PType; obj: PNode, result: PNode; conf: ConfigRef; currP
let field = newNodeI(nkExprColonExpr, result.info)
field.add(obj)
let value = getNullValue(obj.sym.typ, result.info, conf)
value.flags.incl nfUseDefaultField
value.flags.incl nfSkipFieldChecking
field.add(value)
result.add field
doAssert obj.sym.position == currPosition