rnk updated this revision to Diff 215442. rnk added a comment. - add DR test case
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D66040/new/ https://reviews.llvm.org/D66040 Files: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp clang/test/CXX/drs/dr23xx.cpp Index: clang/test/CXX/drs/dr23xx.cpp =================================================================== --- clang/test/CXX/drs/dr23xx.cpp +++ clang/test/CXX/drs/dr23xx.cpp @@ -40,6 +40,21 @@ #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 std { +template <typename T> struct tuple_size; +struct Bad1 { int a, b; }; +template<> struct std::tuple_size<Bad1> {}; +void no_value() { auto [x, y] = Bad1(); } +struct Bad2 { int a, b; }; +template<> struct std::tuple_size<Bad2> { static const int value = 42;}; +void wrong_value() { auto [x, y] = Bad2(); } // expected-error {{decomposes into 42 elements}} +} +#endif + namespace dr2387 { // dr2387: 9 #if __cplusplus >= 201402L template<int> int a = 0; Index: clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp =================================================================== --- clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -12,7 +12,7 @@ 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; }; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -1030,8 +1030,10 @@ 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 @@ } } 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())
Index: clang/test/CXX/drs/dr23xx.cpp =================================================================== --- clang/test/CXX/drs/dr23xx.cpp +++ clang/test/CXX/drs/dr23xx.cpp @@ -40,6 +40,21 @@ #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 std { +template <typename T> struct tuple_size; +struct Bad1 { int a, b; }; +template<> struct std::tuple_size<Bad1> {}; +void no_value() { auto [x, y] = Bad1(); } +struct Bad2 { int a, b; }; +template<> struct std::tuple_size<Bad2> { static const int value = 42;}; +void wrong_value() { auto [x, y] = Bad2(); } // expected-error {{decomposes into 42 elements}} +} +#endif + namespace dr2387 { // dr2387: 9 #if __cplusplus >= 201402L template<int> int a = 0; Index: clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp =================================================================== --- clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -12,7 +12,7 @@ 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; }; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -1030,8 +1030,10 @@ 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 @@ } } 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())
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits