<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/64091>64091</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [ODRHash] Regression after f82df0b285ac
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:modules
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ChuanqiXu9
      </td>
    </tr>
</table>

<pre>
    This comes from https://reviews.llvm.org/D154324.

I registered the issue for tracking it formally.

The reproducer reported is:

```
$ cat a.cppmap
module "a" {
  export *
  module "a.h" {
 export *
    header "a.h"
  }
  use "c"
}
$ cat b.cppmap
module "b" {
  export *
  module "b.h" {
    export *
    header "b.h"
  }
  use "c"
}
$ cat c.cppmap
module "c" {
  export *
  module "c1.h" {
    export *
    textual header "c1.h"
  }
  module "c2.h" {
    export *
    textual header "c2.h"
  }
  module "c3.h" {
    export *
    textual header "c3.h"
  }
}
$ cat test.cppmap
module "test" {
  export *
  use "a"
  use "b"
}
$ cat a.h
#ifndef A_H_
#define A_H_

#include "c1.h"

namespace q {
template <typename T,
          typename std::enable_if<::p::P<T>::value>::type>
class X {};
}  // namespace q

#include "c3.h"

#endif  // A_H_
$ cat b.h
#ifndef B_H_
#define B_H_

#include "c2.h"

#endif  // B_H_
$ cat c1.h
#ifndef C1_H_
#define C1_H_

namespace std {
template <class _Tp, _Tp __v>
struct integral_constant {
  static constexpr const _Tp value = __v;
  typedef _Tp value_type;
  typedef integral_constant type;
  constexpr operator value_type() const noexcept { return value; }
  constexpr value_type operator()() const noexcept { return value; }
};

template <class _Tp, _Tp __v>
constexpr const _Tp integral_constant<_Tp, __v>::value;

typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;

template <bool, class _Tp = void>
struct enable_if {};
template <class _Tp>
struct enable_if<true, _Tp> {
 typedef _Tp type;
};
}  // namespace std

namespace p {
template <typename T>
struct P : ::std::false_type {};
}

#endif  // C1_H_
$ cat c2.h
#ifndef C2_H_
#define C2_H_

#include "c3.h"

enum E {};
namespace p {
template <>
struct P<E> : std::true_type {};
}  // namespace proto2

inline void f(::util::EnumErrorSpace<E>) {}

#endif  // C2_H_
$ cat c3.h
#ifndef C3_H_
#define C3_H_

#include "c1.h"

namespace util {

template <typename T>
class ErrorSpaceImpl;

class ErrorSpace {
 protected:
  template <bool* addr>
  struct OdrUse {
    constexpr OdrUse() : b(*addr) {}
 bool& b;
  };
  template <typename T>
  struct Registerer {
 static bool register_token;
    static constexpr OdrUse<&register_token> kRegisterTokenUse{};
  };

 private:
  template <typename T>
 static const ErrorSpace* GetBase() {
    return 0;
  }

  static bool Register(const ErrorSpace* (*space)()) { return true; }
};

template <typename T>
bool ErrorSpace::Registerer<T>::register_token =
 Register(&ErrorSpace::GetBase<T>);

template <typename T>
class ErrorSpaceImpl : public ErrorSpace {
 private:
  static constexpr Registerer<ErrorSpaceImpl> kRegisterer{};
};

template <typename T, typename = typename std::enable_if<p::P<T>::value>::type>
class EnumErrorSpace : public ErrorSpaceImpl<EnumErrorSpace<T>> {};

}  // namespace util
#endif  // C3_H_
$ cat test.cc
#include "a.h"
#include "b.h"

int main(int, char**) {}
$ clang -fmodules -fno-implicit-modules -fno-implicit-module-maps -fmodule-name=c -fmodule-map-file=c.cppmap -xc++ -c c.cppmap -Xclang=-emit-module -o c.pcm
$ clang -fmodules -fno-implicit-modules -fno-implicit-module-maps -fmodule-name=a -fmodule-map-file=a.cppmap -fmodule-map-file=c.cppmap -xc++ -c a.cppmap -Xclang=-emit-module -o a.pcm
$ clang -fmodules -fno-implicit-modules -fno-implicit-module-maps -fmodule-name=b -fmodule-map-file=b.cppmap -fmodule-map-file=c.cppmap -xc++ -c b.cppmap -Xclang=-emit-module -o b.pcm
$ clang -fmodules -fno-implicit-modules -fno-implicit-module-maps -fmodule-name=test -fmodule-map-file=test.cppmap -fmodule-map-file=a.cppmap -fmodule-map-file=b.cppmap -Xclang=-fmodule-file=a.pcm -Xclang=-fmodule-file=b.pcm -xc++ -c test.cc -o test.pcm
In module 'b':
./c3.h:44:7: error: 'util::EnumErrorSpace' has different definitions in different modules; definition in module 'b.b.h' is here
   44 | class EnumErrorSpace : public ErrorSpaceImpl<EnumErrorSpace<T>> {};
      |       ^
./c3.h:44:7: note: definition in module 'a.a.h' is here
   44 | class EnumErrorSpace : public ErrorSpaceImpl<EnumErrorSpace<T>> {};
      |       ^
1 error generated.
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMWUlv4zoS_jX0hbAhk3IUH3zwkszr03t4kwH6ZlBUyea0tiapTPrfD0hqoRY7C9DAC4JI4lL11VfFKpJhSolLAbBDmwPanBas1tdS7o7XmhU_xfd6u4jL5Nfu5SoU5mUOCqeyzPFV60ohukfkGZFnCa8C_qdWWfaar0p5QeT5tN6ElIQrFJxQsHd_v2EJF6E0SEiwvgIWStWA01JiLRn_IYoLFtp85yzLfg3mvlwBS6hkmdQcpHktpYYEC4vCG4gegubXfZIQc6YxW_GqylnlWvMyqTPAiBCGCMEoOrh2jOHNCMaI7NsWb-zqOhw9HYzxFVgCsh_e9qDo1L7WyorjXW_X16KNb6CNP4E2HqPFc-N9wPHXAfMbgPknAPP1BxFreNM1yzzkzdQZ6J548nXx5APi6dfF03nxE5Y1KH2DaNP1LteNH5mnrGmKb7vWhHHTQEVaJJDi_fmPc9eWQCoK8Nu60QXP6gQmDnJ_C5aDqhgH_LNHrSGvMqYBI3rUvyowg_ALIseeP_fTdSqdmAxA91CwOIOzSBE9upbKPf5C9PiC6JP7emVZDd2XEWM-rHSeMaXwd4smOiF66BjB2CU67IG-YyydGIsIhSIRaSfIp7Bd8xOeDzM8H-7zTN5XfZiott4Z6T6uZ5T7jSMnKp3Mu9Gxen6pEDmaBz6fXzvKlZY111gUGi6SZWdeFkqzQvtxrDTTgmPbBW-VdG9WlHUmRvTkhHZTjFuNEd2Ys3P0ZMBU8Whgr7WsQDJdSl8geURk2-ApSnjjUFnoWIKuZYGbYDv4KaOX2AvqhDuJX5A7CNjP-WCO2AkviB7b6W6qv5iGem9Ri-gxLsvMyNDSrkH7HLrmI7NTlik73b4M509tb2d1HNh4eS1FMo7CLoOMM8A8lbdmm9Rl7HNUG5x9MPuBOcT9bsIxiW525VXvps8R0r8wonvsPNilz57Lmfx3N58MMkWTUMhMQiFzCYXcT2fTTApFneOnMcZ32ZhwgOjxyfqG7vsa0sXjx2pAJUtdDtCJIjNmmejCqVnGVmytRebenoo6f5KylP82AhoMZq03-u7yTKY80xme6RzP9Ovl2aDvSf1QoLlF0hv6La-y0RIdD_EWiaEVuIak29qbXdN4Re8xSxLZqTR1wnr2z0T-R8FwH9anONfbJFjj-9i-762skR-wU_SAY68g-FExhDXDQwfq7_bgIz1gTWEzWrqT0VmXP6DwNMzUv8YGekTkYTzvCf9odb2YFjNwGMpDEzrKxSvTcIPwOct8VJ4bjV_-BfrAepJ9RzT1Kxih8aEMaGltQeRxTpPznXKf27Z4bv1S6UrNhyvljKkWiL9ozULuHTrYXQ7dYSpNY5VnCCIPY2ktY40osv0cwrnlZoO7quNM8FurbOzySaANjByvZi_SQM6UjA9ZYPYC7Zcpy_e39V_b0A9z7jwvzqTjJD07NZNyc68o2GR_I4PTSQZ3Rzo-l5T9-4NhTzzJ1qLQOGeiQORRFNpud65MmqOf-R2VF6M6Y8UFL1N3gFR4mRblUuRVJrjQy3uty5xVqpu5NHYjeuJ9S86qZSoy29ocVvHyjSNyQOSAlxz3rd8tDERPS8g7BXhZYr6qeP770LJZtKzD9WFT2PumsN9rSjyLNv68KfH7psS_1xSzFGYBe9cen3fcnF3tsG5-xfM7_bHr99lqlq1hxb52xHwr-juhKEYk6vLrCpFnu1-j-zBEdG96MJhkY3fjJLq5SyQRvjKFE5GmIKHQ2G7qhBZlobAovI6GdFPv-jFmiIdpZbNHhIXCV5DQ1eYwxChqj0m_IWe6exujonnbPN0hpihtabppBluxf5gZa-dMfIHCnOUhae-v2wvpRbKjyZZu2QJ264dtQDYkfIwW190jC1mcQgibKAgfkoiseUzWsOZRsN1AmizEjgSEBhHZBISGYbRKeBBzTsPg8YFtNlGMwgByJrLuBn5hr9Z3D2GwXS8yFkOm7A0_IU2Q79tQIQRtTgu5MzOXcX1RKAwyoXR_m7_QQmf2HwR_nv7-g6kr2pzM1kCCUsYvLNUgcfpIkjSIyeOG8UUts93wXwQXoa91vOJljsizkdw8lpUs_wtcI_JsIStEni3q_wcAAP__3IRGWQ">