summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2015-06-21 22:03:01 +0300
committerArnold D. Robbins <arnold@skeeve.com>2015-06-21 22:03:01 +0300
commitf57f0699d7193571233735ba691ba19fc072b7dc (patch)
tree324f8a3af40517cf6c345fafb8ae2a3e6c084658
parent7c4eb55aea8028503a27cf0132de12257262f71a (diff)
downloadgawk-f57f0699d7193571233735ba691ba19fc072b7dc.tar.gz
Fix typeof to not change untyped param to scalar.
-rw-r--r--ChangeLog13
-rw-r--r--awk.h1
-rw-r--r--awkgram.c6
-rw-r--r--awkgram.y6
-rw-r--r--builtin.c3
-rw-r--r--eval.c1
-rw-r--r--interpret.h9
-rw-r--r--test/ChangeLog5
-rw-r--r--test/Makefile.am4
-rw-r--r--test/Makefile.in9
-rw-r--r--test/Maketests5
-rw-r--r--test/typeof2.awk20
-rw-r--r--test/typeof2.ok6
13 files changed, 79 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 586ea3ee..b00a5c22 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2015-06-21 Arnold D. Robbins <arnold@skeeve.com>
+
+ Fixes for typeof - Don't let typeof change an untyped variable
+ into a scalar.
+
+ * awk.h (opcodeval): Add Op_push_arg_untyped.
+ * awkgram.y (snode): Separate out case for do_typeof, use
+ Op_push_arg_untyped.
+ * builtin.c (do_typeof): Arg will be equal to Nnull_string
+ if it's untyped.
+ * eval.c (optypes): Add Op_push_arg_untyped.
+ * interpret.h (r_interpret): Add Op_push_arg_untyped handling.
+
2015-06-19 Arnold D. Robbins <arnold@skeeve.com>
* builtin.c (do_isarray): Minor edit to lint warning.
diff --git a/awk.h b/awk.h
index 5acd33d8..0c42f2e7 100644
--- a/awk.h
+++ b/awk.h
@@ -643,6 +643,7 @@ typedef enum opcodeval {
Op_push, /* scalar variable */
Op_push_arg, /* variable type (scalar or array) argument to built-in */
+ Op_push_arg_untyped, /* like Op_push_arg, but for typeof */
Op_push_i, /* number, string */
Op_push_re, /* regex */
Op_push_array,
diff --git a/awkgram.c b/awkgram.c
index 12f648ed..ade5ed6a 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -6697,10 +6697,14 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
}
- } else if (r->builtin == do_isarray || r->builtin == do_typeof) {
+ } else if (r->builtin == do_isarray) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
+ } else if (r->builtin == do_typeof) {
+ arg = subn->nexti;
+ if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
|| r->builtin == MPF(intdiv)
diff --git a/awkgram.y b/awkgram.y
index 28541f86..d2503697 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -4277,10 +4277,14 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
}
- } else if (r->builtin == do_isarray || r->builtin == do_typeof) {
+ } else if (r->builtin == do_isarray) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
+ } else if (r->builtin == do_typeof) {
+ arg = subn->nexti;
+ if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
|| r->builtin == MPF(intdiv)
diff --git a/builtin.c b/builtin.c
index 61a4398b..942a36dd 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3872,7 +3872,6 @@ do_typeof(int nargs)
{
NODE *arg;
char *res = "unknown";
- int null_str_flags = (STRCUR|STRING|NUMCUR|NUMBER);
arg = POP();
switch (arg->type) {
@@ -3884,7 +3883,7 @@ do_typeof(int nargs)
break;
case Node_val:
case Node_var:
- if ((arg->flags & null_str_flags) == null_str_flags)
+ if (arg == Nnull_string)
res = "untyped";
else if ((arg->flags & STRING) != 0)
res = "scalar_s";
diff --git a/eval.c b/eval.c
index 73bd56cb..c6008580 100644
--- a/eval.c
+++ b/eval.c
@@ -338,6 +338,7 @@ static struct optypetab {
{ "Op_indirect_func_call", NULL },
{ "Op_push", NULL },
{ "Op_push_arg", NULL },
+ { "Op_push_arg_untyped", NULL },
{ "Op_push_i", NULL },
{ "Op_push_re", NULL },
{ "Op_push_array", NULL },
diff --git a/interpret.h b/interpret.h
index 03532f43..554a7663 100644
--- a/interpret.h
+++ b/interpret.h
@@ -144,6 +144,7 @@ top:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
{
NODE *save_symbol;
bool isparam = false;
@@ -175,8 +176,10 @@ top:
case Node_var_new:
uninitialized_scalar:
- m->type = Node_var;
- m->var_value = dupnode(Nnull_string);
+ if (op != Op_push_arg_untyped) {
+ m->type = Node_var;
+ m->var_value = dupnode(Nnull_string);
+ }
if (do_lint)
lintwarn(isparam ?
_("reference to uninitialized argument `%s'") :
@@ -187,7 +190,7 @@ uninitialized_scalar:
break;
case Node_var_array:
- if (op == Op_push_arg)
+ if (op == Op_push_arg || op == Op_push_arg_untyped)
PUSH(m);
else
fatal(_("attempt to use array `%s' in a scalar context"),
diff --git a/test/ChangeLog b/test/ChangeLog
index b57a756f..393f38e8 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2015-06-21 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (typeof2): New test.
+ * typeof2.awk, typeof2.ok: New files.
+
2015-06-19 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (gsubind, typedregex1, typeof1): New tests.
diff --git a/test/Makefile.am b/test/Makefile.am
index 537a5655..25b8b708 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -985,6 +985,8 @@ EXTRA_DIST = \
typedregex1.ok \
typeof1.awk \
typeof1.ok \
+ typeof2.awk \
+ typeof2.ok \
uninit2.awk \
uninit2.ok \
uninit3.awk \
@@ -1099,7 +1101,7 @@ GAWK_EXT_TESTS = \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
symtab7 symtab8 symtab9 \
- typedregex1 typeof1
+ typedregex1 typeof1 typeof2
timeout
EXTRA_TESTS = inftest regtest
diff --git a/test/Makefile.in b/test/Makefile.in
index a8895ed7..1ab60181 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1242,6 +1242,8 @@ EXTRA_DIST = \
typedregex1.ok \
typeof1.awk \
typeof1.ok \
+ typeof2.awk \
+ typeof2.ok \
uninit2.awk \
uninit2.ok \
uninit3.awk \
@@ -1355,7 +1357,7 @@ GAWK_EXT_TESTS = \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
symtab7 symtab8 symtab9 \
- typedregex1 typeof1
+ typedregex1 typeof1 typeof2
EXTRA_TESTS = inftest regtest
INET_TESTS = inetdayu inetdayt inetechu inetecht
@@ -3905,6 +3907,11 @@ typeof1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+typeof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index a674d5d0..baf973ec 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1342,6 +1342,11 @@ typeof1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+typeof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/typeof2.awk b/test/typeof2.awk
new file mode 100644
index 00000000..25da02e4
--- /dev/null
+++ b/test/typeof2.awk
@@ -0,0 +1,20 @@
+BEGIN {
+ print typeof(x)
+ x[1] = 3
+ print typeof(x)
+}
+
+function test1() {
+}
+
+function test2(p) {
+ p[1] = 1
+}
+
+BEGIN {
+ print typeof(a)
+ test1(a)
+ print typeof(a)
+ test2(a)
+ print typeof(a)
+}
diff --git a/test/typeof2.ok b/test/typeof2.ok
new file mode 100644
index 00000000..cc032a83
--- /dev/null
+++ b/test/typeof2.ok
@@ -0,0 +1,6 @@
+untyped
+array
+untyped
+gawk: typeof2.awk:16: warning: function `test1' called with more arguments than declared
+untyped
+array