From 97a74eb677071f3a73a07f940cc5c6ea1c9b2e4b Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Sun, 14 Jan 2018 10:58:29 +0100 Subject: [PATCH] catch broken vector member access These kinds of expressions currently cannot be handled without pionter support in the qcvm without scanning the ast from within ast_member::codegen for an assignments as seen in the added test case. This change makes code like that return a pointer type which will cause an error that we did not get a vector or field back. With pointer support this pointer could actually be used instead. So at least it shouldn't silently produce broken code anymore. Signed-off-by: Wolfgang Bumiller --- ast.cpp | 18 ++++++++++++++---- tests/vecfields-broken.tmpl | 4 ++++ tests/vecfields.qc | 4 ++++ 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 tests/vecfields-broken.tmpl diff --git a/ast.cpp b/ast.cpp index cbc5db9..1ac0a44 100644 --- a/ast.cpp +++ b/ast.cpp @@ -1932,6 +1932,7 @@ bool ast_binstore::codegen(ast_function *func, bool lvalue, ir_value **out) if (!idx->codegen(func, false, &iridx)) return false; } + if (!m_dest->codegen(func, false, &leftr)) return false; @@ -2153,19 +2154,28 @@ bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out) else m_outr = *out; return (*out != nullptr); - } else { - if (!m_owner->codegen(func, false, &vec)) - return false; } + // Vector member access + if (!m_owner->codegen(func, lvalue, &vec)) + return false; + if (vec->m_vtype != TYPE_VECTOR && !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR)) { + compile_error(m_context, "vector member produced neither vector nor field"); return false; } *out = vec->vectorMember(m_field); - m_outl = *out; + if (!*out) { + compile_error(m_context, "internal error: failed to create vector member access"); + return false; + } + if (lvalue) + m_outl = *out; + else + m_outr = *out; return (*out != nullptr); } diff --git a/tests/vecfields-broken.tmpl b/tests/vecfields-broken.tmpl new file mode 100644 index 0000000..59f968b --- /dev/null +++ b/tests/vecfields-broken.tmpl @@ -0,0 +1,4 @@ +I: vecfields.qc +D: vector field member accesses +T: -fail +C: -std=gmqcc -fftepp -DBROKEN_ACCESS diff --git a/tests/vecfields.qc b/tests/vecfields.qc index 6cc053a..815de98 100644 --- a/tests/vecfields.qc +++ b/tests/vecfields.qc @@ -10,4 +10,8 @@ void main() { e.v1 = '1 2 3'; print(ftos(set(e, 42)), " => "); print(vtos(e.v1), "\n"); + +#ifdef BROKEN_ACCESS + (e.v1 = '0 0 0').x += 1; +#endif } -- 2.39.2