llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

... when creating the temporary variables for a
MaterializeTemporaryExpr.

---

Patch is 24.69 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/128141.diff


3 Files Affected:

- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+47-42) 
- (modified) clang/lib/AST/ByteCode/Compiler.h (+1-1) 
- (added) clang/test/AST/ByteCode/libcxx/primitive-temporary.cpp (+271) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 503c58a67adeb..ec18f9d72b66f 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -567,8 +567,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
     // Location for the SubExpr.
     // Since SubExpr is of complex type, visiting it results in a pointer
     // anyway, so we just create a temporary pointer variable.
-    unsigned SubExprOffset = allocateLocalPrimitive(
-        SubExpr, PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
+    unsigned SubExprOffset =
+        allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(SubExpr))
       return false;
     if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE))
@@ -611,8 +611,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
 
     const auto *VT = CE->getType()->getAs<VectorType>();
     PrimType ElemT = classifyPrim(SubExpr->getType());
-    unsigned ElemOffset = allocateLocalPrimitive(
-        SubExpr, ElemT, /*IsConst=*/true, /*IsExtended=*/false);
+    unsigned ElemOffset =
+        allocateLocalPrimitive(SubExpr, ElemT, /*IsConst=*/true);
 
     // Prepare a local variable for the scalar value.
     if (!this->visit(SubExpr))
@@ -1104,7 +1104,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const 
BinaryOperator *E) {
   PrimType ResultElemT = this->classifyComplexElementType(E->getType());
   unsigned ResultOffset = ~0u;
   if (!DiscardResult)
-    ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false);
+    ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);
 
   // Save result pointer in ResultOffset
   if (!this->DiscardResult) {
@@ -1178,14 +1178,14 @@ bool Compiler<Emitter>::VisitComplexBinOp(const 
BinaryOperator *E) {
 
   // Evaluate LHS and save value to LHSOffset.
   if (LHSType->isAnyComplexType()) {
-    LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false);
+    LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(LHS))
       return false;
     if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
       return false;
   } else {
     PrimType LHST = classifyPrim(LHSType);
-    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, true, false);
+    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
     if (!this->visit(LHS))
       return false;
     if (!this->emitSetLocal(LHST, LHSOffset, E))
@@ -1195,14 +1195,14 @@ bool Compiler<Emitter>::VisitComplexBinOp(const 
BinaryOperator *E) {
   // Same with RHS.
   unsigned RHSOffset;
   if (RHSType->isAnyComplexType()) {
-    RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false);
+    RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(RHS))
       return false;
     if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
       return false;
   } else {
     PrimType RHST = classifyPrim(RHSType);
-    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, true, false);
+    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
     if (!this->visit(RHS))
       return false;
     if (!this->emitSetLocal(RHST, RHSOffset, E))
@@ -1342,14 +1342,16 @@ bool Compiler<Emitter>::VisitVectorBinOp(const 
BinaryOperator *E) {
   PrimType ResultElemT = this->classifyVectorElementType(E->getType());
 
   // Evaluate LHS and save value to LHSOffset.
-  unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false);
+  unsigned LHSOffset =
+      this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
   if (!this->visit(LHS))
     return false;
   if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
     return false;
 
   // Evaluate RHS and save value to RHSOffset.
-  unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false);
+  unsigned RHSOffset =
+      this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
   if (!this->visit(RHS))
     return false;
   if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
@@ -2710,8 +2712,8 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
   // For everyhing else, use local variables.
   if (SubExprT) {
     bool IsConst = SubExpr->getType().isConstQualified();
-    unsigned LocalIndex = allocateLocalPrimitive(E, *SubExprT, IsConst,
-                                                 /*IsExtended=*/true);
+    unsigned LocalIndex =
+        allocateLocalPrimitive(E, *SubExprT, IsConst, E->getExtendingDecl());
     if (!this->visit(SubExpr))
       return false;
     if (!this->emitSetLocal(*SubExprT, LocalIndex, E))
@@ -2781,7 +2783,7 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const 
CompoundLiteralExpr *E) {
     unsigned LocalIndex;
 
     if (T)
-      LocalIndex = this->allocateLocalPrimitive(Init, *T, false, false);
+      LocalIndex = this->allocateLocalPrimitive(Init, *T, /*IsConst=*/false);
     else if (std::optional<unsigned> MaybeIndex = this->allocateLocal(Init))
       LocalIndex = *MaybeIndex;
     else
@@ -3337,8 +3339,8 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr 
*E) {
     PrimType SizeT = classifyPrim(Stripped->getType());
 
     // Save evaluated array size to a variable.
-    unsigned ArrayLen = allocateLocalPrimitive(
-        Stripped, SizeT, /*IsConst=*/false, /*IsExtended=*/false);
+    unsigned ArrayLen =
+        allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
     if (!this->visit(Stripped))
       return false;
     if (!this->emitSetLocal(SizeT, ArrayLen, E))
@@ -3416,8 +3418,8 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr 
*E) {
         }
 
         // Create loop variables.
