static void var_block_close(struct parse_context *c, enum closetype ct)
{
- /* Close off all variables that are in_scope */
+ /* Close off all variables that are in_scope.
+ * Some variables in c->scope may already be not-in-scope,
+ * such as when a PendingScope variable is hidden by a new
+ * variable with the same name.
+ * So we check for v->name->var != v and drop them.
+ * If we choose to make a variable OutScope, we drop it
+ * immediately too.
+ */
struct variable *v, **vp, *v2;
scope_pop(c);
? (*vp = v->in_scope, 0)
: ( vp = &v->in_scope, 0)) {
v->min_depth = c->scope_depth;
- if (v->name->var != v) {
+ if (v->name->var != v)
/* This is still in scope, but we haven't just
* closed the scope.
*/
continue;
- }
switch (ct) {
case CloseElse:
case CloseParallel: /* handle PendingScope */
case InScope:
case CondScope:
if (c->scope_stack->child_count == 1)
+ /* first among parallel branches */
v->scope = PendingScope;
else if (v->previous &&
v->previous->scope == PendingScope)
+ /* all previous branches used name */
v->scope = PendingScope;
else if (v->type == Tlabel) // UNTESTED
+ /* Labels remain pending even when not used */
v->scope = PendingScope; // UNTESTED
- else if (v->name->var == v) // UNTESTED
- v->scope = OutScope; // UNTESTED
if (ct == CloseElse) {
/* All Pending variables with this name
* are now Conditional */
}
break;
case PendingScope:
- for (v2 = v;
- v2 && v2->scope == PendingScope;
- v2 = v2->previous)
- if (v2->type != Tlabel)
- v2->scope = OutScope;
- break;
- case OutScope: break; // UNTESTED
+ /* Not possible as it would require
+ * parallel scope to be nested immediately
+ * in a parallel scope, and that never
+ * happens.
+ */
+ case OutScope:
+ /* Not possible as we already tested for
+ * OutScope
+ */
+ abort(); // NOTEST
}
break;
case CloseSequential: