--- a/lib/C/iec_std_functions.h Sun Oct 14 20:14:13 2018 +0300
+++ b/lib/C/iec_std_functions.h Wed Feb 13 14:16:26 2019 +0000
@@ -1481,46 +1481,100 @@
return __time_add(IN1, IN2);
}
+/* overloaded version of ADD(TIME, TIME) */
+static inline TIME ADD__TIME__TIME__TIME(EN_ENO_PARAMS TIME IN1, TIME IN2){
+ TEST_EN(TIME)
+ return __time_add(IN1, IN2);
+}
+
static inline TOD ADD_TOD_TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){
TEST_EN(TOD)
return __time_add(IN1, IN2);
}
+/* overloaded version of ADD(TOD, TIME) */
+static inline TOD ADD__TOD__TOD__TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){
+ TEST_EN(TIME)
+ return __time_add(IN1, IN2);
+}
+
static inline DT ADD_DT_TIME(EN_ENO_PARAMS DT IN1, TIME IN2){
TEST_EN(DT)
return __time_add(IN1, IN2);
}
+/* overloaded version of ADD(DT, TIME) */
+static inline DT ADD__DT__DT__TIME(EN_ENO_PARAMS DT IN1, TIME IN2){
+ TEST_EN(TIME)
+ return __time_add(IN1, IN2);
+}
+
static inline TIME SUB_TIME(EN_ENO_PARAMS TIME IN1, TIME IN2){
TEST_EN(TIME)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(TIME, TIME) */
+static inline TIME SUB__TIME__TIME__TIME(EN_ENO_PARAMS TIME IN1, TIME IN2){
+ TEST_EN(TIME)
+ return __time_sub(IN1, IN2);
+}
+
static inline TIME SUB_DATE_DATE(EN_ENO_PARAMS DATE IN1, DATE IN2){
TEST_EN(TIME)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(DATE, DATE) */
+static inline TIME SUB__TIME__DATE__DATE(EN_ENO_PARAMS DATE IN1, DATE IN2){
+ TEST_EN(TIME)
+ return __time_sub(IN1, IN2);
+}
+
static inline TOD SUB_TOD_TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){
TEST_EN(TOD)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(TOD, TIME) */
+static inline TOD SUB__TOD__TOD__TIME(EN_ENO_PARAMS TOD IN1, TIME IN2){
+ TEST_EN(TOD)
+ return __time_sub(IN1, IN2);
+}
+
static inline TIME SUB_TOD_TOD(EN_ENO_PARAMS TOD IN1, TOD IN2){
TEST_EN(TIME)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(TOD, TOD) */
+static inline TIME SUB__TIME__TOD__TOD(EN_ENO_PARAMS TOD IN1, TOD IN2){
+ TEST_EN(TIME)
+ return __time_sub(IN1, IN2);
+}
+
static inline DT SUB_DT_TIME(EN_ENO_PARAMS DT IN1, TIME IN2){
TEST_EN(DT)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(DT, TIME) */
+static inline DT SUB__DT__DT__TIME(EN_ENO_PARAMS DT IN1, TIME IN2){
+ TEST_EN(DT)
+ return __time_sub(IN1, IN2);
+}
+
static inline TIME SUB_DT_DT(EN_ENO_PARAMS DT IN1, DT IN2){
TEST_EN(TIME)
return __time_sub(IN1, IN2);
}
+/* overloaded version of SUB(DT, DT) */
+static inline TIME SUB__TIME__DT__DT(EN_ENO_PARAMS DT IN1, DT IN2){
+ TEST_EN(TIME)
+ return __time_sub(IN1, IN2);
+}
+
/*** MULTIME ***/
#define __iec_(TYPENAME)\
@@ -1531,6 +1585,15 @@
__ANY_NUM(__iec_)
#undef __iec_
+/*** MULTIME_TYPENAME ***/
+#define __iec_(TYPENAME)\
+static inline TIME MULTIME_##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\
+ TEST_EN(TIME)\
+ return __time_mul(IN1, (LREAL)IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
/*** MUL ***/
#define __iec_(TYPENAME)\
static inline TIME MUL__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\
@@ -1549,6 +1612,15 @@
__ANY_NUM(__iec_)
#undef __iec_
+/*** DIVTIME_TYPENAME ***/
+#define __iec_(TYPENAME)\
+static inline TIME DIVTIME_##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\
+ TEST_EN(TIME)\
+ return __time_div(IN1, (LREAL)IN2);\
+}
+__ANY_NUM(__iec_)
+#undef __iec_
+
/*** DIV ***/
#define __iec_(TYPENAME)\
static inline TIME DIV__TIME__TIME__##TYPENAME(EN_ENO_PARAMS TIME IN1, TYPENAME IN2){\
--- a/lib/create_standard_function_txt.sh Sun Oct 14 20:14:13 2018 +0300
+++ b/lib/create_standard_function_txt.sh Wed Feb 13 14:16:26 2019 +0000
@@ -836,16 +836,25 @@
/*** Functions of time data types ***/
/**************************************/
-__function_2p(ADD_TIME, TIME, IN1, TIME, IN2, TIME)
-__function_2p(ADD_TOD_TIME, TOD, IN1, TOD, IN2, TIME)
-__function_2p(ADD_DT_TIME, DT, IN1, DT, IN2, TIME)
-
-__function_2p(SUB_TIME, TIME, IN1, TIME, IN2, TIME)
+__function_2p(ADD_TIME, TIME, IN1, TIME, IN2, TIME)
+__function_2p(ADD, TIME, IN1, TIME, IN2, TIME) /* overloaded function */
+__function_2p(ADD_TOD_TIME, TOD, IN1, TOD, IN2, TIME)
+__function_2p(ADD, TOD, IN1, TOD, IN2, TIME) /* overloaded function */
+__function_2p(ADD_DT_TIME, DT, IN1, DT, IN2, TIME)
+__function_2p(ADD, DT, IN1, DT, IN2, TIME) /* overloaded function */
+
+__function_2p(SUB_TIME, TIME, IN1, TIME, IN2, TIME)
+__function_2p(SUB, TIME, IN1, TIME, IN2, TIME) /* overloaded function */
__function_2p(SUB_DATE_DATE, TIME, IN1, DATE, IN2, DATE)
-__function_2p(SUB_TOD_TIME, TOD, IN1, TOD, IN2, TIME)
-__function_2p(SUB_TOD_TOD, TIME, IN1, TOD, IN2, TOD)
-__function_2p(SUB_DT_TIME, DT, IN1, DT, IN2, TIME)
-__function_2p(SUB_DT_DT, TIME, IN1, DT, IN2, DT)
+__function_2p(SUB, TIME, IN1, DATE, IN2, DATE) /* overloaded function */
+__function_2p(SUB_TOD_TIME, TOD, IN1, TOD, IN2, TIME)
+__function_2p(SUB, TOD, IN1, TOD, IN2, TIME) /* overloaded function */
+__function_2p(SUB_TOD_TOD, TIME, IN1, TOD, IN2, TOD )
+__function_2p(SUB, TIME, IN1, TOD, IN2, TOD ) /* overloaded function */
+__function_2p(SUB_DT_TIME, DT, IN1, DT, IN2, TIME)
+__function_2p(SUB, DT, IN1, DT, IN2, TIME) /* overloaded function */
+__function_2p(SUB_DT_DT, TIME, IN1, DT, IN2, DT )
+__function_2p(SUB, TIME, IN1, DT, IN2, DT ) /* overloaded function */
/*** MULTIME ***/
--- a/lib/standard_functions.txt Sun Oct 14 20:14:13 2018 +0300
+++ b/lib/standard_functions.txt Wed Feb 13 14:16:26 2019 +0000
@@ -1763,15 +1763,24 @@
FUNCTION FIND : UDINT VAR_INPUT IN1 : STRING; IN2 : STRING; END_VAR RETURN; END_FUNCTION
FUNCTION FIND : ULINT VAR_INPUT IN1 : STRING; IN2 : STRING; END_VAR RETURN; END_FUNCTION
FUNCTION ADD_TIME : TIME VAR_INPUT IN1 : TIME; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION ADD : TIME VAR_INPUT IN1 : TIME; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION ADD_TOD_TIME : TOD VAR_INPUT IN1 : TOD; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION ADD : TOD VAR_INPUT IN1 : TOD; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION ADD_DT_TIME : DT VAR_INPUT IN1 : DT; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION ADD : DT VAR_INPUT IN1 : DT; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_TIME : TIME VAR_INPUT IN1 : TIME; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : TIME VAR_INPUT IN1 : TIME; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_DATE_DATE : TIME VAR_INPUT IN1 : DATE; IN2 : DATE; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : TIME VAR_INPUT IN1 : DATE; IN2 : DATE; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_TOD_TIME : TOD VAR_INPUT IN1 : TOD; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : TOD VAR_INPUT IN1 : TOD; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_TOD_TOD : TIME VAR_INPUT IN1 : TOD; IN2 : TOD; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : TIME VAR_INPUT IN1 : TOD; IN2 : TOD; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_DT_TIME : DT VAR_INPUT IN1 : DT; IN2 : TIME; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : DT VAR_INPUT IN1 : DT; IN2 : TIME; END_VAR RETURN; END_FUNCTION
FUNCTION SUB_DT_DT : TIME VAR_INPUT IN1 : DT; IN2 : DT; END_VAR RETURN; END_FUNCTION
+FUNCTION SUB : TIME VAR_INPUT IN1 : DT; IN2 : DT; END_VAR RETURN; END_FUNCTION
--- a/stage1_2/iec_flex.ll Sun Oct 14 20:14:13 2018 +0300
+++ b/stage1_2/iec_flex.ll Wed Feb 13 14:16:26 2019 +0000
@@ -247,6 +247,8 @@
void append_bodystate_buffer(const char *text, int is_whitespace = 0);
void unput_bodystate_buffer(void);
int isempty_bodystate_buffer(void);
+void del_bodystate_buffer(void);
+
int GetNextChar(char *b, int maxBuffer);
%}
@@ -1231,12 +1233,12 @@
append_bodystate_buffer(yytext, 1 /* is whitespace */);
}
/* 'INITIAL_STEP' always used in beginning of SFCs !! */
-INITIAL_STEP { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(sfc_state);}
+INITIAL_STEP { if (isempty_bodystate_buffer()) {unput_text(0); del_bodystate_buffer(); BEGIN(sfc_state);}
else {append_bodystate_buffer(yytext);}
}
/* ':=', at the very beginning of a 'body', occurs only in transitions and not Function, FB, or Program bodies! */
-:= { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(st_state);} /* We do _not_ return a start_ST_body_token here, as bison does not expect it! */
+:= { if (isempty_bodystate_buffer()) {unput_text(0); del_bodystate_buffer(); BEGIN(st_state);} /* We do _not_ return a start_ST_body_token here, as bison does not expect it! */
else {append_bodystate_buffer(yytext);}
}
@@ -1257,7 +1259,7 @@
FOR |
WHILE |
EXIT |
-REPEAT { if (isempty_bodystate_buffer()) {unput_text(0); BEGIN(st_state); return start_ST_body_token;}
+REPEAT { if (isempty_bodystate_buffer()) {unput_text(0); del_bodystate_buffer(); BEGIN(st_state); return start_ST_body_token;}
else {append_bodystate_buffer(yytext);}
}
@@ -2183,6 +2185,16 @@
}
+/* Delete all data in bodystate. */
+/* Will be used to delete ST whitespace when not needed. If not deleted this whitespace
+ * will be prepended to the next text block of code being appended to bodystate_buffer,
+ * which may cause trouble if it is IL code
+ */
+void del_bodystate_buffer(void) {
+ free(bodystate_buffer);
+ bodystate_buffer = NULL;
+ bodystate_is_whitespace = 1;
+}
/* Called by flex when it reaches the end-of-file */
--- a/stage3/fill_candidate_datatypes.cc Sun Oct 14 20:14:13 2018 +0300
+++ b/stage3/fill_candidate_datatypes.cc Wed Feb 13 14:16:26 2019 +0000
@@ -2011,7 +2011,7 @@
* We do not need to generate an error message. This error will be caught somewhere else!
*/
if (NULL == prev_il_instruction) return NULL;
- if (NULL == il_operand) return NULL;
+ if (NULL != il_operand) return NULL;
for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
if (get_datatype_info_c::is_ANY_BIT_compatible(prev_il_instruction->candidate_datatypes[i]))
add_datatype_to_candidate_list(symbol, prev_il_instruction->candidate_datatypes[i]);
--- a/stage4/generate_c/generate_c.cc Sun Oct 14 20:14:13 2018 +0300
+++ b/stage4/generate_c/generate_c.cc Wed Feb 13 14:16:26 2019 +0000
@@ -544,9 +544,27 @@
/***********************************************************************/
/***********************************************************************/
-#define MILLISECOND 1000000
+#define MILLISECOND ((unsigned long long)1000000)
#define SECOND 1000 * MILLISECOND
+#define ULL_MAX std::numeric_limits<unsigned long long>::max()
+
+/* unsigned long long -> multiply and add : time_var += interval * multiplier */
+/* note: multiplier must be <> 0 due to overflow test */
+#define ULL_MUL_ADD(time_var, interval, multiplier, overflow_flag) { \
+ /* Test overflow on MUL by pre-condition: If (ULL_MAX / a) < b => overflow! */ \
+ overflow_flag |= ((ULL_MAX / (multiplier)) < GET_CVALUE(uint64, interval)); \
+ /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */ \
+ overflow_flag |= ((ULL_MAX - (GET_CVALUE(uint64, interval) * multiplier)) < time_var); \
+ time_var += GET_CVALUE(uint64, interval) * (multiplier); \
+}
+
+/* long double -> multiply and add : time_var += interval * multiplier */
+#define LDB_MUL_ADD(time_var, interval, multiplier) { \
+ time_var += GET_CVALUE(real64, interval) * (multiplier); \
+}
+
+
unsigned long long calculate_time(symbol_c *symbol) {
if (NULL == symbol) return 0;
@@ -567,52 +585,54 @@
/* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
unsigned long long int time_ull = 0;
long double time_ld = 0;
- /*
- const unsigned long long int MILLISECOND = 1000000;
- const unsigned long long int SECOND = 1000 * MILLISECOND
- */
+ bool ovflow = false;
if (NULL != interval->milliseconds) {
if (VALID_CVALUE( int64, interval->milliseconds) && GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive!
- if (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND;
- else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND;
- else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND;
+ if (VALID_CVALUE(uint64, interval->milliseconds)) ULL_MUL_ADD(time_ull, interval->milliseconds, MILLISECOND, ovflow)
+ else if (VALID_CVALUE(real64, interval->milliseconds)) LDB_MUL_ADD(time_ld , interval->milliseconds, MILLISECOND)
else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value!
}
if (NULL != interval->seconds ) {
if (VALID_CVALUE( int64, interval->seconds ) && GET_CVALUE( int64, interval->seconds ) < 0) ERROR; // interval elements should always be positive!
- if (VALID_CVALUE( int64, interval->seconds )) time_ull += GET_CVALUE( int64, interval->seconds ) * SECOND;
- else if (VALID_CVALUE(uint64, interval->seconds )) time_ull += GET_CVALUE(uint64, interval->seconds ) * SECOND;
- else if (VALID_CVALUE(real64, interval->seconds )) time_ld += GET_CVALUE(real64, interval->seconds ) * SECOND;
+ if (VALID_CVALUE(uint64, interval->seconds )) ULL_MUL_ADD(time_ull, interval->seconds, SECOND, ovflow)
+ else if (VALID_CVALUE(real64, interval->seconds )) LDB_MUL_ADD(time_ld , interval->seconds, SECOND)
else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value!
}
if (NULL != interval->minutes ) {
if (VALID_CVALUE( int64, interval->minutes ) && GET_CVALUE( int64, interval->minutes ) < 0) ERROR; // interval elements should always be positive!
- if (VALID_CVALUE( int64, interval->minutes )) time_ull += GET_CVALUE( int64, interval->minutes ) * SECOND * 60;
- else if (VALID_CVALUE(uint64, interval->minutes )) time_ull += GET_CVALUE(uint64, interval->minutes ) * SECOND * 60;
- else if (VALID_CVALUE(real64, interval->minutes )) time_ld += GET_CVALUE(real64, interval->minutes ) * SECOND * 60;
+ if (VALID_CVALUE(uint64, interval->minutes )) ULL_MUL_ADD(time_ull, interval->minutes, SECOND * 60, ovflow)
+ else if (VALID_CVALUE(real64, interval->minutes )) LDB_MUL_ADD(time_ld , interval->minutes, SECOND * 60)
else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value!
}
if (NULL != interval->hours ) {
if (VALID_CVALUE( int64, interval->hours ) && GET_CVALUE( int64, interval->hours ) < 0) ERROR; // interval elements should always be positive!
- if (VALID_CVALUE( int64, interval->hours )) time_ull += GET_CVALUE( int64, interval->hours ) * SECOND * 60 * 60;
- else if (VALID_CVALUE(uint64, interval->hours )) time_ull += GET_CVALUE(uint64, interval->hours ) * SECOND * 60 * 60;
- else if (VALID_CVALUE(real64, interval->hours )) time_ld += GET_CVALUE(real64, interval->hours ) * SECOND * 60 * 60;
+ if (VALID_CVALUE(uint64, interval->hours )) ULL_MUL_ADD(time_ull, interval->hours, SECOND * 60 * 60, ovflow)
+ else if (VALID_CVALUE(real64, interval->hours )) LDB_MUL_ADD(time_ld , interval->hours, SECOND * 60 * 60)
else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value!
}
if (NULL != interval->days ) {
if (VALID_CVALUE( int64, interval->days ) && GET_CVALUE( int64, interval->days ) < 0) ERROR; // interval elements should always be positive!
- if (VALID_CVALUE( int64, interval->days )) time_ull += GET_CVALUE( int64, interval->days ) * SECOND * 60 * 60 * 24;
- else if (VALID_CVALUE(uint64, interval->days )) time_ull += GET_CVALUE(uint64, interval->days ) * SECOND * 60 * 60 * 24;
- else if (VALID_CVALUE(real64, interval->days )) time_ld += GET_CVALUE(real64, interval->days ) * SECOND * 60 * 60 * 24;
+ if (VALID_CVALUE(uint64, interval->days )) ULL_MUL_ADD(time_ull, interval->days, SECOND * 60 * 60 * 24, ovflow)
+ else if (VALID_CVALUE(real64, interval->days )) LDB_MUL_ADD(time_ld , interval->days, SECOND * 60 * 60 * 24)
else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value!
}
+ /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */
+ ovflow |= ((ULL_MAX - time_ull) < (unsigned long long)time_ld);
time_ull += time_ld;
+
+ if (ovflow) {
+ /* time is being stored in ns resolution (MILLISECOND #define is set to 1000000) */
+ /* time is being stored in unsigned long long (ISO C99 guarantees at least 64 bits) */
+ /* 2⁶64ns works out to around 584.5 years, assuming 365.25 days per year */
+ STAGE4_ERROR(symbol, symbol, "Internal overflow calculating task interval (must be < 584 years).");
+ }
+
return time_ull;
};
ERROR; // should never reach this point!
@@ -642,8 +662,10 @@
else
return euclide(b, c);
}
-
- void update_ticktime(unsigned long long time) {
+
+ bool update_ticktime(unsigned long long time) {
+ bool overflow = false;
+
if (common_ticktime == 0)
common_ticktime = time;
else if (time > common_ticktime)
@@ -652,10 +674,14 @@
common_ticktime = euclide(common_ticktime, time);
if (least_common_ticktime == 0)
least_common_ticktime = time;
- else
- least_common_ticktime = (least_common_ticktime * time) / common_ticktime;
- }
-
+ else {
+ /* Test overflow on MUL by pre-condition: If (ULL_MAX / a) < b => overflow! */
+ overflow = ((ULL_MAX / least_common_ticktime) < (time / common_ticktime));
+ least_common_ticktime = least_common_ticktime * (time / common_ticktime);
+ }
+ return !overflow;
+ }
+
unsigned long long get_common_ticktime(void) {
return common_ticktime;
}
@@ -671,9 +697,12 @@
//SYM_REF2(task_configuration_c, task_name, task_initialization)
void *visit(task_initialization_c *symbol) {
if (symbol->interval_data_source != NULL) {
- unsigned long long time = calculate_time(symbol->interval_data_source);
- if (time < 0) ERROR;
- else update_ticktime(time);
+ unsigned long long time = calculate_time(symbol->interval_data_source);
+ if (!update_ticktime(time))
+ /* time is being stored in ns resolution (MILLISECOND #define is set to 1000000) */
+ /* time is being stored in unsigned long long (ISO C99 guarantees at least 64 bits) */
+ /* 2⁶64ns works out to around 584.5 years, assuming 365.25 days per year */
+ STAGE4_ERROR(symbol, symbol, "Internal overflow calculating least common multiple of task intervals (must be < 584 years).");
}
return NULL;
}
@@ -2670,6 +2699,8 @@
config_s4o.print("unsigned long long common_ticktime__ = ");
config_s4o.print_long_long_integer(common_ticktime);
+ config_s4o.print(" * ");
+ config_s4o.print_long_long_integer(1000000 / MILLISECOND);
config_s4o.print("; /*ns*/\n");
config_s4o.print("unsigned long greatest_tick_count__ = (unsigned long)");
config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count());
--- a/stage4/generate_c/generate_c_st.cc Sun Oct 14 20:14:13 2018 +0300
+++ b/stage4/generate_c/generate_c_st.cc Wed Feb 13 14:16:26 2019 +0000
@@ -937,7 +937,7 @@
/* B 3.2.1 Assignment Statements */
/*********************************/
void *visit(assignment_statement_c *symbol) {
- symbol_c *left_type = search_varfb_instance_type->get_type_id(symbol->l_exp);
+ symbol_c *left_type = symbol->l_exp->datatype;
if (this->is_variable_prefix_null()) {
symbol->l_exp->accept(*this);