r369043 - [Sema] Implement DR2386 for C++17 structured binding

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 20 02:59:29 PDT 2019


Merged to release_90 in r369361.

On Thu, Aug 15, 2019 at 9:44 PM Reid Kleckner via cfe-commits
<cfe-commits at 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 at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list