[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-22 Thread Louis Dionne via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa0839b14df6d: [libc++] Fix tuple assignment from types 
derived from a tuple-like (authored by ldionne).

Changed prior to commit:
  https://reviews.llvm.org/D50106?vs=325449=325524#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/array.extension.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using 

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-22 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 325449.
ldionne added a comment.

Rebase onto main.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/array.extension.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  CondT::type,
+CondT::type, Vp>>;
+
+  template 
+  using Apply = ApplyReferenceQuals>>;
+
+  template ::type = true>
+  static Apply> cast(Tp &) {
+using ToType = Apply>;
+return static_cast(t);
+  }
+
+  template ::type = true>

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-22 Thread Louis Dionne via Phabricator via cfe-commits
ldionne added a comment.

I think we should be pretty much good to go now. Will let CI run just in case.




Comment at: libcxx/include/tuple:971
+_VSTD::get<0>(*this) = _VSTD::forward<_Up1>(__pair.first);
+_VSTD::get<1>(*this) = _VSTD::forward<_Up2>(__pair.second);
+return *this;

Quuxplusone wrote:
> Oh, late-breaking nit: I would prefer to see `... = 
> static_cast<_Up1&&>(__pair.first);` here, because `_Up1` is not being deduced 
> according to forwarding-reference rules, and thus shouldn't be "forwarded."  
> Pragmatically I think `forward<_Up1>` ends up doing the right thing in all 
> cases... but I don't think it's appropriate here. (Plus, we save one function 
> template instantiation by omitting it!)
It actually occurs to me that we should really be using 
`_VSTD::move(__pair.first)` since we're taking a rvalue reference to the pair 
as an argument. I'll change it to that, please LMK if you disagree.



Comment at: libcxx/include/tuple:975
+
+// EXTENSION
+template Perhaps in a followup patch: could we delineate exactly what code is part of 
> this extension and put it all under an `#if _LIBCPP_TUPLE_ARRAY_ASSIGNMENT` 
> or something, such that we could say "this is the exact extent of the 
> extension code" and maybe even get customers to try compiling with 
> `-D_LIBCPP_TUPLE_ARRAY_ASSIGNMENT=0` to see what breaks?
> 
> I'm assuming that our goal here is to deprecate and remove this extension 
> over time. But even if we support it forever, I think `#if` would be nicer 
> than the `//EXTENSION` comments.
The goal is to remove the extension shortly after.



Comment at: libcxx/include/tuple:992
+// EXTENSION
+template Nitpick: Sent you a Slack suggesting how to eliminate this `class = void`.
Replied there. The short story is that I used `class = void` to workaround the 
GCC segfaults I was seeing on the bots.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-22 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 325445.
ldionne marked 6 inline comments as done.
ldionne added a comment.

Address Arthur's comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/array.extension.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  CondT::type,
+CondT::type, Vp>>;
+
+  template 
+  using Apply = ApplyReferenceQuals>>;
+
+  template ::type = true>
+  static Apply> cast(Tp &) {
+using ToType = Apply>;
+return 

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-19 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: libcxx/include/tuple:971
+_VSTD::get<0>(*this) = _VSTD::forward<_Up1>(__pair.first);
+_VSTD::get<1>(*this) = _VSTD::forward<_Up2>(__pair.second);
+return *this;

Oh, late-breaking nit: I would prefer to see `... = 
static_cast<_Up1&&>(__pair.first);` here, because `_Up1` is not being deduced 
according to forwarding-reference rules, and thus shouldn't be "forwarded."  
Pragmatically I think `forward<_Up1>` ends up doing the right thing in all 
cases... but I don't think it's appropriate here. (Plus, we save one function 
template instantiation by omitting it!)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-19 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.

Suggested some ways to improve test coverage, and continued bikeshedding on the 
SFINAE ;) but there's no reason to hold this up AFAIC.




Comment at: libcxx/include/tuple:58
 tuple& operator=(const tuple&);
-tuple&
-operator=(tuple&&) noexcept(AND(is_nothrow_move_assignable::value 
...));
+tuple& operator=(tuple&&) 
noexcept(AND(is_nothrow_move_assignable::value ...));
 template 

Since this already isn't mimicking the syntax of 
http://eel.is/c++draft/tuple.tuple#tuple.assign-1 , I think you should say

tuple& operator=(tuple&&) noexcept(is_nothrow_move_assignable_v && ...);

but it definitely doesn't matter.



Comment at: libcxx/include/tuple:975
+
+// EXTENSION
+template Array;
+static_assert(!std::is_nothrow_assignable::value, "");
+}

