https://gcc.gnu.org/g:1498f0547eb1692c39c63ad3e8e22859dc526e3e
commit r17-5424-g1498f0547eb1692c39c63ad3e8e22859dc526e3e Author: Jakub Jelinek <[email protected]> Date: Wed Oct 21 09:04:21 2026 +0200 c++: Call check_trait_type for CPTK_STRUCTURED_BINDING_SIZE [PR127766] The following testcase is rejected because we don't even try to complete the type, so if it wasn't instantiated with those arguments before, we reject it. Fixed up calling check_trait_type, with kind 4, for non-class I think cp_decomp_size already does the right thing, for arrays we actually just care about number of elements. On the pt.cc side, fixed by removing the special casing of this exact trait and instead passing complain to all finish_trait_expr calls in TRAIT_EXPR case. 2026-10-21 Jakub Jelinek <[email protected]> PR c++/127766 * semantics.cc (finish_trait_expr) <case CPTK_STRUCTURED_BINDING_SIZE>: Call check_trait_type with kind 4. * pt.cc (tsubst_expr) <case TRAIT_EXPR>: Remove special casing of CPTK_STRUCTURED_BINDING_SIZE. Instead pass complain to finish_trait_expr. * g++.dg/ext/builtin-structured-binding-size2.C: Expect different diagnostics. * g++.dg/ext/builtin-structured-binding-size7.C: New test. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/pt.cc | 10 ++-------- gcc/cp/semantics.cc | 2 ++ gcc/testsuite/g++.dg/ext/builtin-structured-binding-size2.C | 2 +- gcc/testsuite/g++.dg/ext/builtin-structured-binding-size7.C | 10 ++++++++++ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index f46916a256d1..9db8f09735fd 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -23524,15 +23524,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) type1 = tsubst_expr (type1, args, complain, in_decl); tree type2 = tsubst (TRAIT_EXPR_TYPE2 (t), args, complain, in_decl); - if (TRAIT_EXPR_KIND (t) == CPTK_STRUCTURED_BINDING_SIZE - && type1 != error_mark_node - && !processing_template_decl) - /* __builtin_structured_binding_size handled separately - to make it SFINAE friendly. */ - RETURN (finish_structured_binding_size (TRAIT_EXPR_LOCATION (t), - type1, complain)); RETURN (finish_trait_expr (TRAIT_EXPR_LOCATION (t), - TRAIT_EXPR_KIND (t), type1, type2)); + TRAIT_EXPR_KIND (t), type1, type2, + complain)); } case STMT_EXPR: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 581cb3565f19..42b974a764ba 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -14753,6 +14753,8 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2, return maybe_wrap_with_location (type_order_value (type1, type2), loc); case CPTK_STRUCTURED_BINDING_SIZE: + if (!check_trait_type (type1, /* kind = */ 4, complain)) + return error_mark_node; return finish_structured_binding_size (loc, type1, complain); case CPTK_IS_LAYOUT_COMPATIBLE: diff --git a/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size2.C b/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size2.C index 9abd80fec9d5..ebdc08ec19ff 100644 --- a/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size2.C +++ b/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size2.C @@ -21,7 +21,7 @@ template <> struct std::tuple_size <C> { static constexpr double value = 42; }; template <> struct std::tuple_size <D> { static constexpr int value = -1; }; -int a = __builtin_structured_binding_size (A); // { dg-error "structured binding refers to incomplete class type 'A'" } +int a = __builtin_structured_binding_size (A); // { dg-error "invalid use of incomplete type 'struct A'" } int b = __builtin_structured_binding_size (A &); // { dg-error "'__builtin_structured_binding_size' argument 'A\\\&' is a reference" } int c = __builtin_structured_binding_size (B[]); // { dg-error "cannot decompose array of unknown bound 'B \\\[\\\]'" } int d = __builtin_structured_binding_size (C); // { dg-error "'std::tuple_size<C>::value' is not an integral constant expression" } diff --git a/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size7.C b/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size7.C new file mode 100644 index 000000000000..d12934b5ac75 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin-structured-binding-size7.C @@ -0,0 +1,10 @@ +// PR c++/127766 +// { dg-do compile { target c++11 } } + +template <typename T> struct A { T a, b; }; +static_assert (__builtin_structured_binding_size (A <int>) == 2, ""); + +template <typename T> struct B { T a, b, c; }; +template <typename T> +constexpr int foo () { return __builtin_structured_binding_size (B<T>); } +static_assert (foo <int> () == 3, "");