-        unsigned Iter = allocateLocalPrimitive(
-            Stripped, SizeT, /*IsConst=*/false, /*IsExtended=*/false);
+        unsigned Iter =
+            allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
         if (!this->emitConst(StaticInitElems, SizeT, E))
           return false;
         if (!this->emitSetLocal(SizeT, Iter, E))
@@ -3668,8 +3670,8 @@ template <class Emitter>
 bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
   assert(E->getType()->isVoidPointerType());
 
-  unsigned Offset = allocateLocalPrimitive(
-      E->getLabel(), PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
+  unsigned Offset =
+      allocateLocalPrimitive(E->getLabel(), PT_Ptr, /*IsConst=*/true);
 
   return this->emitGetLocal(PT_Ptr, Offset, E);
 }
@@ -3684,7 +3686,8 @@ bool Compiler<Emitter>::VisitConvertVectorExpr(const 
ConvertVectorExpr *E) {
   QualType SrcType = Src->getType();
   PrimType SrcElemT = classifyVectorElementType(SrcType);
 
-  unsigned SrcOffset = this->allocateLocalPrimitive(Src, PT_Ptr, true, false);
+  unsigned SrcOffset =
+      this->allocateLocalPrimitive(Src, PT_Ptr, /*IsConst=*/true);
   if (!this->visit(Src))
     return false;
   if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))
@@ -3727,8 +3730,8 @@ bool Compiler<Emitter>::VisitShuffleVectorExpr(const 
ShuffleVectorExpr *E) {
   // Save both input vectors to a local variable.
   unsigned VectorOffsets[2];
   for (unsigned I = 0; I != 2; ++I) {
-    VectorOffsets[I] = this->allocateLocalPrimitive(
-        Vecs[I], PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
+    VectorOffsets[I] =
+        this->allocateLocalPrimitive(Vecs[I], PT_Ptr, /*IsConst=*/true);
     if (!this->visit(Vecs[I]))
       return false;
     if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))
@@ -3780,8 +3783,7 @@ bool Compiler<Emitter>::VisitExtVectorElementExpr(
   }
 
   // Create a local variable for the base.
-  unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true,
-                                               /*IsExtended=*/false);
+  unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true);
   if (!this->visit(Base))
     return false;
   if (!this->emitSetLocal(PT_Ptr, BaseOffset, E))
@@ -4193,9 +4195,8 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, 
const Expr *E) {
 }
 
 template <class Emitter>
-unsigned Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty,
-                                                   bool IsConst,
-                                                   bool IsExtended) {
+unsigned Compiler<Emitter>::allocateLocalPrimitive(
+    DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl) {
   // Make sure we don't accidentally register the same decl twice.
   if (const auto *VD =
           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
@@ -4212,7 +4213,10 @@ unsigned 
Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty,
   Scope::Local Local = this->createLocal(D);
   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
     Locals.insert({VD, Local});
-  VarScope->add(Local, IsExtended);
+  if (ExtendingDecl)
+    VarScope->addExtended(Local, ExtendingDecl);
+  else
+    VarScope->add(Local, false);
   return Local.Offset;
 }
 
@@ -4780,7 +4784,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
       // decl as the function pointer.
       const Expr *Callee = E->getCallee();
       CalleeOffset =
-          this->allocateLocalPrimitive(Callee, PT_MemberPtr, true, false);
+          this->allocateLocalPrimitive(Callee, PT_MemberPtr, /*IsConst=*/true);
       if (!this->visit(Callee))
         return false;
       if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))
@@ -4802,7 +4806,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
     return this->emitKill(E);
   } else if (!FuncDecl) {
     const Expr *Callee = E->getCallee();
-    CalleeOffset = this->allocateLocalPrimitive(Callee, PT_FnPtr, true, false);
+    CalleeOffset =
+        this->allocateLocalPrimitive(Callee, PT_FnPtr, /*IsConst=*/true);
     if (!this->visit(Callee))
       return false;
     if (!this->emitSetLocal(PT_FnPtr, *CalleeOffset, E))
@@ -5404,7 +5409,8 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt 
*S) {
 
   LabelTy EndLabel = this->getLabel();
   OptLabelTy DefaultLabel = std::nullopt;
-  unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false);
+  unsigned CondVar =
+      this->allocateLocalPrimitive(Cond, CondT, /*IsConst=*/true);
 
   if (const auto *CondInit = S->getInit())
     if (!visitStmt(CondInit))
