From b709da7f17c683ba943159929c8310794112e0f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Thu, 27 Jan 2022 15:52:59 +0100
Subject: [PATCH] =?UTF-8?q?Fix=20SymbolTable=E2=80=99s=20getOrigSymbIdForA?=
 =?UTF-8?q?uxVar()=20and=20getUltimateOrigSymbID()=20so=20that=20they=20ne?=
 =?UTF-8?q?ver=20return=20-1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The case of a diff aux var corresponding to a complex expression was not
correctly handled, and could lead to a value -1 being returned by these
methods.
---
 src/DynamicModel.cc |  4 +---
 src/SymbolTable.cc  |  7 +++++--
 src/SymbolTable.hh  | 12 ++++++++----
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index c59b9be1..4dfefec0 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -4764,9 +4764,7 @@ DynamicModel::createVariableMapping()
       equations[ii]->collectVariables(SymbolType::endogenous, eqvars);
       equations[ii]->collectVariables(SymbolType::exogenous, eqvars);
       for (auto eqvar : eqvars)
-        if (int orig_symb_id = symbol_table.getUltimateOrigSymbID(eqvar);
-            orig_symb_id >= 0)
-        variableMapping[orig_symb_id].emplace(ii);
+        variableMapping[symbol_table.getUltimateOrigSymbID(eqvar)].emplace(ii);
     }
 }
 
diff --git a/src/SymbolTable.cc b/src/SymbolTable.cc
index 32ea5670..e9899fca 100644
--- a/src/SymbolTable.cc
+++ b/src/SymbolTable.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2021 Dynare Team
+ * Copyright © 2003-2022 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -726,7 +726,10 @@ SymbolTable::getOrigSymbIdForAuxVar(int aux_var_symb_id) const noexcept(false)
          || aux_var.get_type() == AuxVarType::diffLag
          || aux_var.get_type() == AuxVarType::diffLead)
         && aux_var.get_symb_id() == aux_var_symb_id)
-      return aux_var.get_orig_symb_id();
+      if (int r = aux_var.get_orig_symb_id(); r >= 0)
+        return r;
+      else
+        throw UnknownSymbolIDException(aux_var_symb_id); // Some diff var have orig_symb_id == -1
   throw UnknownSymbolIDException(aux_var_symb_id);
 }
 
diff --git a/src/SymbolTable.hh b/src/SymbolTable.hh
index cb4a7ab7..adab581a 100644
--- a/src/SymbolTable.hh
+++ b/src/SymbolTable.hh
@@ -319,7 +319,9 @@ public:
   /* Searches aux_vars for the aux var represented by aux_var_symb_id and
      returns its associated orig_symb_id.
      Works only for endoLag, exoLag, diff, diffLag, diffLead.
-     Throws an UnknownSymbolIDException otherwise.
+     Throws an UnknownSymbolIDException if there is no orig_symb_id associated to
+     this aux var (either because it’s of the wrong type, or because there is
+     no such orig var for this specific aux var, e.g. a diff for a complex expression).
      N.B.: some code might rely on the fact that, in particular, it does not work on unaryOp
      type (to be verified) */
   int getOrigSymbIdForAuxVar(int aux_var_symb_id) const noexcept(false);
@@ -433,9 +435,11 @@ public:
   //! Get list of endogenous variables without aux vars
   set <int> getOrigEndogenous() const;
   //! Returns the original symbol corresponding to this variable
-  /* If symb_id is not an auxiliary var, returns symb_id. Otherwise,
-     repeatedly call getOrigSymbIDForAuxVar() until an original
-     (non-auxiliary) variable is found. */
+  /* If symb_id has no original variable, returns symb_id. Otherwise,
+     repeatedly call getOrigSymbIDForAuxVar() until an original variable is
+     found. Note that the result may be an auxiliary variable if the latter has
+     no original variable (e.g. aux var for lead, Lagrange Multiplier or diff
+     associated to a complex expression). */
   int getUltimateOrigSymbID(int symb_id) const;
   //! If this is a Lagrange multiplier, return its associated equation number; otherwise return -1
   int getEquationNumberForMultiplier(int symb_id) const;
-- 
GitLab