From 7b3df21f11b81c83938abd982575260ab61c993a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Fri, 16 Apr 2021 17:34:13 +0200
Subject: [PATCH] DataTree::operator=(): fix crash when symbol ID ordering of
 model local variables does not correspond to the recursive ordering in the
 model block

Ref. dynare#1782
---
 src/DataTree.cc      | 11 +++++++----
 src/ParsingDriver.cc |  4 +++-
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/DataTree.cc b/src/DataTree.cc
index 5649aa0e..1906212a 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2020 Dynare Team
+ * Copyright © 2003-2021 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -99,9 +99,12 @@ DataTree::operator=(const DataTree &d)
   initConstants();
 
   /* Model local variables must be next, because they can be evaluated in Add*
-     methods when the model equations are added */
-  for (const auto &it : d.local_variables_table)
-    local_variables_table[it.first] = it.second->clone(*this);
+     methods when the model equations are added. They need to be cloned in
+     order of appearance in the model block (hence with
+     local_variables_vector), because if there is a model_local_variable statement
+     the symbol IDs ordering may not be the right one (see dynare#1782) */
+  for (const auto &id : d.local_variables_vector)
+    local_variables_table[id] = d.local_variables_table.at(id)->clone(*this);
 
   for (const auto &it : d.node_list)
     it->clone(*this);
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 4670113b..51cd2943 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -2368,7 +2368,9 @@ ParsingDriver::declare_and_init_model_local_variable(const string &name, expr_t
     }
   catch (SymbolTable::AlreadyDeclaredException &e)
     {
-      // It can have already been declared in a steady_state_model block, check that it is indeed a ModelLocalVariable
+      /* It can have already been declared in a steady_state_model block or
+         model_local_variable statement, check that it is indeed a
+         ModelLocalVariable */
       symb_id = mod_file->symbol_table.getID(name);
       if (mod_file->symbol_table.getType(symb_id) != SymbolType::modelLocalVariable)
         error(name + " has wrong type or was already used on the right-hand side. You cannot use it on the left-hand side of a pound ('#') expression");
-- 
GitLab