@@ -6067,7 +6073,8 @@ bool Compiler<Emitter>::VisitComplexUnaryOperator(const 
UnaryOperator *E) {
   // The offset of the temporary, if we created one.
   unsigned SubExprOffset = ~0u;
   auto createTemp = [=, &SubExprOffset]() -> bool {
-    SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
+    SubExprOffset =
+        this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(SubExpr))
       return false;
     return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
@@ -6181,7 +6188,7 @@ bool Compiler<Emitter>::VisitVectorUnaryOperator(const 
UnaryOperator *E) {
 
   // The offset of the temporary, if we created one.
   unsigned SubExprOffset =
-      this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
+      this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
   if (!this->visit(SubExpr))
     return false;
   if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))
@@ -6554,8 +6561,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr 
*LHS, const Expr *RHS,
   if (LHS->getType()->isAnyComplexType()) {
     LHSIsComplex = true;
     ElemT = classifyComplexElementType(LHS->getType());
-    LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true,
-                                       /*IsExtended=*/false);
+    LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(LHS))
       return false;
     if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
@@ -6563,7 +6569,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr 
*LHS, const Expr *RHS,
   } else {
     LHSIsComplex = false;
     PrimType LHST = classifyPrim(LHS->getType());
-    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, true, false);
+    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
     if (!this->visit(LHS))
       return false;
     if (!this->emitSetLocal(LHST, LHSOffset, E))
@@ -6575,8 +6581,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr 
*LHS, const Expr *RHS,
   if (RHS->getType()->isAnyComplexType()) {
     RHSIsComplex = true;
     ElemT = classifyComplexElementType(RHS->getType());
-    RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true,
-                                       /*IsExtended=*/false);
+    RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
     if (!this->visit(RHS))
       return false;
     if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
@@ -6584,7 +6589,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr 
*LHS, const Expr *RHS,
   } else {
     RHSIsComplex = false;
     PrimType RHST = classifyPrim(RHS->getType());
-    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, true, false);
+    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
     if (!this->visit(RHS))
       return false;
     if (!this->emitSetLocal(RHST, RHSOffset, E))
@@ -6761,8 +6766,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr 
*E) {
     if (!this->visit(SubExpr))
       return false;
   } else if (std::optional<PrimType> FromT = classify(SubExpr)) {
-    unsigned TempOffset = allocateLocalPrimitive(
-        SubExpr, *FromT, /*IsConst=*/true, /*IsExtended=*/false);
+    unsigned TempOffset =
+        allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);
     if (!this->visit(SubExpr))
       return false;
     if (!this->emitSetLocal(*FromT, TempOffset, E))
diff --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 0a93c46a40ef5..77fcc3d1b41ce 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -303,7 +303,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, 
bool>,
 
   /// Creates a local primitive value.
   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
-                                  bool IsExtended = false);
+                                  const ValueDecl *ExtendingDecl = nullptr);
 
   /// Allocates a space storing a local given its type.
   std::optional<unsigned>
