Since we don't unique specializations for concepts, we can just instantiate them with the sugared template arguments, at negligible cost. If we don't track their specializations, we can't resugar them later anyway, and that would be more expensive than just instantiating them sugared in the first place since it would require an additional pass. Signed-off-by: Matheus Izvekov <mizvekov@gmail.com> Differential Revision: https://reviews.llvm.org/D136566
64 lines
1.9 KiB
C++
64 lines
1.9 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
|
|
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
|
|
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
|
|
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
|
|
// expected-no-diagnostics
|
|
|
|
struct Incomplete;
|
|
template <class T> struct Holder { T t; };
|
|
|
|
namespace DotFollowingFunctionName {
|
|
struct Good {
|
|
struct Nested {
|
|
int b;
|
|
} a;
|
|
};
|
|
|
|
struct Bad {
|
|
Holder<Incomplete> a();
|
|
};
|
|
|
|
template <class T>
|
|
constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
|
|
constexpr bool f(...) { return false; }
|
|
|
|
static_assert(DotFollowingFunctionName::f(Good{}), "");
|
|
static_assert(!DotFollowingFunctionName::f(Bad{}), "");
|
|
|
|
#if __cplusplus >= 202002L
|
|
template <class T>
|
|
concept C = requires(T t) { t.a.b; };
|
|
// cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
|
|
|
|
static_assert(C<Good>);
|
|
static_assert(!C<Bad>);
|
|
static_assert(C<Bad>); // cxx20-error {{static assertion failed}}
|
|
// cxx20-note@-1 {{because 'Bad' does not satisfy 'C'}}
|
|
#endif
|
|
} // namespace DotFollowingFunctionName
|
|
|
|
namespace DotFollowingPointer {
|
|
struct Good {
|
|
int begin();
|
|
};
|
|
using Bad = Holder<Incomplete> *;
|
|
|
|
template <class T>
|
|
constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
|
|
constexpr bool f(...) { return false; }
|
|
|
|
static_assert(DotFollowingPointer::f(Good{}), "");
|
|
static_assert(!DotFollowingPointer::f(Bad{}), "");
|
|
|
|
#if __cplusplus >= 202002L
|
|
template <class T>
|
|
concept C = requires(T t) { t.begin(); };
|
|
// cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Bad' (aka 'Holder<Incomplete> *') is a pointer}}
|
|
|
|
static_assert(C<Good>);
|
|
static_assert(!C<Bad>);
|
|
static_assert(C<Bad>); // cxx20-error {{static assertion failed}}
|
|
// cxx20-note@-1 {{because 'Bad' (aka 'Holder<Incomplete> *') does not satisfy 'C'}}
|
|
#endif
|
|
} // namespace DotFollowingPointer
|