[libcxx-commits] [PATCH] D147560: [libc++] Fix std::optional-related type deduction

Ian McKellar via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 4 12:35:48 PDT 2023


ianloic created this revision.
Herald added a project: All.
ianloic requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

When clang a constructor invocation where there are single-argument
constructors that take either std::optional or some other type the
checks in _CheckOptionalArgsConstructor fail becaues that helper tries
(and fails) to take a reference to void.

A simple example is here: https://godbolt.org/z/bPdzYfcnv
This works just fine with other C++ standard library implementations.

This change introduces a check against void in the
_CheckOptionalArgsCtor helper so that it won't try to instantiate the
_CheckOptionalArgsConstructor if the compiler is guessing that _Up is
void.

This fixes bug https://github.com/llvm/llvm-project/issues/61692 and
maybe https://github.com/llvm/llvm-project/issues/48959.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147560

Files:
  libcxx/include/optional
  libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ambigous_constructor.pass.cpp


Index: libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ambigous_constructor.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ambigous_constructor.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// <optional>
+
+#include <optional>
+#include <string>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::string;
+
+struct Outer {
+  struct Inner {
+    optional<string> s;
+  };
+  Outer(Inner&& inner) noexcept : inner_(std::move(inner)) {}
+  explicit Outer(std::optional<std::string> s) noexcept { inner_.s = s; }
+
+  Inner inner_;
+};
+
+int main(int, char**) {
+  Outer __test{{.s = "hello"}};
+
+  return 0;
+}
\ No newline at end of file
Index: libcxx/include/optional
===================================================================
--- libcxx/include/optional
+++ libcxx/include/optional
@@ -675,12 +675,11 @@
       }
     };
     template <class _Up>
-    using _CheckOptionalArgsCtor = _If<
-        _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value &&
-        _IsNotSame<__remove_cvref_t<_Up>, optional>::value,
-        _CheckOptionalArgsConstructor,
-        __check_tuple_constructor_fail
-    >;
+    using _CheckOptionalArgsCtor =
+        _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value &&
+                 _IsNotSame<__remove_cvref_t<_Up>, optional>::value && _IsNotSame<__remove_cvref_t<_Up>, void>::value,
+             _CheckOptionalArgsConstructor,
+             __check_tuple_constructor_fail >;
     template <class _QualUp>
     struct _CheckOptionalLikeConstructor {
       template <class _Up, class _Opt = optional<_Up>>


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147560.510896.patch
Type: text/x-patch
Size: 2160 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20230404/a8b04863/attachment.bin>


More information about the libcxx-commits mailing list