From 2299a2d4858dae1f60533b37bb7a776142b88870 Mon Sep 17 00:00:00 2001 From: Greg Hewgill Date: Fri, 31 Mar 2017 14:58:13 +1300 Subject: [PATCH] Fix internal compiler error with certain kinds of INOUT parameters (issue #146) --- src/analyzer.cpp | 3 +++ src/ast.h | 5 +++++ t/errors/N3241.neon | 6 ++++++ t/parameter-inout-array.neon | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 t/errors/N3241.neon diff --git a/src/analyzer.cpp b/src/analyzer.cpp index dc75a3cbf9..195fd01285 100644 --- a/src/analyzer.cpp +++ b/src/analyzer.cpp @@ -1561,6 +1561,9 @@ const ast::Expression *Analyzer::analyze(const pt::FunctionCallExpression *expr) if (not e->type->is_assignment_compatible(ftype->params[p]->type)) { error2(3194, a->expr->token, "type mismatch", ftype->params[p]->declaration, "function argument here"); } + if (ftype->params[p]->mode == ast::ParameterType::INOUT && not ref->can_generate_address()) { + error(3241, a->expr->token, "using this kind of expression with an INOUT parameter is currently not supported"); + } } if (ftype->params[p]->mode == ast::ParameterType::OUT && a->mode.type != OUT) { error(3184, a->expr->token, "OUT keyword required"); diff --git a/src/ast.h b/src/ast.h index 5cf075fe5b..ae7c499247 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1629,6 +1629,7 @@ class ReferenceExpression: public Expression { ReferenceExpression(const Type *type, bool is_readonly): Expression(type, false, is_readonly) {} virtual void generate_expr(Emitter &emitter) const override { generate_load(emitter); } + virtual bool can_generate_address() const { return true; } virtual void generate_address_read(Emitter &) const = 0; virtual void generate_address_write(Emitter &) const = 0; virtual void generate_load(Emitter &) const; @@ -1646,6 +1647,7 @@ class DummyExpression: public ReferenceExpression { virtual bool eval_boolean() const override { internal_error("DummyExpression"); } virtual Number eval_number() const override { internal_error("DummyExpression"); } virtual std::string eval_string() const override { internal_error("DummyExpression"); } + virtual bool can_generate_address() const { return false; } virtual void generate_address_read(Emitter &) const override { internal_error("DummyExpression"); } virtual void generate_address_write(Emitter &) const override { internal_error("DummyExpression"); } virtual void generate_load(Emitter &) const override { internal_error("DummyExpression"); } @@ -1751,6 +1753,7 @@ class StringReferenceIndexExpression: public ReferenceExpression { virtual bool eval_boolean() const override { internal_error("StringReferenceIndexExpression"); } virtual Number eval_number() const override { internal_error("StringReferenceIndexExpression"); } virtual std::string eval_string() const override { internal_error("StringReferenceIndexExpression"); } + virtual bool can_generate_address() const { return false; } virtual void generate_address_read(Emitter &) const override { internal_error("StringReferenceIndexExpression"); } virtual void generate_address_write(Emitter &) const override { internal_error("StringReferenceIndexExpression"); } virtual void generate_load(Emitter &) const override; @@ -1803,6 +1806,7 @@ class BytesReferenceIndexExpression: public ReferenceExpression { virtual bool eval_boolean() const override { internal_error("BytesReferenceIndexExpression"); } virtual Number eval_number() const override { internal_error("BytesReferenceIndexExpression"); } virtual std::string eval_string() const override { internal_error("BytesReferenceIndexExpression"); } + virtual bool can_generate_address() const { return false; } virtual void generate_address_read(Emitter &) const override { internal_error("BytesReferenceIndexExpression"); } virtual void generate_address_write(Emitter &) const override { internal_error("BytesReferenceIndexExpression"); } virtual void generate_load(Emitter &) const override; @@ -1896,6 +1900,7 @@ class ArrayReferenceRangeExpression: public ReferenceExpression { virtual bool eval_boolean() const override { internal_error("ArrayReferenceRangeExpression"); } virtual Number eval_number() const override { internal_error("ArrayReferenceRangeExpression"); } virtual std::string eval_string() const override { internal_error("ArrayReferenceRangeExpression"); } + virtual bool can_generate_address() const { return false; } virtual void generate_address_read(Emitter &) const override { internal_error("StringReferenceRangeExpression"); } virtual void generate_address_write(Emitter &) const override { internal_error("StringReferenceRangeExpression"); } virtual void generate_load(Emitter &) const override; diff --git a/t/errors/N3241.neon b/t/errors/N3241.neon new file mode 100644 index 0000000000..a7fa2407e4 --- /dev/null +++ b/t/errors/N3241.neon @@ -0,0 +1,6 @@ +FUNCTION a_inout(INOUT p: Array) +END FUNCTION + +VAR a: Array := [] +a_inout(INOUT a[0 TO 4]) + %< diff --git a/t/parameter-inout-array.neon b/t/parameter-inout-array.neon index 9bac21912c..2d42cffc69 100644 --- a/t/parameter-inout-array.neon +++ b/t/parameter-inout-array.neon @@ -1,4 +1,4 @@ -% TODO +% TODO https://github.com/ghewgill/neon-lang/issues/146 FUNCTION a_inout(INOUT p: Array) p := [1, 2] END FUNCTION