Commit 1eecc24a authored by malff@lambda.hsd1.co.comcast.net's avatar malff@lambda.hsd1.co.comcast.net

Merge malff@bk-internal.mysql.com:/home/bk/mysql-5.0-runtime

into  lambda.hsd1.co.comcast.net.:/home/malff/TREE/mysql-5.0-33618
parents 3cd05f00 c3ad0cac
...@@ -733,4 +733,113 @@ optimizer: keep hreturn ...@@ -733,4 +733,113 @@ optimizer: keep hreturn
drop table t1; drop table t1;
drop procedure proc_26977_broken; drop procedure proc_26977_broken;
drop procedure proc_26977_works; drop procedure proc_26977_works;
drop procedure if exists proc_33618_h;
drop procedure if exists proc_33618_c;
create procedure proc_33618_h(num int)
begin
declare count1 int default '0';
declare vb varchar(30);
declare last_row int;
while(num>=1) do
set num=num-1;
begin
declare cur1 cursor for select `a` from t_33618;
declare continue handler for not found set last_row = 1;
set last_row:=0;
open cur1;
rep1:
repeat
begin
declare exit handler for 1062 begin end;
fetch cur1 into vb;
if (last_row = 1) then
## should generate a hpop instruction here
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
create procedure proc_33618_c(num int)
begin
declare count1 int default '0';
declare vb varchar(30);
declare last_row int;
while(num>=1) do
set num=num-1;
begin
declare cur1 cursor for select `a` from t_33618;
declare continue handler for not found set last_row = 1;
set last_row:=0;
open cur1;
rep1:
repeat
begin
declare cur2 cursor for select `b` from t_33618;
fetch cur1 into vb;
if (last_row = 1) then
## should generate a cpop instruction here
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
show procedure code proc_33618_h;
Pos Instruction
0 set count1@1 _latin1'0'
1 set vb@2 NULL
2 set last_row@3 NULL
3 jump_if_not 24(24) (num@0 >= 1)
4 set num@0 (num@0 - 1)
5 cpush cur1@0
6 hpush_jump 9 4 CONTINUE
7 set last_row@3 1
8 hreturn 4
9 set last_row@3 0
10 copen cur1@0
11 hpush_jump 13 4 EXIT
12 hreturn 0 17
13 cfetch cur1@0 vb@2
14 jump_if_not 17(17) (last_row@3 = 1)
15 hpop 1
16 jump 19
17 hpop 1
18 jump_if_not 11(19) (last_row@3 = 1)
19 cclose cur1@0
20 hpop 1
21 cpop 1
22 jump 3
show procedure code proc_33618_c;
Pos Instruction
0 set count1@1 _latin1'0'
1 set vb@2 NULL
2 set last_row@3 NULL
3 jump_if_not 23(23) (num@0 >= 1)
4 set num@0 (num@0 - 1)
5 cpush cur1@0
6 hpush_jump 9 4 CONTINUE
7 set last_row@3 1
8 hreturn 4
9 set last_row@3 0
10 copen cur1@0
11 cpush cur2@1
12 cfetch cur1@0 vb@2
13 jump_if_not 16(16) (last_row@3 = 1)
14 cpop 1
15 jump 18
16 cpop 1
17 jump_if_not 11(18) (last_row@3 = 1)
18 cclose cur1@0
19 hpop 1
20 cpop 1
21 jump 3
drop procedure proc_33618_h;
drop procedure proc_33618_c;
End of 5.0 tests. End of 5.0 tests.
...@@ -1465,3 +1465,51 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp ...@@ -1465,3 +1465,51 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SELECT ..inexistent(); SELECT ..inexistent();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.inexistent()' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.inexistent()' at line 1
USE test; USE test;
drop procedure if exists proc_33983_a;
drop procedure if exists proc_33983_b;
drop procedure if exists proc_33983_c;
drop procedure if exists proc_33983_d;
create procedure proc_33983_a()
begin
label1:
begin
label2:
begin
select 1;
end label1;
end;
end|
ERROR 42000: End-label label1 without match
create procedure proc_33983_b()
begin
label1:
repeat
label2:
repeat
select 1;
until FALSE end repeat label1;
until FALSE end repeat;
end|
ERROR 42000: End-label label1 without match
create procedure proc_33983_c()
begin
label1:
while TRUE do
label2:
while TRUE do
select 1;
end while label1;
end while;
end|
ERROR 42000: End-label label1 without match
create procedure proc_33983_d()
begin
label1:
loop
label2:
loop
select 1;
end loop label1;
end loop;
end|
ERROR 42000: End-label label1 without match
...@@ -6578,22 +6578,41 @@ DROP PROCEDURE db28318_a.t1; ...@@ -6578,22 +6578,41 @@ DROP PROCEDURE db28318_a.t1;
DROP PROCEDURE db28318_b.t2; DROP PROCEDURE db28318_b.t2;
DROP DATABASE db28318_a; DROP DATABASE db28318_a;
DROP DATABASE db28318_b; DROP DATABASE db28318_b;
USE test; use test;
DROP TABLE IF EXISTS t1; drop table if exists t_33618;
DROP PROCEDURE IF EXISTS bug29770; drop procedure if exists proc_33618;
CREATE TABLE t1(a int); create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam;
CREATE PROCEDURE bug29770() insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2');
BEGIN create procedure proc_33618(num int)
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S22' SET @state:= 'run'; begin
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @exception:= 'run'; declare count1 int default '0';
SELECT x FROM t1; declare vb varchar(30);
END| declare last_row int;
CALL bug29770(); while(num>=1) do
SELECT @state, @exception; set num=num-1;
@state @exception begin
run NULL declare cur1 cursor for select `a` from t_33618;
DROP TABLE t1; declare continue handler for not found set last_row = 1;
DROP PROCEDURE bug29770; set last_row:=0;
open cur1;
rep1:
repeat
begin
declare exit handler for 1062 begin end;
fetch cur1 into vb;
if (last_row = 1) then
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
call proc_33618(20);
drop table t_33618;
drop procedure proc_33618;
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# -- End of 5.0 tests # -- End of 5.0 tests
# ------------------------------------------------------------------ # ------------------------------------------------------------------
...@@ -520,5 +520,82 @@ drop table t1; ...@@ -520,5 +520,82 @@ drop table t1;
drop procedure proc_26977_broken; drop procedure proc_26977_broken;
drop procedure proc_26977_works; drop procedure proc_26977_works;
#
# Bug#33618 Crash in sp_rcontext
#
--disable_warnings
drop procedure if exists proc_33618_h;
drop procedure if exists proc_33618_c;
--enable_warnings
delimiter //;
create procedure proc_33618_h(num int)
begin
declare count1 int default '0';
declare vb varchar(30);
declare last_row int;
while(num>=1) do
set num=num-1;
begin
declare cur1 cursor for select `a` from t_33618;
declare continue handler for not found set last_row = 1;
set last_row:=0;
open cur1;
rep1:
repeat
begin
declare exit handler for 1062 begin end;
fetch cur1 into vb;
if (last_row = 1) then
## should generate a hpop instruction here
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
create procedure proc_33618_c(num int)
begin
declare count1 int default '0';
declare vb varchar(30);
declare last_row int;
while(num>=1) do
set num=num-1;
begin
declare cur1 cursor for select `a` from t_33618;
declare continue handler for not found set last_row = 1;
set last_row:=0;
open cur1;
rep1:
repeat
begin
declare cur2 cursor for select `b` from t_33618;
fetch cur1 into vb;
if (last_row = 1) then
## should generate a cpop instruction here
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
delimiter ;//
show procedure code proc_33618_h;
show procedure code proc_33618_c;
drop procedure proc_33618_h;
drop procedure proc_33618_c;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -2112,6 +2112,69 @@ SELECT .inexistent(); ...@@ -2112,6 +2112,69 @@ SELECT .inexistent();
SELECT ..inexistent(); SELECT ..inexistent();
USE test; USE test;
#
# Bug#33983 (Stored Procedures: wrong end <label> syntax is accepted)
#
--disable_warnings
drop procedure if exists proc_33983_a;
drop procedure if exists proc_33983_b;
drop procedure if exists proc_33983_c;
drop procedure if exists proc_33983_d;
--enable_warnings
delimiter |;
--error ER_SP_LABEL_MISMATCH
create procedure proc_33983_a()
begin
label1:
begin
label2:
begin
select 1;
end label1;
end;
end|
--error ER_SP_LABEL_MISMATCH
create procedure proc_33983_b()
begin
label1:
repeat
label2:
repeat
select 1;
until FALSE end repeat label1;
until FALSE end repeat;
end|
--error ER_SP_LABEL_MISMATCH
create procedure proc_33983_c()
begin
label1:
while TRUE do
label2:
while TRUE do
select 1;
end while label1;
end while;
end|
--error ER_SP_LABEL_MISMATCH
create procedure proc_33983_d()
begin
label1:
loop
label2:
loop
select 1;
end loop label1;
end loop;
end|
delimiter ;|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -7723,6 +7723,57 @@ SELECT @state, @exception; ...@@ -7723,6 +7723,57 @@ SELECT @state, @exception;
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE bug29770; DROP PROCEDURE bug29770;
#
# Bug#33618 Crash in sp_rcontext
#
use test;
--disable_warnings
drop table if exists t_33618;
drop procedure if exists proc_33618;
--enable_warnings
create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam;
insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2');
delimiter //;
create procedure proc_33618(num int)
begin
declare count1 int default '0';
declare vb varchar(30);
declare last_row int;
while(num>=1) do
set num=num-1;
begin
declare cur1 cursor for select `a` from t_33618;
declare continue handler for not found set last_row = 1;
set last_row:=0;
open cur1;
rep1:
repeat
begin
declare exit handler for 1062 begin end;
fetch cur1 into vb;
if (last_row = 1) then
leave rep1;
end if;
end;
until last_row=1
end repeat;
close cur1;
end;
end while;
end//
delimiter ;//
call proc_33618(20);
drop table t_33618;
drop procedure proc_33618;
--echo # ------------------------------------------------------------------ --echo # ------------------------------------------------------------------
--echo # -- End of 5.0 tests --echo # -- End of 5.0 tests
......
...@@ -1933,11 +1933,17 @@ sp_head::backpatch(sp_label_t *lab) ...@@ -1933,11 +1933,17 @@ sp_head::backpatch(sp_label_t *lab)
uint dest= instructions(); uint dest= instructions();
List_iterator_fast<bp_t> li(m_backpatch); List_iterator_fast<bp_t> li(m_backpatch);
DBUG_ENTER("sp_head::backpatch");
while ((bp= li++)) while ((bp= li++))
{ {
if (bp->lab == lab) if (bp->lab == lab)
{
DBUG_PRINT("info", ("backpatch: (m_ip %d, label 0x%lx <%s>) to dest %d",
bp->instr->m_ip, (ulong) lab, lab->name, dest));
bp->instr->backpatch(dest, lab->ctx); bp->instr->backpatch(dest, lab->ctx);
} }
}
DBUG_VOID_RETURN;
} }
/* /*
......
...@@ -779,7 +779,8 @@ public: ...@@ -779,7 +779,8 @@ public:
virtual void backpatch(uint dest, sp_pcontext *dst_ctx) virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
{ {
if (m_dest == 0) // Don't reset /* Calling backpatch twice is a logic flaw in jump resolution. */
DBUG_ASSERT(m_dest == 0);
m_dest= dest; m_dest= dest;
} }
......
...@@ -334,17 +334,91 @@ sp_rcontext::handle_error(uint sql_errno, ...@@ -334,17 +334,91 @@ sp_rcontext::handle_error(uint sql_errno,
void void
sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
{ {
DBUG_ENTER("sp_rcontext::push_cursor");
DBUG_ASSERT(m_ccount < m_root_parsing_ctx->max_cursor_index());
m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i);
DBUG_PRINT("info", ("m_ccount: %d", m_ccount));
DBUG_VOID_RETURN;
} }
void void
sp_rcontext::pop_cursors(uint count) sp_rcontext::pop_cursors(uint count)
{ {
DBUG_ENTER("sp_rcontext::pop_cursors");
DBUG_ASSERT(m_ccount >= count);
while (count--) while (count--)
{ {
delete m_cstack[--m_ccount]; delete m_cstack[--m_ccount];
} }
DBUG_PRINT("info", ("m_ccount: %d", m_ccount));
DBUG_VOID_RETURN;
}
void
sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
{
DBUG_ENTER("sp_rcontext::push_handler");
DBUG_ASSERT(m_hcount < m_root_parsing_ctx->max_handler_index());
m_handler[m_hcount].cond= cond;
m_handler[m_hcount].handler= h;
m_handler[m_hcount].type= type;
m_handler[m_hcount].foffset= f;
m_hcount+= 1;
DBUG_PRINT("info", ("m_hcount: %d", m_hcount));
DBUG_VOID_RETURN;
}
void
sp_rcontext::pop_handlers(uint count)
{
DBUG_ENTER("sp_rcontext::pop_handlers");
DBUG_ASSERT(m_hcount >= count);
m_hcount-= count;
DBUG_PRINT("info", ("m_hcount: %d", m_hcount));
DBUG_VOID_RETURN;
}
void
sp_rcontext::push_hstack(uint h)
{
DBUG_ENTER("sp_rcontext::push_hstack");
DBUG_ASSERT(m_hsp < m_root_parsing_ctx->max_handler_index());
m_hstack[m_hsp++]= h;
DBUG_PRINT("info", ("m_hsp: %d", m_hsp));
DBUG_VOID_RETURN;
}
uint
sp_rcontext::pop_hstack()
{
uint handler;
DBUG_ENTER("sp_rcontext::pop_hstack");
DBUG_ASSERT(m_hsp);
handler= m_hstack[--m_hsp];
DBUG_PRINT("info", ("m_hsp: %d", m_hsp));
DBUG_RETURN(handler);
}
void
sp_rcontext::enter_handler(int hid)
{
DBUG_ENTER("sp_rcontext::enter_handler");
DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index());
m_in_handler[m_ihsp++]= hid;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
void
sp_rcontext::exit_handler()
{
DBUG_ENTER("sp_rcontext::exit_handler");
DBUG_ASSERT(m_ihsp);
m_ihsp-= 1;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
} }
......
...@@ -107,21 +107,9 @@ class sp_rcontext : public Sql_alloc ...@@ -107,21 +107,9 @@ class sp_rcontext : public Sql_alloc
return m_return_value_set; return m_return_value_set;
} }
inline void void push_handler(struct sp_cond_type *cond, uint h, int type, uint f);
push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
{
m_handler[m_hcount].cond= cond;
m_handler[m_hcount].handler= h;
m_handler[m_hcount].type= type;
m_handler[m_hcount].foffset= f;
m_hcount+= 1;
}
inline void void pop_handlers(uint count);
pop_handlers(uint count)
{
m_hcount-= count;
}
// Returns 1 if a handler was found, 0 otherwise. // Returns 1 if a handler was found, 0 otherwise.
bool bool
...@@ -158,29 +146,13 @@ class sp_rcontext : public Sql_alloc ...@@ -158,29 +146,13 @@ class sp_rcontext : public Sql_alloc
m_hfound= -1; m_hfound= -1;
} }
inline void void push_hstack(uint h);
push_hstack(uint h)
{
m_hstack[m_hsp++]= h;
}
inline uint uint pop_hstack();
pop_hstack()
{
return m_hstack[--m_hsp];
}
inline void void enter_handler(int hid);
enter_handler(int hid)
{
m_in_handler[m_ihsp++]= hid;
}
inline void void exit_handler();
exit_handler()
{
m_ihsp-= 1;
}
void void
push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
......
...@@ -2214,6 +2214,10 @@ sp_proc_stmt: ...@@ -2214,6 +2214,10 @@ sp_proc_stmt:
lex->sphead->backpatch(lex->spcont->pop_label()); lex->sphead->backpatch(lex->spcont->pop_label());
} }
| sp_labeled_block
{}
| sp_unlabeled_block
{}
| LEAVE_SYM label_ident | LEAVE_SYM label_ident
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2231,9 +2235,17 @@ sp_proc_stmt: ...@@ -2231,9 +2235,17 @@ sp_proc_stmt:
sp_instr_jump *i; sp_instr_jump *i;
uint ip= sp->instructions(); uint ip= sp->instructions();
uint n; uint n;
/*
When jumping to a BEGIN-END block end, the target jump
points to the block hpop/cpop cleanup instructions,
so we should exclude the block context here.
When jumping to something else (i.e., SP_LAB_ITER),
there are no hpop/cpop at the jump destination,
so we should include the block context here for cleanup.
*/
bool exclusive= (lab->type == SP_LAB_BEGIN);
n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_handlers(lab->ctx, exclusive);
if (n) if (n)
{ {
sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
...@@ -2241,10 +2253,12 @@ sp_proc_stmt: ...@@ -2241,10 +2253,12 @@ sp_proc_stmt:
MYSQL_YYABORT; MYSQL_YYABORT;
sp->add_instr(hpop); sp->add_instr(hpop);
} }
n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_cursors(lab->ctx, exclusive);
if (n) if (n)
{ {
sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
if (cpop == NULL)
MYSQL_YYABORT;
sp->add_instr(cpop); sp->add_instr(cpop);
} }
i= new sp_instr_jump(ip, ctx); i= new sp_instr_jump(ip, ctx);
...@@ -2276,12 +2290,16 @@ sp_proc_stmt: ...@@ -2276,12 +2290,16 @@ sp_proc_stmt:
if (n) if (n)
{ {
sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
if (hpop == NULL)
MYSQL_YYABORT;
sp->add_instr(hpop); sp->add_instr(hpop);
} }
n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
if (n) if (n)
{ {
sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
if (cpop == NULL)
MYSQL_YYABORT;
sp->add_instr(cpop); sp->add_instr(cpop);
} }
i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
...@@ -2577,19 +2595,17 @@ sp_labeled_control: ...@@ -2577,19 +2595,17 @@ sp_labeled_control:
sp_unlabeled_control sp_opt_label sp_unlabeled_control sp_opt_label
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_label_t *lab= lex->spcont->pop_label();
if ($5.str) if ($5.str)
{ {
sp_label_t *lab= lex->spcont->find_label($5.str); if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
if (!lab ||
my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
{ {
my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
MYSQL_YYABORT; MYSQL_YYABORT;
} }
} }
lex->sphead->backpatch(lex->spcont->pop_label()); lex->sphead->backpatch(lab);
} }
; ;
...@@ -2598,15 +2614,59 @@ sp_opt_label: ...@@ -2598,15 +2614,59 @@ sp_opt_label:
| label_ident { $$= $1; } | label_ident { $$= $1; }
; ;
sp_unlabeled_control: sp_labeled_block:
label_ident ':'
{
LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($1.str);
if (lab)
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
MYSQL_YYABORT;
}
lab= lex->spcont->push_label($1.str,
lex->sphead->instructions());
lab->type= SP_LAB_BEGIN;
}
sp_block_content sp_opt_label
{
LEX *lex= Lex;
sp_label_t *lab= lex->spcont->pop_label();
if ($5.str)
{
if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
MYSQL_YYABORT;
}
}
}
;
sp_unlabeled_block:
{ /* Unlabeled blocks get a secret label. */
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->push_label((char *)"", ip);
lab->type= SP_LAB_BEGIN;
}
sp_block_content
{
LEX *lex= Lex;
lex->spcont->pop_label();
}
;
sp_block_content:
BEGIN_SYM BEGIN_SYM
{ /* QQ This is just a dummy for grouping declarations and statements { /* QQ This is just a dummy for grouping declarations and statements
together. No [[NOT] ATOMIC] yet, and we need to figure out how together. No [[NOT] ATOMIC] yet, and we need to figure out how
make it coexist with the existing BEGIN COMMIT/ROLLBACK. */ make it coexist with the existing BEGIN COMMIT/ROLLBACK. */
LEX *lex= Lex; LEX *lex= Lex;
sp_label_t *lab= lex->spcont->last_label();
lab->type= SP_LAB_BEGIN;
lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE); lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE);
} }
sp_decls sp_decls
...@@ -2636,7 +2696,10 @@ sp_unlabeled_control: ...@@ -2636,7 +2696,10 @@ sp_unlabeled_control:
} }
lex->spcont= ctx->pop_context(); lex->spcont= ctx->pop_context();
} }
| LOOP_SYM ;
sp_unlabeled_control:
LOOP_SYM
sp_proc_stmts1 END LOOP_SYM sp_proc_stmts1 END LOOP_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment