Problem
Summary
When NOT is applied to a boolean expression built from integer comparisons,
STruC++ emits a C++ NOT(<int>) call. The runtime NOT template is constrained
to any-bit types (is_any_bit_v<T>), and the negated expression has already
been promoted to int, so g++ reports no matching function for call to
NOT(int). Codegen succeeds; the resulting C++ does not compile.
Environment
- STruC++ version: 0.6.2, runtime
iec_std_lib.hpp
- C++ compiler: g++ (MSYS2 UCRT64) 15.1.0,
-std=c++17
Impact
g++ failed
Reproduction
not_int.st:
PROGRAM PLC_PRG
VAR
a : DINT;
b : DINT;
r : DINT;
END_VAR
r := TO_DINT(NOT( (a = 0) OR (b = 0) ));
END_PROGRAM
strucpp not_int.st -o not_int.cpp --no-default-libs
g++ -std=c++17 -I<strucpp>/runtime/include -c not_int.cpp
Actual result
strucpp reports Compilation successful! and emits:
R = TO_DINT(NOT(((A == 0)) | ((B == 0))));
g++ then fails:
not_int.cpp:43:20: error: no matching function for call to 'NOT(int)'
43 | R = TO_DINT(NOT(((A == 0)) | ((B == 0))));
iec_std_lib.hpp:1258: note: candidate:
'template<class T, std::enable_if_t<is_any_bit_v<T>, int> = ...> T NOT(T)'
iec_std_lib.hpp:1258: note: template argument deduction/substitution failed:
iec_std_lib.hpp:1257: error: no type named 'type' in 'struct std::enable_if<false, int>'
The operands of | and == are bool/int comparison results; C++ promotes
the whole expression to int, so the argument to NOT is int, which is not
an "any-bit" type — deduction fails.
Code Locations
No response
Fix
Root cause
Two interacting problems:
- The negated expression's C++ type collapses to
int (via the usual
arithmetic promotions in == / |) instead of staying a BOOL/bit type.
- The runtime
NOT overload set has no overload for that promoted int —
it only matches is_any_bit_v<T> (BOOL/BYTE/WORD/…).
Suggested fixes
- Preserve the boolean type: emit the sub-expression so its result stays a
bit type (e.g. an IEC_BOOL temporary), so NOT binds to its
is_any_bit_v overload. Preferred — keeps IEC typing correct.
- Or add a
NOT overload for integral/bool arguments in iec_std_lib.hpp that
returns the boolean complement.
- Or, when the operand is known-boolean at codegen, emit the C++
! operator
on an explicitly IEC_BOOL-typed temporary instead of a bare
NOT(<promoted int>).
Acceptance
NOT on a boolean expression is boolean negation and should compile. The
emitted code should call NOT on a BOOL/bit type, not on a promoted int.
Problem
Summary
When
NOTis applied to a boolean expression built from integer comparisons,STruC++ emits a C++
NOT(<int>)call. The runtimeNOTtemplate is constrainedto any-bit types (
is_any_bit_v<T>), and the negated expression has alreadybeen promoted to
int, so g++ reports no matching function for call toNOT(int). Codegen succeeds; the resulting C++ does not compile.Environment
iec_std_lib.hpp-std=c++17Impact
g++ failed
Reproduction
not_int.st:Actual result
strucppreportsCompilation successful!and emits:g++ then fails:
The operands of
|and==arebool/intcomparison results; C++ promotesthe whole expression to
int, so the argument toNOTisint, which is notan "any-bit" type — deduction fails.
Code Locations
No response
Fix
Root cause
Two interacting problems:
int(via the usualarithmetic promotions in
==/|) instead of staying aBOOL/bit type.NOToverload set has no overload for that promotedint—it only matches
is_any_bit_v<T>(BOOL/BYTE/WORD/…).Suggested fixes
bit type (e.g. an
IEC_BOOLtemporary), soNOTbinds to itsis_any_bit_voverload. Preferred — keeps IEC typing correct.NOToverload for integral/bool arguments iniec_std_lib.hppthatreturns the boolean complement.
!operatoron an explicitly
IEC_BOOL-typed temporary instead of a bareNOT(<promoted int>).Acceptance
NOTon a boolean expression is boolean negation and should compile. Theemitted code should call
NOTon aBOOL/bit type, not on a promotedint.