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

Reply via email to