https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115870
Bug ID: 115870
Summary: Inlining of a template function leads to infinite loop
Product: gcc
Version: 12.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: Manuel.Demmeler at kuka dot com
Target Milestone: ---
Created attachment 58635
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58635&action=edit
Preprocessed file from "/usr/bin/gcc -save-temps -Wall -O2 -g -Wextra -o
out/main main.cpp"
The minimal example below compiled with
```
/usr/bin/gcc -save-temps -Wall -O2 -g -Wextra -o out/main main.cpp
```
produces an endless loop when executing the program and the following
compilation output:
```
In member function 'int CArray<N>::foo(int, int) const [with int N = 10]',
inlined from 'int CArray<N>::foo(int, int) const [with int N = 11]' at
main.cpp:24:8,
inlined from 'int main()' at main.cpp:49:23:
main.cpp:30:10: warning: iteration 10 invokes undefined behavior
[-Waggressive-loop-optimizations]
30 | for (int idx{0U}; idx < num; ++idx)
| ^~~
main.cpp:30:32: note: within this loop
30 | for (int idx{0U}; idx < num; ++idx)
| ~~~~^~~~~
```
It looks like the compiler confuses the different instances of the template
function for parameters N = 10 and 11.
Further, if using int_type = uint32_t, the above warning is missing and the
endless loop is still produced.
Note that the endless loop can also easily be seen in the assembler output:
https://godbolt.org/z/9P8bY3TK6
main.cpp:
```
#include <cstdint>
using int_type = int;
int_type bar(uint8_t const * const s, int_type const len)
{
return s[0] + s[len-1];
}
template<int_type N>
class CArray final
{
public:
// (......)
int_type foo(int_type const initialValue, int_type const num) const
{
int_type retVal{initialValue};
if (num <= N)
{
for (int_type idx{0U}; idx < num; ++idx)
{
retVal += bar(reinterpret_cast<uint8_t const *>(&m_values[idx]),
sizeof(int_type));
}
}
return retVal;
}
private:
int_type m_values[N]{};
};
int main()
{
CArray<10U> array1{};
CArray<11U> array2{};
int_type foo1{array1.foo(1U, 10U)};
int_type foo2{array2.foo(1U, 11U)};
return foo1 + foo2;
}
```
Used version: g++ (Debian 12.2.0-14) 12.2.0