{"id":2232021,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2232021/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/oro6iyfbxp.fsf_-_@lxoliva.fsfla.org/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.1/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<oro6iyfbxp.fsf_-_@lxoliva.fsfla.org>","date":"2026-05-02T08:33:22","name":"[v3] libstdc++: check value in std::{con,dis}junction","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"ca396ca552484f91b317b572f10f8fd1314eb54e","submitter":{"id":74937,"url":"http://patchwork.ozlabs.org/api/1.1/people/74937/?format=json","name":"Alexandre Oliva","email":"oliva@adacore.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/oro6iyfbxp.fsf_-_@lxoliva.fsfla.org/mbox/","series":[{"id":502518,"url":"http://patchwork.ozlabs.org/api/1.1/series/502518/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=502518","date":"2026-05-02T08:33:22","name":"[v3] libstdc++: check value in std::{con,dis}junction","version":3,"mbox":"http://patchwork.ozlabs.org/series/502518/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2232021/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2232021/checks/","tags":{},"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256\n header.s=google header.b=JrciEa2d;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (2048-bit key,\n secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256\n header.s=google header.b=JrciEa2d","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=adacore.com","sourceware.org; spf=pass smtp.mailfrom=adacore.com","server2.sourceware.org;\n arc=none smtp.remote-ip=2607:f8b0:4864:20::122e"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g71RF5Nvrz1yGq\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 02 May 2026 18:34:16 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 568F74BBC0DC\n\tfor <incoming@patchwork.ozlabs.org>; Sat,  2 May 2026 08:34:14 +0000 (GMT)","from mail-dl1-x122e.google.com (mail-dl1-x122e.google.com\n [IPv6:2607:f8b0:4864:20::122e])\n by sourceware.org (Postfix) with ESMTPS id 050264BBC0DC\n for <gcc-patches@gcc.gnu.org>; Sat,  2 May 2026 08:33:38 +0000 (GMT)","by mail-dl1-x122e.google.com with SMTP id\n a92af1059eb24-12dfee30612so839287c88.0\n for <gcc-patches@gcc.gnu.org>; Sat, 02 May 2026 01:33:38 -0700 (PDT)","from free.home ([2804:14c:4d1:41a6::2000])\n by smtp.gmail.com with ESMTPSA id\n a92af1059eb24-12df8279e57sm6127513c88.3.2026.05.02.01.33.36\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sat, 02 May 2026 01:33:37 -0700 (PDT)","from livre (livre.home [172.31.160.2])\n by free.home (8.15.2/8.15.2) with ESMTPS id 6428XM86302652\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT);\n Sat, 2 May 2026 05:33:23 -0300"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 568F74BBC0DC","OpenDKIM Filter v2.11.0 sourceware.org 050264BBC0DC"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 050264BBC0DC","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 050264BBC0DC","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777710819; cv=none;\n b=U/qUNscV36lbBYk/Sqx5CpMdJM75kLzn4+XD9jx4Ox8JJWVqlQ24S2E4wjroTuKO87zE4VpIARkUwjsEklDEGiZN5w1AwqKLTYtzljEVqPDCuoRUb2uDBPEvkDOcZScpsUnz/U/zQrv0sK4Mqpsb2FWzE0/ulpvN/ESPKEN1nxg=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777710819; c=relaxed/simple;\n bh=u4qWfgexD+SqVdq71T0+TaWakMMzyYHiPJtWnAKTmKU=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=MWgc6nCMX4cTNN3LwE2AVYYVD1POpHqJEPuHuXG8pqKod8LrXoTF7IdPVnaWDLeAVM8yxnHQRXtlNutki2ShSJrwghHdFn858syEncIWTycAr40ogRZa+ApEC9p7Yo5YvkWoSNxEEVaf/AprVVz/TgNwdMGx+jTNqvv440tgeDQ=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=adacore.com; s=google; t=1777710818; x=1778315618; darn=gcc.gnu.org;\n h=mime-version:user-agent:message-id:in-reply-to:date:references\n :organization:subject:cc:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=uIE64IzxzDi4jXfvVYoH1spRiBS9GOtUF0/q0sNOSp4=;\n b=JrciEa2dRd4ULBfM5lkZyNik0YKKGV3rib1gUFNLSd7JwYlM7EriTJ2+Y6Zz60WhNb\n iNEYa8exLLKpBvsBkxf4rN7k2q28zov0ptUx1cdN9gpV3hBFRXfPgFAwfEjrrT6x0SDV\n YG25xCPbNS9mEGhfzbj/K80rMEAfbIirB6pkU0inJUcaUpA0yMkJ9MLpZ9ERJnEqCdXl\n ult7RMji6OCbqsYGegtm0/rWWzYyTrNiWyd4MZ98+4K5u+EjIHFoHJakdEtCPZZXgNOF\n 8HmcwLz3abliaTkdWGcTFrCvfE3B/HJdh2TksQAxoJGyKR90QP9wOV61w1pbEAYLTryg\n NxaQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777710818; x=1778315618;\n h=mime-version:user-agent:message-id:in-reply-to:date:references\n :organization:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=uIE64IzxzDi4jXfvVYoH1spRiBS9GOtUF0/q0sNOSp4=;\n b=Dc6OkRZ77J80z1xaGcZXFueTgNwXSr2ykmrIjE/cBYubnayUaK/g9dB/POpnFeFZuv\n tzht4qOjEJPPSlBqjnrBz/UqYmNaImTGL4/Sbe5L+jsQBlq/7IwZg9W7hoiQlFK0b66C\n 4xlO3BzWmHQOlxawQOvnGqBjU7yVDZYzrLIqOXAIaU9FWRssaJeqv0kKEnpThWfltVU5\n 3NWLHC/6JgsarY9GFPYcvFB6cBLr38fkS51ug4IWHnGyVbsXVbyou9+lPCVjd/fgSN47\n UAOmrVXmtaL6RPyDD17gIMwVCHbnJj+RkNs682PXL7ceBWvoVB7As8y5EHOGbM3HjXRC\n XYtQ==","X-Forwarded-Encrypted":"i=1;\n AFNElJ+vDIlyEJYFalXoySXJpL2meoIV6RCSeLYYaBhpmXO7ePm+Wq2WV1BElZwWabfEQXuWookqpLDGbOfbIQ==@gcc.gnu.org","X-Gm-Message-State":"AOJu0Yyv+U4Iw+W+YFEpCCCLRra6pDzCNqRMbzj68yEYk8aJM5AK/k7z\n o966UFfB434yUkkmC5kIHyDHeqyWdUDq4iZT/kR1x+o6HutQ/UhSZHOwmVCjfd0bLw==","X-Gm-Gg":"AeBDieu1ku07eepdrvrhbgPqSoUxQRz/eoFuyu+2Cq6w+4ux3JWLKlJBt+zc9Y0kA+K\n O8AV5Cj6xvhg7OZsTP+IAmp5kcDPEwvKV6AiZQJ72S4XVlKYNchszAs3gYwC6XbXBJufClBITpZ\n y72ZiLEQKGW0JSV0Oq80agfZT8flliguh1Rw4pbL76qqiXRtpDEgeQ1JMWW+w32ngxfnEmm9e0x\n Ys8EAOC4m94wW81RuQUt3+WnMnoip1irrhLV3qU06j1kZmxpMJmHRdyWPhTwYqN/6eLjFHqQVuA\n MEBQh3MEXuuBu63HOjHxxXdTd0pwWM9KNO/z60+lPoGU5QAZ608gUp0GKiDBjQIWXeuh2XpOIei\n NH7+zMPipTF/ms9zwSpV1TlrrkpD06Gqs+XASo82CKuKw5pi+Qv/OpwKM5y/yLi0wKUD7n84a7A\n OzbfzRdh/EKA==","X-Received":"by 2002:a05:7022:43a6:b0:12d:b26f:cafd with SMTP id\n a92af1059eb24-12dfd7ae640mr1183159c88.5.1777710817486;\n Sat, 02 May 2026 01:33:37 -0700 (PDT)","From":"Alexandre Oliva <oliva@adacore.com>","To":"Jonathan Wakely <jwakely@redhat.com>","Cc":"Patrick Palka <ppalka@redhat.com>,\n Jonathan Wakely <jwakely.gcc@gmail.com>,\n \"libstdc++\" <libstdc++@gcc.gnu.org>, gcc-patches <gcc-patches@gcc.gnu.org>","Subject":"[PATCH v3] libstdc++: check value in std::{con,dis}junction","Organization":"Free thinker, does not speak for AdaCore","References":"<orfr4dmtm8.fsf@lxoliva.fsfla.org>\n <CAH6eHdQJBc8WTuqEC=Wrx-y0vo9ceSSNAsNss_-ng6tcPwMd+w@mail.gmail.com>\n <cdc6367b-dd33-49cf-f2fd-007b41002564@idea>\n <CACb0b4ki8FpUNGUaukYzfKy30JPOWpN7frELydOSUVCsQc3c0Q@mail.gmail.com>","Date":"Sat, 02 May 2026 05:33:22 -0300","In-Reply-To":"\n <CACb0b4ki8FpUNGUaukYzfKy30JPOWpN7frELydOSUVCsQc3c0Q@mail.gmail.com>\n (Jonathan Wakely's message of \"Thu, 30 Apr 2026 10:23:32 +0100\")","Message-ID":"<oro6iyfbxp.fsf_-_@lxoliva.fsfla.org>","User-Agent":"Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)","MIME-Version":"1.0","Content-Type":"text/plain","X-Scanned-By":"MIMEDefang 2.84","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":"On Apr 30, 2026, Jonathan Wakely <jwakely@redhat.com> wrote:\n\n> There's no requirement to make the new testcase  ill-formed, so I'm\n> not sure we need to change anything.\n\nI agree we don't need to change; it just seems good practice to check\nthat the requirements are met instead of silently swallowing what is\nlikely an error, that I'm told other compilers report.  That said, it's\nprobably just a pedantic overcompliance matter, since any use of\n::value, which is to be expected, would report the error anyway.\n\nSo this is probably my last attempt at this.  Instead of using\ntype::value, I introduce __type as a typedef to the base type to\nsimplify the static_assert.\n\nI'd appreciate an explicit decline in case we don't want this, so that I\ndon't keep on pinging and waiting for a resolution.  (ditto for\nhttps://gcc.gnu.org/pipermail/gcc-patches/2026-April/713470.html BTW :-)\nTIA,\n\nRegstrapping on x86_64-linux-gnu.  Ok to install?\n\n\nWhen std::{con,dis}junction is passed a type that doesn't have a\n\"value\" static data member, or whose value doesn't convert to bool, is\nambiguous or inaccessible, we stop iterating over the types and use\nthat type for the {con,dis}junction, without any diagnostic.\n\nWe'd get a diagnostic when attempting to use its value data member as\na bool, but if the member isn't used, compilation is successful,\ndespite the failure to meet the requirements for \"value\" in\n[meta.logical]/4.  A diagnostic is not required, but it may be useful.\n\nCheck that the selected type parameter has a value member, and that\nits value member is convertible to bool at the user-visible class; an\nassert in the _impl class would fuse errors whose malformed type\nstarts a shared tail, so introduce __type in the user-visible class to\nshorten the assert.\n\n\nfor  libstdc++-v3/ChangeLog\n\n\t* include/std/type_traits (disjunction, conjunction): Check\n\tthat value converts to bool.  Move implementation down.\n---\n libstdc++-v3/include/std/type_traits               |  142 ++++++++++----------\n .../logical_traits/requirements/junction_neg.cc    |   31 ++++\n 2 files changed, 105 insertions(+), 68 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc","diff":"diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits\nindex 1c03c22e8eed4..d8de3f013a73c 100644\n--- a/libstdc++-v3/include/std/type_traits\n+++ b/libstdc++-v3/include/std/type_traits\n@@ -213,74 +213,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     { };\n   /// @endcond\n \n-#ifdef __cpp_lib_logical_traits // C++ >= 17\n-\n-  /// @cond undocumented\n-  template<typename... _Bn>\n-    inline constexpr bool __or_v = __or_<_Bn...>::value;\n-  template<typename... _Bn>\n-    inline constexpr bool __and_v = __and_<_Bn...>::value;\n-\n-  namespace __detail\n-  {\n-    template<typename /* = void */, typename _B1, typename... _Bn>\n-      struct __disjunction_impl\n-      { using type = _B1; };\n-\n-    template<typename _B1, typename _B2, typename... _Bn>\n-      struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...>\n-      { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; };\n-\n-    template<typename /* = void */, typename _B1, typename... _Bn>\n-      struct __conjunction_impl\n-      { using type = _B1; };\n-\n-    template<typename _B1, typename _B2, typename... _Bn>\n-      struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...>\n-      { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; };\n-  } // namespace __detail\n-  /// @endcond\n-\n-  template<typename... _Bn>\n-    struct conjunction\n-    : __detail::__conjunction_impl<void, _Bn...>::type\n-    { };\n-\n-  template<>\n-    struct conjunction<>\n-    : true_type\n-    { };\n-\n-  template<typename... _Bn>\n-    struct disjunction\n-    : __detail::__disjunction_impl<void, _Bn...>::type\n-    { };\n-\n-  template<>\n-    struct disjunction<>\n-    : false_type\n-    { };\n-\n-  template<typename _Pp>\n-    struct negation\n-    : __not_<_Pp>::type\n-    { };\n-\n-  /** @ingroup variable_templates\n-   * @{\n-   */\n-  template<typename... _Bn>\n-    inline constexpr bool conjunction_v = conjunction<_Bn...>::value;\n-\n-  template<typename... _Bn>\n-    inline constexpr bool disjunction_v = disjunction<_Bn...>::value;\n-\n-  template<typename _Pp>\n-    inline constexpr bool negation_v = negation<_Pp>::value;\n-  /// @}\n-\n-#endif // __cpp_lib_logical_traits\n-\n   // Forward declarations\n   template<typename>\n     struct is_object;\n@@ -3871,6 +3803,80 @@ template<typename _Ret, typename _Fn, typename... _Args>\n /// @}\n #endif // __cpp_lib_type_trait_variable_templates\n \n+#ifdef __cpp_lib_logical_traits // C++ >= 17\n+\n+  /// @cond undocumented\n+  template<typename... _Bn>\n+    inline constexpr bool __or_v = __or_<_Bn...>::value;\n+  template<typename... _Bn>\n+    inline constexpr bool __and_v = __and_<_Bn...>::value;\n+\n+  namespace __detail\n+  {\n+    template<typename /* = void */, typename _B1, typename... _Bn>\n+      struct __disjunction_impl\n+      { using type = _B1; };\n+\n+    template<typename _B1, typename _B2, typename... _Bn>\n+      struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...>\n+      { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; };\n+\n+    template<typename /* = void */, typename _B1, typename... _Bn>\n+      struct __conjunction_impl\n+      { using type = _B1; };\n+\n+    template<typename _B1, typename _B2, typename... _Bn>\n+      struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...>\n+      { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; };\n+  } // namespace __detail\n+  /// @endcond\n+\n+  template<typename... _Bn>\n+    struct conjunction\n+    : __detail::__conjunction_impl<void, _Bn...>::type\n+    {\n+      typedef typename __detail::__conjunction_impl<void, _Bn...>::type __type;\n+      static_assert(is_convertible_v<decltype(__type::value), bool>);\n+    };\n+\n+  template<>\n+    struct conjunction<>\n+    : true_type\n+    { };\n+\n+  template<typename... _Bn>\n+    struct disjunction\n+    : __detail::__disjunction_impl<void, _Bn...>::type\n+    {\n+      typedef typename __detail::__disjunction_impl<void, _Bn...>::type __type;\n+      static_assert(is_convertible_v<decltype(__type::value), bool>);\n+    };\n+\n+  template<>\n+    struct disjunction<>\n+    : false_type\n+    { };\n+\n+  template<typename _Pp>\n+    struct negation\n+    : __not_<_Pp>::type\n+    { };\n+\n+  /** @ingroup variable_templates\n+   * @{\n+   */\n+  template<typename... _Bn>\n+    inline constexpr bool conjunction_v = conjunction<_Bn...>::value;\n+\n+  template<typename... _Bn>\n+    inline constexpr bool disjunction_v = disjunction<_Bn...>::value;\n+\n+  template<typename _Pp>\n+    inline constexpr bool negation_v = negation<_Pp>::value;\n+  /// @}\n+\n+#endif // __cpp_lib_logical_traits\n+\n #ifdef __cpp_lib_has_unique_object_representations // C++ >= 17 && HAS_UNIQ_OBJ_REP\n   /// has_unique_object_representations\n   /// @since C++17\ndiff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc\nnew file mode 100644\nindex 0000000000000..bfa502fe03116\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/junction_neg.cc\n@@ -0,0 +1,31 @@\n+// { dg-do compile { target c++17 } }\n+\n+#include <type_traits>\n+\n+class S {}; // not convertible to bool\n+\n+struct T {\n+  static constexpr S value{};\n+};\n+\n+// 4 Every template type argument for which Bi::value is instantiated shall be\n+// usable as a base class and shall have a member value which is convertible to\n+// bool, is not hidden, and is unambiguously available in the type.\n+\n+// ctT and dfT test that we don't fuse error messages when the type that\n+// doesn't satisfy the requirements start a shared tail of types in the _impl\n+// instantiations.\n+\n+std::conjunction<T> cT; // { dg-error \"here\" }\n+std::conjunction<T, std::true_type> cTt; // { dg-error \"here\" }\n+std::conjunction<T, std::false_type> cTf; // { dg-error \"here\" }\n+std::conjunction<std::true_type, T> ctT; // { dg-error \"here\" }\n+std::conjunction<std::false_type, T> cfT;\n+\n+std::disjunction<T> dT; // { dg-error \"here\" }\n+std::disjunction<T, std::false_type> dTf; // { dg-error \"here\" }\n+std::disjunction<T, std::true_type> dTt; // { dg-error \"here\" }\n+std::disjunction<std::false_type, T> dfT; // { dg-error \"here\" }\n+std::disjunction<std::true_type, T> dtT;\n+\n+// { dg-prune-output {(static assertion failed|could not convert|evaluates to false)} }\n","prefixes":["v3"]}