hahnjo wrote:

Thanks, the reproducer is indeed useful. The first "bad" commit is the second 
`Complete only needed partial specializations`.

I was manually able to further reduce the example (throwing out empty files & 
modules, inline through typedefs, etc)

<details><summary>Smaller reproducer</summary>

```
//--- 2OT.h
#include "LQ1.h"

namespace ciy {
namespace xqk {
template <typename>
class vum {
 public:
  using sc = std::C::wmd;
  friend bool operator==(vum, vum);
};
template <typename>
class me {
 public:
  using vbh = vum<me>;
  using sc = std::C::vy<vbh>::sc;
  template <typename db>
  operator db() { return {}; }
};
}  // namespace xqk
template <typename vus>
xqk::me<vus> uvo(std::C::wmd, vus);
}  // namespace ciy

class ua {
  std::C::wmd kij() {
    ciy::uvo(kij(), '-');
    return {};
  }
};

//--- 9KF.h
#include "LQ1.h"
#include "2OT.h"
namespace {
void al(std::C::wmd lou) { std::C::jv<std::C::wmd> yt = ciy::uvo(lou, '/'); }
}  // namespace

//--- CMO.cppmap
module "hf" {
header "LQ1.h"
}


//--- E6H.cppmap
module "g" {
export *
header "2OT.h"
}


//--- HMT.cppmap
module "r" {
header "2OT.h"
}


//--- JOV.cppmap
module "q" {
header "9KF.h"
}


//--- LQ1.h
namespace std {
namespace C {
template <class zd>
struct vy : zd {};
template <class ub>
struct vy<ub*> {
  typedef ub jz;
};
struct wmd {};
template <class uo, class zt>
void sk(uo k, zt gf) {
  (void)(k != gf);
}
template <class uo>
class fm {
 public:
  fm(uo);
};
template <class kj, class kju>
bool operator==(kj, kju);
template <class epn>
void afm(epn) {
  using yp = vy<epn>;
  if (__is_trivially_copyable(yp)) {
    sk(fm(epn()), nullptr);
  }
}
template <class ub>
class jv {
 public:
  constexpr void gq();
  ub *nef;
};
template <class ub>
constexpr void jv<ub>::gq() {
    afm(nef);
}
}  // namespace C
}  // namespace std
namespace ciy {
}  // namespace ciy

//--- Makefile
.ALWAYS:
FZV.o: .ALWAYS WI9.pcm 4BK.pcm LUM.pcm 9VX.pcm
        $(CLANG) -fmodule-name=p -Xclang=-fno-cxx-modules -fmodules 
-fno-implicit-modules -fno-implicit-module-maps -Xclang=-fmodule-file=9VX.pcm 
-fmodule-map-file=CMO.cppmap -std=gnu++20 -c XFD.cc -o FZV.o
WI9.pcm: .ALWAYS
        $(CLANG) -fmodule-name=hf -fmodule-map-file=CMO.cppmap 
-Xclang=-fno-cxx-modules -xc++ -Xclang=-emit-module -fmodules 
-fno-implicit-modules -fno-implicit-module-maps -std=gnu++20 -c CMO.cppmap -o 
WI9.pcm
4BK.pcm: .ALWAYS WI9.pcm
        $(CLANG) -fmodule-name=g -fmodule-map-file=E6H.cppmap 
-Xclang=-fno-cxx-modules -xc++ -Xclang=-emit-module -fmodules 
-fno-implicit-modules -fno-implicit-module-maps -Xclang=-fmodule-file=WI9.pcm 
-fmodule-map-file=CMO.cppmap -std=gnu++20 -c E6H.cppmap -o 4BK.pcm
LUM.pcm: .ALWAYS WI9.pcm
        $(CLANG) -fmodule-name=r -fmodule-map-file=HMT.cppmap 
-Xclang=-fno-cxx-modules -xc++ -Xclang=-emit-module -fmodules 
-fno-implicit-modules -fno-implicit-module-maps -Xclang=-fmodule-file=WI9.pcm 
-fmodule-map-file=CMO.cppmap -std=gnu++20 -c HMT.cppmap -o LUM.pcm
9VX.pcm: .ALWAYS WI9.pcm 4BK.pcm LUM.pcm
        $(CLANG) -fmodule-name=q -fmodule-map-file=JOV.cppmap 
-Xclang=-fno-cxx-modules -xc++ -Xclang=-emit-module -fmodules 
-fno-implicit-modules -fno-implicit-module-maps -Xclang=-fmodule-file=LUM.pcm 
-Xclang=-fmodule-file=4BK.pcm -fmodule-map-file=CMO.cppmap -std=gnu++20 -c 
JOV.cppmap -o 9VX.pcm
.PHONY: clean
clean:
        find . \( -name '*.pcm' -o -name '*.o' \) -delete

//--- XFD.cc
#include "LQ1.h"
#include "2OT.h"
class wiy {
 public:
  std::C::wmd eyb();
};
template <typename wpa>
void i(wpa fg) {
  std::C::jv<std::C::wmd> zs;
  zs = ciy::uvo(fg.eyb(), '\n');
}
namespace ciy {
namespace xqk {
struct sbv;
std::C::jv<sbv> ns() {
  std::C::jv<sbv> ubs;
  ubs.gq();
  return ubs;
}
}  // namespace xqk
}  // namespace ciy
void s() {
  wiy fg;
  i(fg);
}
```
</details>

The failure with modules and this PR is:
```
XFD.cc:10:6: error: use of overloaded operator '=' is ambiguous (with operand 
types 'std::C::jv<std::C::wmd>' and 'xqk::me<char>')
   10 |   zs = ciy::uvo(fg.eyb(), '\n');
      |   ~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
XFD.cc:24:3: note: in instantiation of function template specialization 
'i<wiy>' requested here
   24 |   i(fg);
      |   ^
./LQ1.h:29:7: note: candidate function (the implicit copy assignment operator)
   29 | class jv {
      |       ^
./LQ1.h:29:7: note: candidate function (the implicit move assignment operator)
```

Two observations:
1. There is a diamond module structure: Both `4BK.pcm` and `LUM.pcm` depend on 
`WI9.pcm` and contain `2OT.h` with different module names (I removed transitive 
empty includes). I'm not sure if this is valid... @emaxx-google is it possible 
to share the modulemap for Abseil? We should check if all private headers that 
are potentially used by multiple "public" modules are correctly taken care of.
2. The problem is the conversion operator `xqk::me` that is declared as 
`template`. I *think* the problem is that an object can be implicitly converted 
into multiple temporaries that can either be copy- or move-constructed.

https://github.com/llvm/llvm-project/pull/133057
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to