diff --git a/clang/test/AST/ByteCode/libcxx/primitive-temporary.cpp 
b/clang/test/AST/ByteCode/libcxx/primitive-temporary.cpp
new file mode 100644
index 0000000000000..475f7ffef4525
--- /dev/null
+++ b/clang/test/AST/ByteCode/libcxx/primitive-temporary.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++2c  -verify=ref,both %s
+
+// both-no-diagnostics
+
+namespace std {
+inline namespace {
+template <class _Tp, _Tp __v> struct integral_constant {
+  static const _Tp value = __v;
+};
+template <bool _Val> using _BoolConstant = integral_constant<bool, _Val>;
+template <class _Tp> using __remove_cv_t = __remove_cv(_Tp);
+template <class _Tp> using remove_cv_t = __remove_cv_t<_Tp>;
+} // namespace
+inline namespace __1 {
+template <class _Tp>
+using __libcpp_remove_reference_t = __remove_reference_t(_Tp);
+template <bool, class _IfRes, class> using conditional_t = _IfRes;
+template <class _Tp, class _Up>
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
+template <class _Tp> struct enable_if {
+  typedef _Tp type;
+};
+template <bool, class _Tp = void> using __enable_if_t = _Tp;
+template <class _Bp, class _Dp>
+constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp);
+template <class _Tp> _Tp __declval(long);
+template <class _Tp> decltype(__declval<_Tp>(0)) declval();
+template <class _Fp, class... _Args>
+constexpr decltype(declval<_Fp>()(declval<_Args>()...))
+__invoke(_Fp __f, _Args... __args) {
+  return (__f)((__args)...);
+}
+template <class, class _Fp, class... _Args> struct __invokable_r {
+  template <class _XFp, class... _XArgs>
+  static decltype(__invoke(declval<_XFp>(), declval<_XArgs>()...))
+  __try_call(int);
+  using _Result = decltype(__try_call<_Fp, _Args...>(0));
+};
+template <class _Func, class... _Args>
+struct __invoke_result
+    : enable_if<typename __invokable_r<void, _Func, _Args...>::_Result> {};
+template <class _Fn, class... _Args>
+using invoke_result_t = __invoke_result<_Fn, _Args...>::type;
+template <class _Tp> constexpr __libcpp_remove_reference_t<_Tp> &&move(_Tp &&);
+template <class _From, class _To>
+constexpr bool is_convertible_v = __is_convertible(_From, _To);
+template <class _From, class _To>
+concept convertible_to =
+    is_convertible_v<_From, _To> && requires { (declval<_From>()); };
+template <class _Tp, class _Up>
+concept __same_as_impl = _IsSame<_Tp, _Up>::value;
+template <class _Tp, class _Up>
+concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
+template <class _Tp> using __remove_cvref_t = __remove_cvref(_Tp);
+template <class _Tp> using remove_cvref_t = __remove_cvref_t<_Tp>;
+template <class _Xp, class _Yp>
+using __cond_res =
+    decltype(false ? declval<_Xp (&)()>()() : declval<_Yp (&)()>()());
+template <class...> struct common_reference;
+template <class... _Types>
+using common_reference_t = common_reference<_Types...>::type;
+template <class, class> struct __common_reference_sub_bullet3;
+template <class _Tp, class _Up>
+struct common_reference<_Tp, _Up> : __common_reference_sub_bullet3<_Tp, _Up> 
{};
+template <class _Tp, class _Up>
+  requires requires { typename __cond_res<_Tp, _Up>; }
+struct __common_reference_sub_bullet3<_Tp, _Up> {
+  using type = __cond_res<_Tp, _Up>;
+};
+template <class _Tp, class _Up>
+concept common_reference_with =
+    same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> &&
+    convertible_to<_Tp, common_reference_t<_Tp, _Up>> &&
+    convertible_to<_Up, common_reference_t<_Tp, _Up>>;
+template <class _Tp>
+using __make_const_lvalue_ref = __libcpp_remove_reference_t<_Tp>;
+template <class _Lhs, class _Rhs>
+concept assignable_from =
+    common_reference_with<__make_const_lvalue_ref<_Lhs>,
+                          __make_const_lvalue_ref<_Rhs>> &&
+    requires(_Lhs __lhs, _Rhs __rhs) {
+      { __lhs = (__rhs) };
+    };
+template <class _Tp>
+concept default_initializable = requires { _Tp{}; };
+template <class _Tp> constexpr bool is_object_v = __is_object(_Tp);
+template <class _Dp, class _Bp>
+concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<_Dp *, _Bp 
*>;
+template <class _Tp, class _Up>
+concept __weakly_equality_comparable_with = requires(
+    __make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
+  { __u };
+};
+template <class _Fn, class... _Args>
+constexpr invoke_result_t<_Fn, _Args...> invoke(_Fn __f, _Args &&...__args) {
+  return __invoke((__f), (__args)...);
+}
+template <class _Fn, class... _Args>
+concept invocable =
+    requires(_Fn __fn, _Args... __args) { invoke((__fn), (__args)...); };
+template <class _Fn, class... _Args>
+concept regular_invocable = invocable<_Fn, _Args...>;
+template <template <class> class, class>
+integral_constant<bool, false> __sfinae_test_impl();
+template <template <class> class _Templ, class... _Args>
+using _IsValidExpansion = decltype(__sfinae_test_impl<_Templ, _Args...>());
+template <class _Tp>
+using __test_for_primary_template =
+    __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;
+template <class _Tp>
+using __is_primary_template =
+    _IsValidExpansion<__test_for_primary_template, _Tp>;
+template <class> struct __cond_value_type;
+template <class _Tp>
+  requires is_object_v<_Tp>
+struct __cond_value_type<_Tp> {
+  using value_type = remove_cv_t<_Tp>;
+};
+template <class _Tp>
+concept __has_member_value_type = requires { typename _Tp; };
+template <class> struct indirectly_readable_traits;
+template <class _Tp>
+struct indirectly_readable_traits<_Tp *> : __cond_value_type<_Tp> {};
+template <__has_member_value_type _Tp>
+struct indirectly_readable_traits<_Tp>
+    : __cond_value_type<typename _Tp::value_type> {};
+template <bool> struct _OrImpl;
+template <> struct _OrImpl<true> {
+  template <class, class _First, class... _Rest>
+  using _Result =
+      _OrImpl<!bool() && sizeof...(_Rest)>::template _Result<_First, _Rest...>;
+};
+template <> struct _OrImpl<false> {
+  template <class _Res> using _Result = _Res;
+...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/128141
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to