I would like to see this file combined with rvalue_array.pass.cpp, and also 
test the currently missing two value categories:

static_assert(std::is_nothrow_assignable::value, "");
static_assert(std::is_nothrow_assignable::value, "");

and also the negative cases:

static_assert(!std::is_assignable&>::value, "");
static_assert(!std::is_assignable&&>::value, "");
static_assert(!std::is_assignable&>::value, "");
static_assert(!std::is_assignable&&>::value, "");

static_assert(!std::is_assignable&>::value, "");
static_assert(!std::is_assignable&&>::value, "");
static_assert(!std::is_assignable&>::value, "");
static_assert(!std::is_assignable&&>::value, "");




Comment at: 
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp:52
+typedef std::pair Pair;
+static_assert(!std::is_nothrow_assignable::value, 
"");
+}

Don't just test for lack-of-nothrow-assignability; test for 
assignability-but-maythrow:

static_assert(std::is_assignable::value, "");
static_assert(!std::is_nothrow_assignable::value, "");

And as above, I'd prefer to see tests for `Pair&` and `Pair&&` and `const 
Pair&&` as well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-19 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 325039.
ldionne added a comment.

Fix GCC issues. I swear I had done the same fix locally previously, but I must
have messed something up with Git or `arc diff`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/const_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/rvalue_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  CondT::type,
+CondT::type, Vp>>;
+
+  template 

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-18 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 324648.
ldionne added a comment.

Address Arthur's comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/const_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/rvalue_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  CondT::type,
+CondT::type, Vp>>;
+
+  template 
+  using Apply = ApplyReferenceQuals>>;
+
+  template ::type = true>
+  static Apply> cast(Tp &) {

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-18 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 324645.
ldionne added a comment.

Fix build on GCC (or at least I think it should)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/const_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/rvalue_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  CondT::type,
+CondT::type, Vp>>;
+
+  template 
+  using Apply = ApplyReferenceQuals>>;
+
+  template ::type = true>
+  

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: libcxx/include/tuple:432
+void __memberwise_copy_assign(_Dest& __dest, _Source const& __source, 
__tuple_indices<_Np...>) {
+__swallow(((_VSTD::get<_Np>(__dest) = _VSTD::get<_Np>(__source)), void(), 
int())...);
+}

Your friendly neighborhood ADL hater says: `_VSTD::__swallow` plz
(and line 438)
(and maybe `int()` is a sillier-than-necessary way to write `0`?)



Comment at: libcxx/include/tuple:891
+{
+__memberwise_copy_assign(*this, __tuple,
+typename __make_tuple_indices::type());

Your friendly neighborhood ADL hater says: `_VSTD::` plz
(and line 900)
(and line 931)
(and line 986)
(and line 1002)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-11 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 323047.
ldionne added a comment.

Fix segfault on GCC and a few incorrect checks in the type traits.

I reduced the GCC segfault and it appears to have been fixed on GCC trunk, so
I won't be filing a bug report.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/const_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/rvalue_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+  hasValueCategory(VC, VC_ConstVolatile), typename std::add_cv::type,
+  CondT::type,
+CondT::type, Tp>>>;
+
+  template ::type>
+  using ApplyReferenceQuals =
+  

[PATCH] D50106: [libc++] Fix tuple assignment from types derived from a tuple-like

2021-02-10 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 322746.
ldionne retitled this revision from "[libc++] Fix tuple assignment from type 
derived from a tuple-like" to "[libc++] Fix tuple assignment from types derived 
from a tuple-like".
ldionne edited the summary of this revision.
ldionne added a comment.
Herald added a project: libc++.
Herald added a reviewer: libc++.

Fix issues with the laziness of how we evaluate type traits


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D50106/new/

https://reviews.llvm.org/D50106

Files:
  libcxx/include/tuple
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/const_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/rvalue_array.pass.cpp
  
libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/derived_from_tuple_like.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
  libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
  
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/tuple_array_template_depth.pass.cpp
  libcxx/test/support/propagate_value_category.hpp

Index: libcxx/test/support/propagate_value_category.hpp
===
--- /dev/null
+++ libcxx/test/support/propagate_value_category.hpp
@@ -0,0 +1,153 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#ifndef TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+#define TEST_SUPPORT_PROPAGATE_VALUE_CATEGORY
+
+#include "test_macros.h"
+#include 
+
+#if TEST_STD_VER < 11
+#error this header may only be used in C++11
+#endif
+
+using UnderlyingVCType = unsigned;
+enum ValueCategory : UnderlyingVCType {
+  VC_None = 0,
+  VC_LVal = 1 << 0,
+  VC_RVal = 1 << 1,
+  VC_Const = 1 << 2,
+  VC_Volatile = 1 << 3,
+  VC_ConstVolatile = VC_Const | VC_Volatile
+};
+
+inline constexpr ValueCategory operator&(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS & (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator|(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS | (UnderlyingVCType)RHS);
+}
+
+inline constexpr ValueCategory operator^(ValueCategory LHS, ValueCategory RHS) {
+  return ValueCategory(LHS ^ (UnderlyingVCType)RHS);
+}
+
+inline constexpr bool isValidValueCategory(ValueCategory VC) {
+  return (VC & (VC_LVal | VC_RVal)) != (VC_LVal | VC_RVal);
+}
+
+inline constexpr bool hasValueCategory(ValueCategory Arg, ValueCategory Key) {
+  return Arg == Key || ((Arg & Key) == Key);
+}
+
+template 
+using UnCVRef =
+typename std::remove_cv::type>::type;
+
+template 
+constexpr ValueCategory getReferenceQuals() {
+  return std::is_lvalue_reference::value
+ ? VC_LVal
+ : (std::is_rvalue_reference::value ? VC_RVal : VC_None);
+}
+static_assert(getReferenceQuals() == VC_None, "");
+static_assert(getReferenceQuals() == VC_LVal, "");
+static_assert(getReferenceQuals() == VC_RVal, "");
+
+template 
+constexpr ValueCategory getCVQuals() {
+  using Vp = typename std::remove_reference::type;
+  return std::is_const::value && std::is_volatile::value
+ ? VC_ConstVolatile
+ : (std::is_const::value
+? VC_Const
+: (std::is_volatile::value ? VC_Volatile : VC_None));
+}
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+static_assert(getCVQuals() == VC_Volatile, "");
+static_assert(getCVQuals() == VC_ConstVolatile, "");
+static_assert(getCVQuals() == VC_None, "");
+static_assert(getCVQuals() == VC_Const, "");
+
+template 
+inline constexpr ValueCategory getValueCategory() {
+  return getReferenceQuals() | getCVQuals();
+}
+static_assert(getValueCategory() == VC_None, "");
+static_assert(getValueCategory() == (VC_LVal | VC_Const), "");
+static_assert(getValueCategory() ==
+  (VC_RVal | VC_ConstVolatile),
+  "");
+
+template 
+struct ApplyValueCategory {
+private:
+  static_assert(isValidValueCategory(VC), "");
+
+  template 
+  using CondT = typename std::conditional::type;
+
+public:
+  template >
+  using ApplyCVQuals = CondT<
+