mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 10:01:11 +02:00
53602: "typeset -nu" always refers to at a call level above the declaration
This commit is contained in:
parent
1706805d46
commit
b0fa403a3d
4 changed files with 39 additions and 18 deletions
|
@ -1,3 +1,9 @@
|
|||
2025-05-12 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 53602: Doc/Zsh/func.yo, Src/params.c, Test/K01nameref.ztst:
|
||||
Update "typeset -nu" behavior to always refer to parameters
|
||||
at a call level above the declaration of the named reference.
|
||||
|
||||
2025-05-09 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* unposted: Src/params.c: fix bad pointer found by valgrind
|
||||
|
|
|
@ -23,9 +23,11 @@ declared in an earlier function scope.
|
|||
(See noderef(Local Parameters).)
|
||||
|
||||
A named parameter declared with the `tt(-n)' option to any of the
|
||||
`tt(typeset)' commands becomes a reference to a parameter in scope at
|
||||
the time of assignment to the named reference, which may be at a
|
||||
different call level than the declaring function. For this reason,
|
||||
`tt(typeset)' acts as a reference to another parameter, which may
|
||||
be at a different call level than the declaring function. When the
|
||||
`tt(-u)' option is also given, the referenced parameter is always
|
||||
found at a call level above the function where the reference is
|
||||
declared, otherwise the reference scope is dynamic. For this reason,
|
||||
it is good practice to declare a named reference as soon as the
|
||||
referent parameter is in scope, and as early as possible in the
|
||||
function if the reference is to a parameter in a calling scope.
|
||||
|
|
11
Src/params.c
11
Src/params.c
|
@ -5899,9 +5899,8 @@ scanendscope(HashNode hn, UNUSED(int flags))
|
|||
pm = hidden;
|
||||
if (pm && (pm->node.flags & PM_NAMEREF) &&
|
||||
pm->base >= pm->level && pm->base >= locallevel) {
|
||||
/* Should never get here for a -u reference */
|
||||
pm->base = locallevel;
|
||||
if (pm->level < locallevel && (pm->node.flags & PM_UPPER))
|
||||
pm->node.flags &= ~PM_UPPER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6307,7 +6306,9 @@ resolve_nameref(Param pm, const Asgment stop)
|
|||
if (pm) {
|
||||
if (!(stop && (stop->flags & (PM_LOCAL)))) {
|
||||
int scope = ((pm->node.flags & PM_NAMEREF) ?
|
||||
((pm->node.flags & PM_UPPER) ? -(pm->base) :
|
||||
((pm->node.flags & PM_UPPER) ?
|
||||
/* pm->base == 0 means not set yet */
|
||||
-(pm->base ? pm->base : pm->level) :
|
||||
pm->base) : ((Param)hn)->level);
|
||||
hn = (HashNode)upscope((Param)hn, scope);
|
||||
}
|
||||
|
@ -6413,14 +6414,14 @@ setscope(Param pm)
|
|||
} else if (!pm->base) {
|
||||
pm->base = basepm->level;
|
||||
if ((pm->node.flags & PM_UPPER) &&
|
||||
(basepm = upscope(basepm, -locallevel)))
|
||||
(basepm = upscope(basepm, -(pm->level))))
|
||||
pm->base = basepm->level;
|
||||
}
|
||||
} else if (pm->base < locallevel && refname &&
|
||||
(basepm = (Param)getparamnode(realparamtab, refname))) {
|
||||
pm->base = basepm->level;
|
||||
if ((pm->node.flags & PM_UPPER) &&
|
||||
(basepm = upscope(basepm, -locallevel)))
|
||||
(basepm = upscope(basepm, -(pm->level))))
|
||||
pm->base = basepm->level;
|
||||
}
|
||||
if (pm->base > pm->level) {
|
||||
|
|
|
@ -767,6 +767,18 @@ F:typeset cannot bypass a name in the local scope, even via nameref
|
|||
>typeset -a foo=( alpha beta gamma )
|
||||
>typeset -g foo=3
|
||||
|
||||
() {
|
||||
# scope with no parameters
|
||||
() {
|
||||
local -nu upref=$1
|
||||
local var=at_upref
|
||||
print -- $upref
|
||||
} var
|
||||
}
|
||||
0:up-reference part 15, non-existent parameter in outer scope
|
||||
# no output expected
|
||||
>
|
||||
|
||||
if [[ $options[typesettounset] != on ]]; then
|
||||
ZTST_skip='Ignoring zmodload bug that resets TYPESET_TO_UNSET'
|
||||
setopt typesettounset
|
||||
|
@ -1088,16 +1100,16 @@ F:previously this could create an infinite recursion and crash
|
|||
>h:1: rs= - ra= - rs1= - ra1=
|
||||
>h:2: rs= - ra= - rs1= - ra1=
|
||||
>i:1: rs= - ra= - rs1= - ra1=
|
||||
>i:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>j:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>j:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>i:3: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>h:3: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:1: rs=h - ra=h - rs1=h - ra1=h
|
||||
>k:2: rs=h - ra=h - rs1=h - ra1=h
|
||||
>g:3: rs=g - ra=g - rs1=g - ra1=g
|
||||
>i:2: rs=g - ra=g - rs1=g - ra1=g
|
||||
>j:1: rs=g - ra=g - rs1=g - ra1=g
|
||||
>j:2: rs=g - ra=g - rs1=g - ra1=g
|
||||
>i:3: rs=g - ra=g - rs1=g - ra1=g
|
||||
>k:1: rs=g - ra=g - rs1=g - ra1=g
|
||||
>k:2: rs=g - ra=g - rs1=g - ra1=g
|
||||
>h:3: rs=g - ra=g - rs1=g - ra1=g
|
||||
>k:1: rs=g - ra=g - rs1=g - ra1=g
|
||||
>k:2: rs=g - ra=g - rs1=g - ra1=g
|
||||
>g:3: rs=f - ra=f - rs1=f - ra1=f
|
||||
|
||||
e '' 6
|
||||
0:assignment at different scope than declaration, '' 6
|
||||
|
|
Loading…
Reference in a new issue