mirror of https://github.com/microsoft/clang.git
[Sema] P0961R1: Relaxing the structured bindings customization point finding rules
Differential revision: https://reviews.llvm.org/D50418 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339375 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
467b2ee90d
commit
14274399e2
|
@ -1108,7 +1108,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
|
|||
|
||||
// [dcl.decomp]p3:
|
||||
// The unqualified-id get is looked up in the scope of E by class member
|
||||
// access lookup
|
||||
// access lookup ...
|
||||
LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
|
||||
bool UseMemberGet = false;
|
||||
if (S.isCompleteType(Src->getLocation(), DecompType)) {
|
||||
|
@ -1116,7 +1116,20 @@ static bool checkTupleLikeDecomposition(Sema &S,
|
|||
S.LookupQualifiedName(MemberGet, RD);
|
||||
if (MemberGet.isAmbiguous())
|
||||
return true;
|
||||
UseMemberGet = !MemberGet.empty();
|
||||
// ... and if that finds at least one declaration that is a function
|
||||
// template whose first template parameter is a non-type parameter ...
|
||||
for (NamedDecl *D : MemberGet) {
|
||||
if (FunctionTemplateDecl *FTD =
|
||||
dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) {
|
||||
TemplateParameterList *TPL = FTD->getTemplateParameters();
|
||||
if (TPL->size() != 0 &&
|
||||
isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) {
|
||||
// ... the initializer is e.get<i>().
|
||||
UseMemberGet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
S.FilterAcceptableTemplateNames(MemberGet);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ void no_get_2() {
|
|||
auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
|
||||
}
|
||||
|
||||
template<int> float &get(A);
|
||||
template<int> float &get(A); // expected-note 2 {{no known conversion}}
|
||||
|
||||
void no_tuple_element_1() {
|
||||
auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}}
|
||||
|
@ -57,7 +57,7 @@ void no_tuple_element_3() {
|
|||
template<> struct std::tuple_element<1, A> { typedef float &type; };
|
||||
template<> struct std::tuple_element<2, A> { typedef const float &type; };
|
||||
|
||||
template<int N> auto get(B) -> int (&)[N + 1];
|
||||
template<int N> auto get(B) -> int (&)[N + 1]; // expected-note 2 {{no known conversion}}
|
||||
template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; };
|
||||
|
||||
template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {};
|
||||
|
@ -138,19 +138,25 @@ int member_get() {
|
|||
return c;
|
||||
}
|
||||
|
||||
struct D { template<int> struct get {}; }; // expected-note {{declared here}}
|
||||
struct D {
|
||||
// FIXME: Emit a note here explaining why this was ignored.
|
||||
template<int> struct get {};
|
||||
};
|
||||
template<> struct std::tuple_size<D> { static const int value = 1; };
|
||||
template<> struct std::tuple_element<0, D> { typedef D::get<0> type; };
|
||||
void member_get_class_template() {
|
||||
auto [d] = D(); // expected-error {{cannot refer to member 'get' in 'D' with '.'}} expected-note {{in implicit init}}
|
||||
auto [d] = D(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
|
||||
}
|
||||
|
||||
struct E { int get(); };
|
||||
struct E {
|
||||
// FIXME: Emit a note here explaining why this was ignored.
|
||||
int get();
|
||||
};
|
||||
template<> struct std::tuple_size<E> { static const int value = 1; };
|
||||
template<> struct std::tuple_element<0, E> { typedef int type; };
|
||||
void member_get_non_template() {
|
||||
// FIXME: This diagnostic is not very good.
|
||||
auto [e] = E(); // expected-error {{no member named 'get'}} expected-note {{in implicit init}}
|
||||
auto [e] = E(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
|
||||
}
|
||||
|
||||
namespace ADL {
|
||||
|
@ -230,3 +236,62 @@ namespace constant {
|
|||
}
|
||||
static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}}
|
||||
}
|
||||
|
||||
// P0961R1
|
||||
struct InvalidMemberGet {
|
||||
int get();
|
||||
template <class T> int get();
|
||||
struct get {};
|
||||
};
|
||||
template <> struct std::tuple_size<InvalidMemberGet> { static constexpr size_t value = 1; };
|
||||
template <> struct std::tuple_element<0, InvalidMemberGet> { typedef float type; };
|
||||
template <size_t> float get(InvalidMemberGet) { return 0; }
|
||||
int f() {
|
||||
InvalidMemberGet img;
|
||||
auto [x] = img;
|
||||
typedef decltype(x) same_as_float;
|
||||
typedef float same_as_float;
|
||||
}
|
||||
|
||||
struct ValidMemberGet {
|
||||
int get();
|
||||
template <class T> int get() { return 0; }
|
||||
template <size_t N> float get() { return 0; }
|
||||
};
|
||||
template <> struct std::tuple_size<ValidMemberGet> { static constexpr size_t value = 1; };
|
||||
template <> struct std::tuple_element<0, ValidMemberGet> { typedef float type; };
|
||||
// Don't use this one; we should use the member get.
|
||||
template <size_t N> int get(ValidMemberGet) { static_assert(N && false, ""); }
|
||||
int f2() {
|
||||
ValidMemberGet img;
|
||||
auto [x] = img;
|
||||
typedef decltype(x) same_as_float;
|
||||
typedef float same_as_float;
|
||||
}
|
||||
|
||||
struct Base1 {
|
||||
int get(); // expected-note{{member found by ambiguous name lookup}}
|
||||
};
|
||||
struct Base2 {
|
||||
template<int> int get(); // expected-note{{member found by ambiguous name lookup}}
|
||||
};
|
||||
struct Derived : Base1, Base2 {};
|
||||
|
||||
template <> struct std::tuple_size<Derived> { static constexpr size_t value = 1; };
|
||||
template <> struct std::tuple_element<0, Derived> { typedef int type; };
|
||||
|
||||
auto [x] = Derived(); // expected-error{{member 'get' found in multiple base classes of different types}}
|
||||
|
||||
struct Base {
|
||||
template<int> int get();
|
||||
};
|
||||
struct UsingGet : Base {
|
||||
using Base::get;
|
||||
};
|
||||
|
||||
template <> struct std::tuple_size<UsingGet> {
|
||||
static constexpr size_t value = 1;
|
||||
};
|
||||
template <> struct std::tuple_element<0, UsingGet> { typedef int type; };
|
||||
|
||||
auto [y] = UsingGet();
|
||||
|
|
|
@ -755,7 +755,7 @@ version 3.7.
|
|||
<tr>
|
||||
<!-- from Jacksonville 2018 -->
|
||||
<td><a href="http://wg21.link/p0961r1">P0961R1</a> (<a href="#dr">DR</a>)</td>
|
||||
<td class="none" align="center">No</td>
|
||||
<td class="none" align="center">SVN</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- from Jacksonville 2018 -->
|
||||
|
|
Loading…
Reference in New Issue