[InstCombine] Preserve NSW flags for `lshr (mul nuw X, C1), C2 -> mul nuw nsw X,...
[llvm-project.git] / clang / test / SemaTemplate / instantiation-dependence.cpp
blob1a97dbf769ec63b8e24ca2ed83be2664563ca572
1 // RUN: %clang_cc1 -std=c++23 -verify %s
3 // Ensure we substitute into instantiation-dependent but non-dependent
4 // constructs. The poster-child for this is...
5 template<class ...> using void_t = void;
7 namespace PR24076 {
8 template<class T> T declval();
9 struct s {};
11 template<class T,
12 class = void_t<decltype(declval<T>() + 1)>>
13 void foo(T) {} // expected-note {{invalid operands to binary expression}}
15 void f() {
16 foo(s{}); // expected-error {{no matching function}}
19 template<class T,
20 class = void_t<decltype(declval<T>() + 1)>> // expected-error {{invalid operands to binary expression}}
21 struct bar {};
23 bar<s> bar; // expected-note {{in instantiation of}}
26 namespace PR33655 {
27 struct One { using x = int; };
28 struct Two { using y = int; };
30 template<typename T, void_t<typename T::x> * = nullptr> int &func() {}
31 template<typename T, void_t<typename T::y> * = nullptr> float &func() {}
33 int &test1 = func<One>();
34 float &test2 = func<Two>();
36 template<class ...Args> struct indirect_void_t_imp { using type = void; };
37 template<class ...Args> using indirect_void_t = typename indirect_void_t_imp<Args...>::type;
39 template<class T> void foo() {
40 int check1[__is_void(indirect_void_t<T>) == 0 ? 1 : -1]; // "ok", dependent
41 int check2[__is_void(void_t<T>) == 0 ? 1 : -1]; // expected-error {{array with a negative size}}
45 namespace PR46791 { // also PR45782
46 template<typename T, typename = void>
47 struct trait {
48 static constexpr int specialization = 0;
51 // FIXME: Per a strict interpretation of the C++ rules, the two void_t<...>
52 // types below are equivalent -- we only (effectively) do token-by-token
53 // comparison for *expressions* appearing within types. But all other
54 // implementations accept this, using rules that are unclear.
55 template<typename T>
56 struct trait<T, void_t<typename T::value_type>> { // expected-note {{previous}} FIXME-note {{matches}}
57 static constexpr int specialization = 1;
60 template<typename T>
61 struct trait<T, void_t<typename T::element_type>> { // expected-error {{redefinition}} FIXME-note {{matches}}
62 static constexpr int specialization = 2;
65 struct A {};
66 struct B { typedef int value_type; };
67 struct C { typedef int element_type; };
68 struct D : B, C {};
70 static_assert(trait<A>::specialization == 0);
71 static_assert(trait<B>::specialization == 1); // FIXME expected-error {{failed}} \
72 // expected-note {{evaluates to '0 == 1'}}
73 static_assert(trait<C>::specialization == 2); // FIXME expected-error {{failed}} \
74 // expected-note {{evaluates to '0 == 2'}}
75 static_assert(trait<D>::specialization == 0); // FIXME-error {{ambiguous partial specialization}}
78 namespace TypeQualifier {
79 // Ensure that we substitute into an instantiation-dependent but
80 // non-dependent qualifier.
81 template<int> struct A { using type = int; };
82 template<typename T> A<sizeof(sizeof(T::error))>::type f() {} // expected-note {{'int' cannot be used prior to '::'}}
83 int k = f<int>(); // expected-error {{no matching}}
86 namespace MemberOfInstantiationDependentBase {
87 template<typename T> struct A { template<int> void f(int); };
88 template<typename T> struct B { using X = A<T>; };
89 template<typename T> struct C1 : B<int> {
90 using X = typename C1::X;
91 void f(X *p) {
92 p->f<0>(0);
93 p->template f<0>(0);
96 template<typename T> struct C2 : B<int> {
97 using X = typename C2<T>::X;
98 void f(X *p) {
99 p->f<0>(0);
100 p->template f<0>(0);
103 void q(C1<int> *c) { c->f(0); }
104 void q(C2<int> *c) { c->f(0); }