https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122922

            Bug ID: 122922
           Summary: Valid code rejected because of interaction of friend
                    function and global module fragment
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: alberto.gcc.bugzilla at gmail dot com
  Target Milestone: ---

Hello

The example bellow works with G++ 15 but is rejected with 16.

This is what I could reduce it to:

// Tensor.cpp
export module VF:Tensor;

import std;

export
namespace VF
{
template<std::size_t d, std::size_t r1>
struct TTensor
{
  TTensor<d, r1 - 1u> TensorArr[d];

  template<std::size_t... i>
  std::istream &Read(std::index_sequence<i...>, std::istream &is)
    { return (is >> ... >> TensorArr[i]); }

  friend std::istream &operator >>(std::istream &is, TTensor<d, r1> &Tensor)
    { return Tensor.Read(std::make_index_sequence<d>{}, is); }
};

template<std::size_t d>
struct TTensor<d, 0u>
{
  double Escalar;

  constexpr TTensor() = default;

  constexpr TTensor(double const Escalar_) :
    Escalar(Escalar_) {}
};

template<std::size_t d>
using TVector = TTensor<d, 1u>;
}

// Malla.cpp
module;

#include <vector>
#include <string>

export module VF:Malla;

import :Tensor;

import std;

namespace VF
{
export
template<std::size_t d>
class TCara
{
private:
  std::vector<TVector<d> const *> const PtoPtrVec;

public:
  TCara(std::vector<TVector<d> const *> &&PtoPtrVec_) :
    PtoPtrVec(std::move(PtoPtrVec_)) {}
};

export
template<std::size_t d>
class TCelda
{
public:
  enum ETipo { TRIAN };

private:
  std::vector<TVector<d> const *> const PtoPtrVec;

private:
  template<ETipo>
  std::vector<TCara<d>> CaraVec_() const;
};

template<>
template<>
std::vector<TCara<2u>>
inline TCelda<2u>::CaraVec_<TCelda<2u>::TRIAN>() const
{
return {{{PtoPtrVec[0u], PtoPtrVec[2u]}},
        {{PtoPtrVec[2u], PtoPtrVec[1u]}},
        {{PtoPtrVec[1u], PtoPtrVec[0u]}}};
}
}

// Campo.cpp
export module VF:Campo;

import :Tensor;

import std;

export
namespace VF
{
template<std::size_t d, std::size_t r>
class TCampo
{
private:
  std::unique_ptr<TTensor<d, r>[]> TensorPtr;

public:
  TCampo(std::size_t N) :
    TensorPtr(std::make_unique<TTensor<d, r>[]>(N)) {}
};
}

// VF.cpp
export module VF;

export import :Tensor;
export import :Malla;
export import :Campo;

// Cavity.cpp
import VF;
import std;

int main()
{
VF::TCampo<2, 1> U(1000);

return 0;
}

/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Tensor.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Malla.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only Campo.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules -fmodule-only VF.cpp -c
/home/alberto/gcc-16/gcc-16/bin/g++ -Wall -Wextra -pedantic -O3 -std=c++23
-fmodules Cavity.cpp -o a.out
En el fichero incluido desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/memory:80,
                 desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/x86_64-pc-linux-gnu/bits/stdc++.h:56,
                 desde
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/std.cc:26,
of module std, imported at Cavity.cpp:3:
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/unique_ptr.h: In
instantiation of ‘constexpr std::__detail::__unique_ptr_array_t<_Tp>
std::make_unique(size_t) [con _Tp = VF::TTensor@VF<2, 1> [];
__detail::__unique_ptr_array_t<_Tp> =
__detail::__unique_ptr_array_t<VF::TTensor@VF<2, 1> []>; size_t = long unsigned
int]’:
required from ‘VF::TCampo@VF<d, r>::TCampo(std::size_t) [con long unsigned int
d = 2; long unsigned int r = 1; std::size_t = long unsigned int]’
Campo.cpp:19:48:   
   19 |     TensorPtr(std::make_unique<TTensor<d, r>[]>(N)) {}
      |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
required from here
Cavity.cpp:7:24:   
    7 | VF::TCampo<2, 1> U(1000);
      |                        ^
/home/alberto/gcc-16/gcc-16/include/c++/16.0.0/bits/unique_ptr.h:1101:30:
error: inicialización por valor del tipo de dato incompleto ‘VF::TTensor@VF<2,
0> [2]’
 1101 |     { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


../gcc-16/gcc-16/bin/g++ -v
Usando especificaciones internas.
COLLECT_GCC=../gcc-16/gcc-16/bin/g++
COLLECT_LTO_WRAPPER=/home/alberto/gcc-16/gcc-16/libexec/gcc/x86_64-pc-linux-gnu/16.0.0/lto-wrapper
Objetivo: x86_64-pc-linux-gnu
Configurado con: ../gcc/configure --enable-languages=c++ --disable-multilib
--disable-bootstrap --prefix=/home/alberto/gcc-16/gcc-16/
Modelo de hilos: posix
Algoritmos de compresión LTO admitidos: zlib zstd
gcc versión 16.0.0 20251129 (experimental) (GCC)

Reply via email to