NVC++ miscompiles code involving std::tuple

NVC++ miscompiles the following code at any optimisation level:

#include <tuple>
#include <cstdio>

std::tuple<int> foo(const std::tuple<int> in) {
   return true ? in : std::tuple<int>{24};
}

int main(){
  auto x = std::tuple<int>{42};
  auto y = foo(x);
  printf("value=%d valid=%d\n", std::get<0>(y), y==x);
  return 0;
}
> /opt/nvidia/hpc_sdk/Linux_x86_64/24.1/compilers/bin/nvc++ -std=c++17 -O0 -Wall -Wextra  pgi_optional.cpp && ./a.out
value=-1799766024 valid=0
> /opt/nvidia/hpc_sdk/Linux_x86_64/24.1/compilers/bin/nvc++ -std=c++17 -O3 -Wall -Wextra  pgi_optional.cpp && ./a.out
value=1911789704 valid=0

Same thing on 23.11, and reproducible on a local GCC13 Fedora machine and also a GCC 8.3 RHEL 8.2 head node.
As expected, GCC and Clang compiles this correctly.
The constness and the ternary seems to play a role here; I suspect something at the frontend level is misconstructed as replacing the expression-based ternary with an if-else works.

Thanks Tom, I’ve filed a problem report, TPR #35137.

Since the error seemed like a UMR or other memory issue, I ran it through Valgrind and sure enough I see a UMR in the STD when using “-O0”:

==513776== Conditional jump or move depends on uninitialised value(s)
==513776==    at 0x40162F: std::__tuple_compare<std::tuple<int>, std::tuple<int>, 0ul, 1ul>::__eq(std::tuple<int> const&, std::tuple<int> const&) (tuple:1880)
==513776==    by 0x4019F0: bool std::operator==<int, int>(std::tuple<int> const&, std::tuple<int> const&) (tuple:1913)
==513776==    by 0x4012C4: main (test2.cpp:14)

At -O2 or above, I’m not seeing any output or a seg fault, but it’s likely due to the same root cause. Not sure if it’s a compiler front end issue or an issue the STL itself.

-Mat

Hi Tom,

TPR #35137 was fixed in our 24.3 release.

-Mat