Merged to release_90 in r369361.
On Thu, Aug 15, 2019 at 9:44 PM Reid Kleckner via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > Author: rnk > Date: Thu Aug 15 12:45:28 2019 > New Revision: 369043 > > URL: http://llvm.org/viewvc/llvm-project?rev=369043&view=rev > Log: > [Sema] Implement DR2386 for C++17 structured binding > > Allow implementations to provide complete definitions of > std::tuple_size<T>, but to omit the 'value' member to signal that T is > not tuple-like. The Microsoft standard library implements > std::tuple_size<const T> this way. > > If the value member exists, clang still validates that it is an ICE, but > if it does not, then the type is considered to not be tuple-like. > > Fixes PR33236 > > Reviewers: rsmith > > Differential Revision: https://reviews.llvm.org/D66040 > > Modified: > cfe/trunk/lib/Sema/SemaDeclCXX.cpp > cfe/trunk/test/CXX/dcl.decl/dcl.decomp/p3.cpp > cfe/trunk/test/CXX/drs/dr23xx.cpp > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=369043&r1=369042&r2=369043&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug 15 12:45:28 2019 > @@ -1030,8 +1030,10 @@ static IsTupleLike isTupleLike(Sema &S, > TemplateArgumentListInfo Args(Loc, Loc); > Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); > > - // If there's no tuple_size specialization, it's not tuple-like. > - if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0)) > + // If there's no tuple_size specialization or the lookup of 'value' is > empty, > + // it's not tuple-like. > + if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/ 0) > || > + R.empty()) > return IsTupleLike::NotTupleLike; > > // If we get this far, we've committed to the tuple interpretation, but > @@ -1048,11 +1050,6 @@ static IsTupleLike isTupleLike(Sema &S, > } > } Diagnoser(R, Args); > > - if (R.empty()) { > - Diagnoser.diagnoseNotICE(S, Loc, SourceRange()); > - return IsTupleLike::Error; > - } > - > ExprResult E = > S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false); > if (E.isInvalid()) > > Modified: cfe/trunk/test/CXX/dcl.decl/dcl.decomp/p3.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.decomp/p3.cpp?rev=369043&r1=369042&r2=369043&view=diff > ============================================================================== > --- cfe/trunk/test/CXX/dcl.decl/dcl.decomp/p3.cpp (original) > +++ cfe/trunk/test/CXX/dcl.decl/dcl.decomp/p3.cpp Thu Aug 15 12:45:28 2019 > @@ -12,7 +12,7 @@ void no_tuple_size_2() { auto [x, y] = A > > struct Bad1 { int a, b; }; > template<> struct std::tuple_size<Bad1> {}; > -void no_tuple_size_3() { auto [x, y] = Bad1(); } // expected-error {{cannot > decompose this type; 'std::tuple_size<Bad1>::value' is not a valid integral > constant expression}} > +void no_tuple_size_3() { auto [x, y] = Bad1(); } // ok, omitting value is > valid after DR2386 > > struct Bad2 {}; > template<> struct std::tuple_size<Bad2> { const int value = 5; }; > > Modified: cfe/trunk/test/CXX/drs/dr23xx.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr23xx.cpp?rev=369043&r1=369042&r2=369043&view=diff > ============================================================================== > --- cfe/trunk/test/CXX/drs/dr23xx.cpp (original) > +++ cfe/trunk/test/CXX/drs/dr23xx.cpp Thu Aug 15 12:45:28 2019 > @@ -40,6 +40,27 @@ namespace dr2353 { // dr2353: 9 > #pragma clang __debug dump not_use_2 > } > > +#if __cplusplus >= 201707L > +// Otherwise, if the qualified-id std::tuple_size<E> names a complete class > +// type **with a member value**, the expression std::tuple_size<E>::value > shall > +// be a well-formed integral constant expression > +namespace dr2386 { // dr2386: 9 > +struct Bad1 { int a, b; }; > +struct Bad2 { int a, b; }; > +} // namespace dr2386 > +namespace std { > +template <typename T> struct tuple_size; > +template <> struct std::tuple_size<dr2386::Bad1> {}; > +template <> struct std::tuple_size<dr2386::Bad2> { > + static const int value = 42; > +}; > +} // namespace std > +namespace dr2386 { > +void no_value() { auto [x, y] = Bad1(); } > +void wrong_value() { auto [x, y] = Bad2(); } // expected-error {{decomposes > into 42 elements}} > +} // namespace dr2386 > +#endif > + > namespace dr2387 { // dr2387: 9 > #if __cplusplus >= 201402L > template<int> int a = 0; > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits