Skip to content

[clang] Concepts breakage only with multiple instantiations #164750

@rupprecht

Description

@rupprecht

After #161671, there is a curious compilation issue where instantiating either one of two templates is fine, but instantiating both will fail.

Repro command: clang -stdlib=libc++ -std=gnu++20 -Wall -Werror -DA -DB / live repro: https://godbolt.org/z/bf5sKMGPK

Note that just -DA or -DB passes, but both -DA -DB fails.

Repro source:

#include <utility>

template <typename>
struct a;
template <typename>
struct b;

template <template <typename> typename c, typename d, typename>
concept e = !std::convertible_to<c<d>*, b<d>*>;

template <typename...>
struct f;
template <typename g, typename... h>
struct f<g, h...> {
    g i;
};

template <typename, typename>
struct u;
template <typename j, template <typename> typename k, typename l>
    requires e<k, j, l>
struct u<const k<j>*, l> {
    u(const a<j>*);
};
template <typename j, template <typename> typename k, typename l>
struct u<const k<j>*, l> {
    u(const b<j>*);
};

template <typename>
struct m;
template <typename n, typename... o>
struct m<n (*)(o...)> {
    template <template <typename> typename j>
    using p = j<o...>;
};

template <typename q, typename r>
struct s {
    template <typename... p>
    struct D {
        using v = f<u<r, p>...>;
    };
    template <typename... t>
    s(t... p1) : x(p1...) {}
    m<q>::template p<D>::v x;
};
template <typename w, typename... t>
void fn1(w, t... p2) {
    s<w, t...>(p2...);
}
int* fn2(int) { return nullptr; }
void fn3() {
#ifdef A
    fn1(fn2, static_cast<const a<int>*>(nullptr));
#endif
#ifdef B
    fn1(fn2, static_cast<const b<int>*>(nullptr));
#endif
}

Failure:

<source>:45:20: error: no viable conversion from 'const b<int> *' to 'u<const b<int> *, int>'
   45 |     s(t... p1) : x(p1...) {}
      |                    ^~
<source>:50:5: note: in instantiation of function template specialization 's<int *(*)(int), const b<int> *>::s<const b<int> *>' requested here
   50 |     s<w, t...>(p2...);
      |     ^
<source>:58:5: note: in instantiation of function template specialization 'fn1<int *(*)(int), const b<int> *>' requested here
   58 |     fn1(fn2, static_cast<const b<int>*>(nullptr));
      |     ^

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"conceptsC++20 concepts

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions