diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -172,8 +172,14 @@ AddDecl(TA.getAsDecl()); break; case TemplateArgument::NullPtr: - case TemplateArgument::Integral: + ID.AddPointer(nullptr); break; + case TemplateArgument::Integral: { + // There are integrals (e.g.: _BitInt(128)) that cannot be represented as + // any builtin integral type, so we use the hash of APSInt instead. + TA.getAsIntegral().Profile(ID); + break; + } case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: AddTemplateName(TA.getAsTemplateOrTemplatePattern()); diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/test/Modules/odr_hash.cpp @@ -1939,6 +1939,164 @@ // expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 2 template arguments}} #endif +#if defined(FIRST) +struct S12 { + template void f(){}; + template <> void f<1>(){}; +}; +#elif defined(SECOND) +struct S12 { + template void f(){}; + template <> void f<2>(){}; +}; +#else +S12 s12; +// expected-error@second.h:* {{'TemplateArgument::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 2 for 1st template argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1 for 1st template argument}} +#endif + +#if defined(FIRST) +struct S13 { + template void f(){}; + template <> void f<10>(){}; +}; +#elif defined(SECOND) +struct S13 { + template void f(){}; + template <> void f<10>(){}; +}; +#else +S13 s13; +#endif + +#if defined(FIRST) +struct S14 { + template void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S14 { + template void f(){}; + template <> void f(){}; +}; +#else +S14 s14; +// expected-error@second.h:* {{'TemplateArgument::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 0 for 1st template argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1 for 1st template argument}} +#endif + +#if defined(FIRST) +struct S15 { + template void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S15 { + template void f(){}; + template <> void f(){}; +}; +#else +S15 s15; +#endif + +#if defined(FIRST) +struct S16 { + template void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S16 { + template void f(){}; + template <> void f(){}; +}; +#else +S16 s16; +#endif + +#if defined(FIRST) +struct S17 { + static int x; + template void f(){}; + template <> void f<&x>(){}; +}; +#elif defined(SECOND) +struct S17 { + static int x; + template void f(){}; + template <> void f(){}; +}; +#else +S17 s17; +// expected-error@second.h:* {{'TemplateArgument::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with nullptr for 1st template argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 'x' for 1st template argument}} +#endif + +#if defined(FIRST) +struct S18 { + static int x; + template void f(){}; + template <> void f<&x>(){}; +}; +#elif defined(SECOND) +struct S18 { + static int x; + template void f(){}; + template <> void f<&x>(){}; +}; +#else +S18 s18; +#endif + +#if defined(FIRST) +struct S19 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S19 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f(){}; +}; +#else +S19 s19; +#endif + +#if defined(FIRST) +struct S20 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S20 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f(){}; +}; +#else +S20 s20; +// expected-error@second.h:* {{'TemplateArgument::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 18446744073709551615 for 1st template argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 36893488147419103230 for 1st template argument}} +#endif + +#if defined(FIRST) +struct S21 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f(){}; +}; +#elif defined(SECOND) +struct S21 { + static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1); + template <_BitInt(128)> void f(){}; + template <> void f<(unsigned long long)-1>(){}; +}; +#else +S21 s21; +#endif + #define DECLS \ OneClass a; \ OneInt<1> b; \