Author: Nico Weber
Date: 2025-12-02T19:37:16-05:00
New Revision: e05fffbbc54d201a60e55e8c051bad81eaebd69a

URL: 
https://github.com/llvm/llvm-project/commit/e05fffbbc54d201a60e55e8c051bad81eaebd69a
DIFF: 
https://github.com/llvm/llvm-project/commit/e05fffbbc54d201a60e55e8c051bad81eaebd69a.diff

LOG: Revert "[Clang] Add __builtin_common_reference (#121199)"

This reverts commit 3b9e203364dcd8234b12eb447ddbcf97a877558c.
Causes not-yet-understood semantic differences, see commits
on #121199.

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/Basic/BuiltinTemplates.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaTemplate.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Sema/SemaTypeTraits.cpp
    libcxx/include/__type_traits/common_reference.h
    libcxx/include/module.modulemap.in

Removed: 
    clang/test/SemaCXX/type-trait-common-reference.cpp


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 40cc18945764a..80cea2166bc83 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1833,23 +1833,6 @@ Builtin type aliases
 
 Clang provides a few builtin aliases to improve the throughput of certain 
metaprogramming facilities.
 
-__builtin_common_reference
---------------------------
-
-.. code-block:: c++
-
-  template <template <class, class, template <class> class, template <class> 
class> class BasicCommonReferenceT,
-            template <class... Args> CommonTypeT,
-            template <class> HasTypeMember,
-            class HasNoTypeMember,
-            class... Ts>
-  using __builtin_common_reference = ...;
-
-This alias is used for implementing ``std::common_reference``. If 
``std::common_reference`` should contain a ``type``
-member, it is an alias to ``HasTypeMember<TheCommonReference>``. Otherwse it 
is an alias to ``HasNoTypeMember``. The
-``CommonTypeT`` is usually ``std::common_type_t``. ``BasicCommonReferenceT`` 
is usually an alias template to
-``basic_common_reference<T, U, TX, UX>::type``.
-
 __builtin_common_type
 ---------------------
 

diff  --git a/clang/include/clang/Basic/BuiltinTemplates.td 
b/clang/include/clang/Basic/BuiltinTemplates.td
index 804871de2bdab..504405acbdc78 100644
--- a/clang/include/clang/Basic/BuiltinTemplates.td
+++ b/clang/include/clang/Basic/BuiltinTemplates.td
@@ -10,11 +10,11 @@ class TemplateArg<string name> {
   string Name = name;
 }
 
-class Template<list<TemplateArg> args, string name = ""> : TemplateArg<name> {
+class Template<list<TemplateArg> args, string name> : TemplateArg<name> {
   list<TemplateArg> Args = args;
 }
 
-class Class<string name = "", bit is_variadic = 0> : TemplateArg<name> {
+class Class<string name, bit is_variadic = 0> : TemplateArg<name> {
   bit IsVariadic = is_variadic;
 }
 
@@ -56,32 +56,6 @@ def __builtin_common_type : CPlusPlusBuiltinTemplate<
    Class<"HasNoTypeMember">,
    Class<"Ts", /*is_variadic=*/1>]>;
 
-// template <template <class,"
-//                     class,"
-//                     template <class> class,"
-//                     template <class> class> class BasicCommonReferenceT,"
-//           template <class... Args> class CommonTypeT,"
-//           template <class> class HasTypeMember,"
-//           class HasNoTypeMember,"
-//           class... Ts>"
-def __builtin_common_reference : CPlusPlusBuiltinTemplate<
-            [Template<[Class<>,
-                       Class<>,
-                       Template<[Class<>]>,
-                       Template<[Class<>]>], "BasicCommonReferenceT">,
-             Template<[Class<"Args", /*is_variadic=*/1>], "CommonTypeT">,
-             Template<[Class<>], "HasTypeMember">,
-             Class<"HasNoTypeMember">,
-             Class<"Ts", /*is_variadic=*/1>]>;
-
-foreach Ref = ["", "lvalue", "rvalue"] in {
-  foreach Const = ["", "const"] in {
-    foreach Volatile = ["", "volatile"] in {
-      def __clang_internal_xref_#Ref#Const#Volatile : 
CPlusPlusBuiltinTemplate<[Class<>]>;
-    }
-  }
-}
-
 // template <uint32_t Opcode,
 //           uint32_t Size,
 //           uint32_t Alignment,

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 19cca691e9859..78ecbccbe4efc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15322,17 +15322,6 @@ class Sema final : public SemaBase {
   QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
   QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
                                SourceLocation Loc);
-
-  QualType BuiltinAddRValueReference(QualType BaseType, SourceLocation Loc) {
-    return BuiltinAddReference(BaseType, 
UnaryTransformType::AddRvalueReference,
-                               Loc);
-  }
-
-  QualType BuiltinAddLValueReference(QualType BaseType, SourceLocation Loc) {
-    return BuiltinAddReference(BaseType, 
UnaryTransformType::AddLvalueReference,
-                               Loc);
-  }
-
   QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
                                SourceLocation Loc);
   QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
@@ -15347,9 +15336,6 @@ class Sema final : public SemaBase {
   QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
                                    SourceLocation Loc);
 
-  bool BuiltinIsConvertible(QualType From, QualType To, SourceLocation Loc,
-                            bool CheckNothrow = false);
-
   bool BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, QualType RhsT);
 
   /// Ensure that the type T is a literal type.

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ba91629783759..4a9e1bc93b918 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3212,36 +3212,6 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
   }
 }
 
-static QualType InstantiateTemplate(Sema &S, ElaboratedTypeKeyword Keyword,
-                                    TemplateName Template,
-                                    ArrayRef<TemplateArgument> Args,
-                                    SourceLocation Loc) {
-  TemplateArgumentListInfo ArgList;
-  for (auto Arg : Args) {
-    if (Arg.getKind() == TemplateArgument::Type) {
-      ArgList.addArgument(TemplateArgumentLoc(
-          Arg, S.Context.getTrivialTypeSourceInfo(Arg.getAsType())));
-    } else {
-      ArgList.addArgument(
-          S.getTrivialTemplateArgumentLoc(Arg, QualType(), Loc));
-    }
-  }
-
-  EnterExpressionEvaluationContext UnevaluatedContext(
-      S, Sema::ExpressionEvaluationContext::Unevaluated);
-  Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
-  Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-
-  QualType Instantiation =
-      S.CheckTemplateIdType(Keyword, Template, Loc, ArgList, /*Scope=*/nullptr,
-                            /*ForNestedNameSpecifier=*/false);
-
-  if (SFINAE.hasErrorOccurred())
-    return QualType();
-
-  return Instantiation;
-}
-
 static QualType builtinCommonTypeImpl(Sema &S, ElaboratedTypeKeyword Keyword,
                                       TemplateName BaseTemplate,
                                       SourceLocation TemplateLoc,
@@ -3254,7 +3224,25 @@ static QualType builtinCommonTypeImpl(Sema &S, 
ElaboratedTypeKeyword Keyword,
       return builtinCommonTypeImpl(S, Keyword, BaseTemplate, TemplateLoc,
                                    {T1, T2});
 
-    return InstantiateTemplate(S, Keyword, BaseTemplate, {T1, T2}, 
TemplateLoc);
+    TemplateArgumentListInfo Args;
+    Args.addArgument(TemplateArgumentLoc(
+        T1, S.Context.getTrivialTypeSourceInfo(T1.getAsType())));
+    Args.addArgument(TemplateArgumentLoc(
+        T2, S.Context.getTrivialTypeSourceInfo(T2.getAsType())));
+
+    EnterExpressionEvaluationContext UnevaluatedContext(
+        S, Sema::ExpressionEvaluationContext::Unevaluated);
+    Sema::SFINAETrap SFINAE(S, /*ForValidityCheck=*/true);
+    Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
+
+    QualType BaseTemplateInst = S.CheckTemplateIdType(
+        Keyword, BaseTemplate, TemplateLoc, Args,
+        /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);
+
+    if (SFINAE.hasErrorOccurred())
+      return QualType();
+
+    return BaseTemplateInst;
   };
 
   // Note A: For the common_type trait applied to a template parameter pack T 
of
@@ -3361,233 +3349,6 @@ static QualType builtinCommonTypeImpl(Sema &S, 
ElaboratedTypeKeyword Keyword,
   }
 }
 
-static QualType CopyCV(QualType From, QualType To) {
-  if (From.isConstQualified())
-    To.addConst();
-  if (From.isVolatileQualified())
-    To.addVolatile();
-  return To;
-}
-
-// Let COND-RES(X, Y) be
-//  decltype(false ? declval<X(&)()>()() : declval<Y(&)()>()())
-static QualType CondRes(Sema &S, QualType X, QualType Y, SourceLocation Loc) {
-  EnterExpressionEvaluationContext UnevaluatedContext(
-      S, Sema::ExpressionEvaluationContext::Unevaluated);
-  Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
-  Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-
-  // false
-  OpaqueValueExpr CondExpr(SourceLocation(), S.Context.BoolTy, VK_PRValue);
-  ExprResult Cond = &CondExpr;
-
-  // declval<X(&)()>()()
-  OpaqueValueExpr LHSExpr(Loc, X.getNonLValueExprType(S.Context),
-                          Expr::getValueKindForType(X));
-  ExprResult LHS = &LHSExpr;
-
-  // declval<Y(&)()>()()
-  OpaqueValueExpr RHSExpr(Loc, Y.getNonLValueExprType(S.Context),
-                          Expr::getValueKindForType(Y));
-  ExprResult RHS = &RHSExpr;
-
-  ExprValueKind VK = VK_PRValue;
-  ExprObjectKind OK = OK_Ordinary;
-
-  // decltype(false ? declval<X(&)()>()() : declval<Y(&)()>()())
-  QualType Result = S.CheckConditionalOperands(Cond, LHS, RHS, VK, OK, Loc);
-
-  if (SFINAE.hasErrorOccurred())
-    return QualType();
-  if (VK == VK_LValue)
-    return S.BuiltinAddLValueReference(Result, Loc);
-  if (VK == VK_XValue)
-    return S.BuiltinAddRValueReference(Result, Loc);
-  return Result;
-}
-
-static QualType CommonRef(Sema &S, QualType A, QualType B, SourceLocation Loc) 
{
-  // Given types A and B, let X be remove_reference_t<A>, let Y be
-  // remove_reference_t<B>, and let COMMON-​REF(A, B) be:
-  assert(A->isReferenceType() && B->isReferenceType() &&
-         "A and B have to be ref qualified for a COMMON-REF");
-  auto X = A.getNonReferenceType();
-  auto Y = B.getNonReferenceType();
-
-  // If A and B are both lvalue reference types, COMMON-REF(A, B) is
-  // COND-RES(COPYCV(X, Y) &, COPYCV(​Y, X) &) if that type exists and is a
-  // reference type.
-  if (A->isLValueReferenceType() && B->isLValueReferenceType()) {
-    auto CR = CondRes(S, S.BuiltinAddLValueReference(CopyCV(X, Y), Loc),
-                      S.BuiltinAddLValueReference(CopyCV(Y, X), Loc), Loc);
-    if (CR.isNull() || !CR->isReferenceType())
-      return QualType();
-    return CR;
-  }
-
-  // Otherwise, let C be remove_reference_t<COMMON-REF(X&, Y&)>&&. If A and B
-  // are both rvalue reference types, C is well-formed, and
-  // is_convertible_v<A, C> && is_convertible_v<B, C> is true, then
-  // COMMON-REF(A, B) is C.
-  if (A->isRValueReferenceType() && B->isRValueReferenceType()) {
-    auto C = CommonRef(S, S.BuiltinAddLValueReference(X, Loc),
-                       S.BuiltinAddLValueReference(Y, Loc), Loc);
-    if (C.isNull())
-      return QualType();
-
-    C = C.getNonReferenceType();
-
-    if (S.BuiltinIsConvertible(A, C, Loc) && S.BuiltinIsConvertible(B, C, Loc))
-      return S.BuiltinAddRValueReference(C, Loc);
-    return QualType();
-  }
-
-  // Otherwise, if A is an lvalue reference and B is an rvalue reference, then
-  // COMMON-REF(A, B) is COMMON-REF(B, A).
-  if (A->isLValueReferenceType() && B->isRValueReferenceType())
-    std::swap(A, B);
-
-  // Otherwise, let D be COMMON-REF(const X&, Y&). If A is an rvalue reference
-  // and B is an lvalue reference and D is well-formed and
-  // is_convertible_v<A, D> is true, then COMMON-REF(A, B) is D.
-  if (A->isRValueReferenceType() && B->isLValueReferenceType()) {
-    auto X2 = X;
-    X2.addConst();
-    auto D = CommonRef(S, S.BuiltinAddLValueReference(X2, Loc),
-                       S.BuiltinAddLValueReference(Y, Loc), Loc);
-    if (!D.isNull() && S.BuiltinIsConvertible(A, D, Loc))
-      return D;
-    return QualType();
-  }
-
-  // Otherwise, COMMON-REF(A, B) is ill-formed.
-  // This is implemented by returning from the individual branches above.
-
-  llvm_unreachable("The above cases should be exhaustive");
-}
-
-static QualType builtinCommonReferenceImpl(Sema &S,
-                                           ElaboratedTypeKeyword Keyword,
-                                           TemplateName CommonReference,
-                                           TemplateName CommonType,
-                                           SourceLocation TemplateLoc,
-                                           ArrayRef<TemplateArgument> Ts) {
-  switch (Ts.size()) {
-  // If sizeof...(T) is zero, there shall be no member type.
-  case 0:
-    return QualType();
-
-  // Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the
-  // pack T. The member typedef type shall denote the same type as T0.
-  case 1:
-    return Ts[0].getAsType();
-
-  // Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in
-  // the pack T. Then
-  case 2: {
-    auto T1 = Ts[0].getAsType();
-    auto T2 = Ts[1].getAsType();
-
-    // Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is
-    // well-formed, and is_convertible_v<add_pointer_t<T1>, add_pointer_t<R>> 
&&
-    // is_convertible_v<add_pointer_t<T2>, add_pointer_t<R>> is true, then the
-    // member typedef type denotes R.
-    if (T1->isReferenceType() && T2->isReferenceType()) {
-      QualType R = CommonRef(S, T1, T2, TemplateLoc);
-      if (!R.isNull()) {
-        if (S.BuiltinIsConvertible(S.BuiltinAddPointer(T1, TemplateLoc),
-                                   S.BuiltinAddPointer(R, TemplateLoc),
-                                   TemplateLoc) &&
-            S.BuiltinIsConvertible(S.BuiltinAddPointer(T2, TemplateLoc),
-                                   S.BuiltinAddPointer(R, TemplateLoc),
-                                   TemplateLoc)) {
-          return R;
-        }
-      }
-    }
-
-    // Otherwise, if basic_common_reference<remove_cvref_t<T1>,
-    // remove_cvref_t<T2>, ​XREF(​T1), XREF(T2)>​::​type is well-formed,
-    // then the member typedef type denotes that type.
-    {
-      auto getXRef = [&](QualType T) {
-        BuiltinTemplateDecl *Quals[12] = {
-            S.Context.get__clang_internal_xref_Decl(),
-            S.Context.get__clang_internal_xref_constDecl(),
-            S.Context.get__clang_internal_xref_volatileDecl(),
-            S.Context.get__clang_internal_xref_constvolatileDecl(),
-            S.Context.get__clang_internal_xref_lvalueDecl(),
-            S.Context.get__clang_internal_xref_lvalueconstDecl(),
-            S.Context.get__clang_internal_xref_lvaluevolatileDecl(),
-            S.Context.get__clang_internal_xref_lvalueconstvolatileDecl(),
-            S.Context.get__clang_internal_xref_rvalueDecl(),
-            S.Context.get__clang_internal_xref_rvalueconstDecl(),
-            S.Context.get__clang_internal_xref_rvaluevolatileDecl(),
-            S.Context.get__clang_internal_xref_rvalueconstvolatileDecl(),
-        };
-        size_t Index = 0;
-        if (T->isLValueReferenceType()) {
-          T = T.getNonReferenceType();
-          Index += 4;
-        } else if (T->isRValueReferenceType()) {
-          T = T.getNonReferenceType();
-          Index += 8;
-        }
-        if (T.isConstQualified())
-          Index += 1;
-
-        if (T.isVolatileQualified())
-          Index += 2;
-
-        return Quals[Index];
-      };
-
-      auto BCR = InstantiateTemplate(S, Keyword, CommonReference,
-                                     {S.BuiltinRemoveCVRef(T1, TemplateLoc),
-                                      S.BuiltinRemoveCVRef(T2, TemplateLoc),
-                                      TemplateName{getXRef(T1)},
-                                      TemplateName{getXRef(T2)}},
-                                     TemplateLoc);
-      if (!BCR.isNull())
-        return BCR;
-    }
-
-    // Otherwise, if COND-RES(T1, T2) is well-formed, then the member typedef
-    // type denotes that type.
-    if (auto CR = CondRes(S, T1, T2, TemplateLoc); !CR.isNull())
-      return CR;
-
-    // Otherwise, if common_type_t<T1, T2> is well-formed, then the member
-    // typedef type denotes that type.
-    if (auto CT =
-            InstantiateTemplate(S, Keyword, CommonType, {T1, T2}, TemplateLoc);
-        !CT.isNull())
-      return CT;
-
-    // Otherwise, there shall be no member type.
-    return QualType();
-  }
-
-  // Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest,
-  // respectively, denote the first, second, and (pack of) remaining types
-  // comprising T. Let C be the type common_reference_t<T1, T2>. Then:
-  default: {
-    auto T1 = Ts[0];
-    auto T2 = Ts[1];
-    auto Rest = Ts.drop_front(2);
-    auto C = builtinCommonReferenceImpl(S, Keyword, CommonReference, 
CommonType,
-                                        TemplateLoc, {T1, T2});
-    if (C.isNull())
-      return QualType();
-    llvm::SmallVector<TemplateArgument, 4> Args;
-    Args.emplace_back(C);
-    Args.append(Rest.begin(), Rest.end());
-    return builtinCommonReferenceImpl(S, Keyword, CommonReference, CommonType,
-                                      TemplateLoc, Args);
-  }
-  }
-}
-
 static bool isInVkNamespace(const RecordType *RT) {
   DeclContext *DC = RT->getDecl()->getDeclContext();
   if (!DC)
@@ -3746,89 +3507,6 @@ static QualType checkBuiltinTemplateIdType(
     return HasNoTypeMember;
   }
 
-  case BTK__builtin_common_reference: {
-    assert(Converted.size() == 5);
-    if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); }))
-      return QualType();
-
-    TemplateName BasicCommonReference = Converted[0].getAsTemplate();
-    TemplateName CommonType = Converted[1].getAsTemplate();
-    TemplateName HasTypeMember = Converted[2].getAsTemplate();
-    QualType HasNoTypeMember = Converted[3].getAsType();
-    ArrayRef<TemplateArgument> Ts = Converted[4].getPackAsArray();
-    if (auto CR =
-            builtinCommonReferenceImpl(SemaRef, Keyword, BasicCommonReference,
-                                       CommonType, TemplateLoc, Ts);
-        !CR.isNull()) {
-      TemplateArgumentListInfo TAs;
-      TAs.addArgument(TemplateArgumentLoc(
-          TemplateArgument(CR), SemaRef.Context.getTrivialTypeSourceInfo(
-                                    CR, TemplateArgs[1].getLocation())));
-      return SemaRef.CheckTemplateIdType(Keyword, HasTypeMember, TemplateLoc,
-                                         TAs, /*Scope=*/nullptr,
-                                         /*ForNestedNameSpecifier=*/false);
-    }
-    return HasNoTypeMember;
-  }
-
-  case BTK__clang_internal_xref_:
-  case BTK__clang_internal_xref_const:
-  case BTK__clang_internal_xref_volatile:
-  case BTK__clang_internal_xref_constvolatile:
-  case BTK__clang_internal_xref_lvalue:
-  case BTK__clang_internal_xref_lvalueconst:
-  case BTK__clang_internal_xref_lvaluevolatile:
-  case BTK__clang_internal_xref_lvalueconstvolatile:
-  case BTK__clang_internal_xref_rvalue:
-  case BTK__clang_internal_xref_rvalueconst:
-  case BTK__clang_internal_xref_rvaluevolatile:
-  case BTK__clang_internal_xref_rvalueconstvolatile: {
-    if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); }))
-      return QualType();
-
-    auto BTK = BTD->getBuiltinTemplateKind();
-    auto anyOf = [&](auto... Vals) { return ((BTK == Vals) || ...); };
-
-    bool AddCV = anyOf(BTK__clang_internal_xref_constvolatile,
-                       BTK__clang_internal_xref_lvalueconstvolatile,
-                       BTK__clang_internal_xref_rvalueconstvolatile);
-
-    bool AddConst = AddCV || anyOf(BTK__clang_internal_xref_const,
-                                   BTK__clang_internal_xref_lvalueconst,
-                                   BTK__clang_internal_xref_rvalueconst);
-
-    bool AddVolatile = AddCV || anyOf(BTK__clang_internal_xref_volatile,
-                                      BTK__clang_internal_xref_lvaluevolatile,
-                                      BTK__clang_internal_xref_rvaluevolatile);
-
-    bool AddLValue = anyOf(BTK__clang_internal_xref_lvalue,
-                           BTK__clang_internal_xref_lvalueconst,
-                           BTK__clang_internal_xref_lvaluevolatile,
-                           BTK__clang_internal_xref_lvalueconstvolatile);
-
-    bool AddRValue = anyOf(BTK__clang_internal_xref_rvalue,
-                           BTK__clang_internal_xref_rvalueconst,
-                           BTK__clang_internal_xref_rvaluevolatile,
-                           BTK__clang_internal_xref_rvalueconstvolatile);
-
-    assert(Converted.size() == 1);
-
-    QualType T = Converted[0].getAsType();
-
-    if (AddConst)
-      T.addConst();
-
-    if (AddVolatile)
-      T.addVolatile();
-
-    if (AddLValue)
-      T = SemaRef.BuiltinAddLValueReference(T, TemplateLoc);
-    else if (AddRValue)
-      T = SemaRef.BuiltinAddRValueReference(T, TemplateLoc);
-
-    return T;
-  }
-
   case BTK__hlsl_spirv_type: {
     assert(Converted.size() == 4);
 

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 9488a853ffab1..9f5aa153d1cbe 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -32,8 +32,6 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/DelayedDiagnostic.h"
-#include "clang/Sema/EnterExpressionEvaluationContext.h"
-#include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/ParsedTemplate.h"
@@ -10074,81 +10072,6 @@ QualType Sema::BuiltinChangeSignedness(QualType 
BaseType, UTTKind UKind,
   return Context.getQualifiedType(Underlying, BaseType.getQualifiers());
 }
 
-bool Sema::BuiltinIsConvertible(QualType From, QualType To, SourceLocation Loc,
-                                bool CheckNothrow) {
-  if (To->isVoidType())
-    return From->isVoidType();
-
-  // [meta.rel]
-  // From and To shall be complete types, cv void, or arrays of unknown bound.
-  if ((!From->isIncompleteArrayType() && !From->isVoidType() &&
-       RequireCompleteType(
-           Loc, From, diag::err_incomplete_type_used_in_type_trait_expr)) ||
-      (!To->isIncompleteArrayType() && !To->isVoidType() &&
-       RequireCompleteType(Loc, To,
-                           diag::err_incomplete_type_used_in_type_trait_expr)))
-    return false;
-
-  // C++11 [meta.rel]p4:
-  //   Given the following function prototype:
-  //
-  //     template <class T>
-  //       typename add_rvalue_reference<T>::type create();
-  //
-  //   the predicate condition for a template specialization
-  //   is_convertible<From, To> shall be satisfied if and only if
-  //   the return expression in the following code would be
-  //   well-formed, including any implicit conversions to the return
-  //   type of the function:
-  //
-  //     To test() {
-  //       return create<From>();
-  //     }
-  //
-  //   Access checking is performed as if in a context unrelated to To and
-  //   From. Only the validity of the immediate context of the expression
-  //   of the return-statement (including conversions to the return type)
-  //   is considered.
-  //
-  // We model the initialization as a copy-initialization of a temporary
-  // of the appropriate type, which for this expression is identical to the
-  // return statement (since NRVO doesn't apply).
-
-  // Functions aren't allowed to return function or array types.
-  if (To->isFunctionType() || To->isArrayType())
-    return false;
-
-  // A function definition requires a non-abstract return type.
-  if (isAbstractType(Loc, To))
-    return false;
-
-  From = BuiltinAddRValueReference(From, Loc);
-
-  // Build a fake source and destination for initialization.
-  InitializedEntity ToEntity(InitializedEntity::InitializeTemporary(To));
-  OpaqueValueExpr FromExpr(Loc, From.getNonLValueExprType(Context),
-                           Expr::getValueKindForType(From));
-  InitializationKind Kind =
-      InitializationKind::CreateCopy(Loc, SourceLocation());
-
-  // Perform the initialization in an unevaluated context within a SFINAE
-  // trap at translation unit scope.
-  EnterExpressionEvaluationContext Unevaluated(
-      *this, Sema::ExpressionEvaluationContext::Unevaluated);
-  Sema::SFINAETrap SFINAE(*this, /*AccessCheckingSFINAE=*/true);
-  Sema::ContextRAII TUContext(*this, Context.getTranslationUnitDecl());
-  Expr *FromExprPtr = &FromExpr;
-  InitializationSequence Init(*this, ToEntity, Kind, FromExprPtr);
-  if (Init.Failed())
-    return false;
-
-  ExprResult Result = Init.Perform(*this, ToEntity, Kind, FromExprPtr);
-  if (Result.isInvalid() || SFINAE.hasErrorOccurred())
-    return false;
-
-  return !CheckNothrow || canThrow(Result.get()) == CT_Cannot;
-}
-
 QualType Sema::BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
                                        SourceLocation Loc) {
   if (BaseType->isDependentType())

diff  --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index 3802da8bc2d45..38877967af05e 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -1212,6 +1212,76 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, 
TypeTrait BTT,
                                     const TypeSourceInfo *Rhs,
                                     SourceLocation KeyLoc);
 
+static ExprResult CheckConvertibilityForTypeTraits(
+    Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs,
+    SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) {
+
+  QualType LhsT = Lhs->getType();
+  QualType RhsT = Rhs->getType();
+
+  // C++0x [meta.rel]p4:
+  //   Given the following function prototype:
+  //
+  //     template <class T>
+  //       typename add_rvalue_reference<T>::type create();
+  //
+  //   the predicate condition for a template specialization
+  //   is_convertible<From, To> shall be satisfied if and only if
+  //   the return expression in the following code would be
+  //   well-formed, including any implicit conversions to the return
+  //   type of the function:
+  //
+  //     To test() {
+  //       return create<From>();
+  //     }
+  //
+  //   Access checking is performed as if in a context unrelated to To and
+  //   From. Only the validity of the immediate context of the expression
+  //   of the return-statement (including conversions to the return type)
+  //   is considered.
+  //
+  // We model the initialization as a copy-initialization of a temporary
+  // of the appropriate type, which for this expression is identical to the
+  // return statement (since NRVO doesn't apply).
+
+  // Functions aren't allowed to return function or array types.
+  if (RhsT->isFunctionType() || RhsT->isArrayType())
+    return ExprError();
+
+  // A function definition requires a complete, non-abstract return type.
+  if (!Self.isCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT) ||
+      Self.isAbstractType(Rhs->getTypeLoc().getBeginLoc(), RhsT))
+    return ExprError();
+
+  // Compute the result of add_rvalue_reference.
+  if (LhsT->isObjectType() || LhsT->isFunctionType())
+    LhsT = Self.Context.getRValueReferenceType(LhsT);
+
+  // Build a fake source and destination for initialization.
+  InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
+  Expr *From = new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())
+      OpaqueValueExpr(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
+                      Expr::getValueKindForType(LhsT));
+  InitializationKind Kind =
+      InitializationKind::CreateCopy(KeyLoc, SourceLocation());
+
+  // Perform the initialization in an unevaluated context within a SFINAE
+  // trap at translation unit scope.
+  EnterExpressionEvaluationContext Unevaluated(
+      Self, Sema::ExpressionEvaluationContext::Unevaluated);
+  Sema::SFINAETrap SFINAE(Self, /*ForValidityCheck=*/true);
+  Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
+  InitializationSequence Init(Self, To, Kind, From);
+  if (Init.Failed())
+    return ExprError();
+
+  ExprResult Result = Init.Perform(Self, To, Kind, From);
+  if (Result.isInvalid() || SFINAE.hasErrorOccurred())
+    return ExprError();
+
+  return Result;
+}
+
 static APValue EvaluateSizeTTypeTrait(Sema &S, TypeTrait Kind,
                                       SourceLocation KWLoc,
                                       ArrayRef<TypeSourceInfo *> Args,
@@ -1372,8 +1442,9 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait 
Kind,
           S.Context.getPointerType(T.getNonReferenceType()));
       TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo(
           S.Context.getPointerType(U.getNonReferenceType()));
-      return S.BuiltinIsConvertible(UPtr->getType(), TPtr->getType(),
-                                    RParenLoc);
+      return !CheckConvertibilityForTypeTraits(S, UPtr, TPtr, RParenLoc,
+                                               OpaqueExprAllocator)
+                  .isInvalid();
     }
 
     if (Kind == clang::TT_IsNothrowConstructible)
@@ -1624,9 +1695,20 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, 
TypeTrait BTT,
   }
   case BTT_IsConvertible:
   case BTT_IsConvertibleTo:
-  case BTT_IsNothrowConvertible:
-    return Self.BuiltinIsConvertible(LhsT, RhsT, KeyLoc,
-                                     BTT == BTT_IsNothrowConvertible);
+  case BTT_IsNothrowConvertible: {
+    if (RhsT->isVoidType())
+      return LhsT->isVoidType();
+    llvm::BumpPtrAllocator OpaqueExprAllocator;
+    ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, 
KeyLoc,
+                                                         OpaqueExprAllocator);
+    if (Result.isInvalid())
+      return false;
+
+    if (BTT != BTT_IsNothrowConvertible)
+      return true;
+
+    return Self.canThrow(Result.get()) == CT_Cannot;
+  }
 
   case BTT_IsAssignable:
   case BTT_IsNothrowAssignable:

diff  --git a/clang/test/SemaCXX/type-trait-common-reference.cpp 
b/clang/test/SemaCXX/type-trait-common-reference.cpp
deleted file mode 100644
index cc4fefc49886d..0000000000000
--- a/clang/test/SemaCXX/type-trait-common-reference.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify 
-std=c++17 -Wno-vla-cxx-extension %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify 
-std=c++20 -Wno-vla-cxx-extension %s
-
-#if !__has_builtin(__builtin_common_reference)
-#  error
-#endif
-
-// expected-note@*:* {{template <template <class, class, template <class> 
class, template <class> class> class, template <class ...> class, template 
<class> class, class, class ...>}}
-
-void test() {
-  __builtin_common_reference<> a; // expected-error {{too few template 
arguments for template '__builtin_common_reference'}}
-  __builtin_common_reference<1> b; // expected-error {{template argument for 
template template parameter must be a class template or type alias template}}
-  __builtin_common_reference<int, 1> c; // expected-error {{template argument 
for template template parameter must be a class template or type alias 
template}}
-}
-
-struct empty_type {};
-
-template <class T>
-struct type_identity {
-  using type = T;
-};
-
-template <class...>
-struct common_type;
-
-template <class... Args>
-using common_type_t = typename common_type<Args...>::type;
-
-template <class, class, template <class> class, template <class> class>
-struct basic_common_reference {};
-
-template <class T, class U, template <class> class TX, template <class> class 
UX>
-using basic_common_reference_t = typename basic_common_reference<T, U, TX, 
UX>::type;
-
-void test_vla() {
-  int i = 4;
-  int VLA[i];
-  __builtin_common_reference<basic_common_reference_t, common_type_t, 
type_identity, empty_type, decltype(VLA)> d; // expected-error {{variably 
modified type 'decltype(VLA)' (aka 'int[i]') cannot be used as a template 
argument}}
-}
-
-template <class... Args>
-using common_reference_base = 
__builtin_common_reference<basic_common_reference_t, common_type_t, 
type_identity, empty_type, Args...>;
-
-template <class... Args>
-struct common_reference : common_reference_base<Args...> {};
-
-template <class... Args>
-using common_reference_t = typename 
__builtin_common_reference<basic_common_reference_t, common_type_t, 
type_identity, empty_type, Args...>::type;
-
-struct Incomplete;
-
-template<>
-struct common_type<Incomplete, Incomplete>;
-
-static_assert(__is_same(common_reference_base<>, empty_type));
-
-static_assert(__is_same(common_reference_base<Incomplete>, 
type_identity<Incomplete>));
-static_assert(__is_same(common_reference_base<char>, type_identity<char>));
-static_assert(__is_same(common_reference_base<int>, type_identity<int>));
-static_assert(__is_same(common_reference_base<const int>, type_identity<const 
int>));
-static_assert(__is_same(common_reference_base<volatile int>, 
type_identity<volatile int>));
-static_assert(__is_same(common_reference_base<const volatile int>, 
type_identity<const volatile int>));
-static_assert(__is_same(common_reference_base<int[]>, type_identity<int[]>));
-static_assert(__is_same(common_reference_base<const int[]>, 
type_identity<const int[]>));
-static_assert(__is_same(common_reference_base<void(&)()>, 
type_identity<void(&)()>));
-
-static_assert(__is_same(common_reference_base<int[], int[]>, 
type_identity<int*>));
-static_assert(__is_same(common_reference_base<int, int>, type_identity<int>));
-static_assert(__is_same(common_reference_base<int, long>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<long, int>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<long, long>, 
type_identity<long>));
-
-static_assert(__is_same(common_reference_base<const int, long>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<const volatile int, long>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<int, const long>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<int, const volatile long>, 
type_identity<long>));
-
-static_assert(__is_same(common_reference_base<int*, long*>, empty_type));
-static_assert(__is_same(common_reference_base<const unsigned int *const &, 
const unsigned int *const &>, type_identity<const unsigned int *const &>));
-
-static_assert(__is_same(common_reference_base<int, long, float>, 
type_identity<float>));
-static_assert(__is_same(common_reference_base<unsigned, char, long>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<long long, long long, long>, 
type_identity<long long>));
-
-static_assert(__is_same(common_reference_base<int 
[[clang::address_space(1)]]>, type_identity<int [[clang::address_space(1)]]>));
-static_assert(__is_same(common_reference_base<int [[clang::address_space(1)]], 
int>, type_identity<int>));
-static_assert(__is_same(common_reference_base<long 
[[clang::address_space(1)]], int>, type_identity<long>));
-static_assert(__is_same(common_reference_base<long 
[[clang::address_space(1)]], int [[clang::address_space(1)]]>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<long 
[[clang::address_space(1)]], long [[clang::address_space(1)]]>, 
type_identity<long>));
-static_assert(__is_same(common_reference_base<long 
[[clang::address_space(1)]], long [[clang::address_space(2)]]>, 
type_identity<long>));
-
-struct S {};
-struct T : S {};
-struct U {};
-
-static_assert(__is_same(common_reference_base<S&&, T&&>, type_identity<S&&>));
-
-static_assert(__is_same(common_reference_base<int S::*, int S::*>, 
type_identity<int S::*>));
-static_assert(__is_same(common_reference_base<int S::*, int T::*>, 
type_identity<int T::*>));
-static_assert(__is_same(common_reference_base<int S::*, long S::*>, 
empty_type));
-
-static_assert(__is_same(common_reference_base<int (S::*)(), int (S::*)()>, 
type_identity<int (S::*)()>));
-static_assert(__is_same(common_reference_base<int (S::*)(), int (T::*)()>, 
type_identity<int (T::*)()>));
-static_assert(__is_same(common_reference_base<int (S::*)(), long (S::*)()>, 
empty_type));
-
-static_assert(__is_same(common_reference_base<int&, int&>, 
type_identity<int&>));
-static_assert(__is_same(common_reference_base<int&, const int&>, 
type_identity<const int&>));
-static_assert(__is_same(common_reference_base<volatile int&, const int&>, 
type_identity<const volatile int&>));
-
-template <class T, class U>
-struct my_pair;
-
-template <class T1, class U1, class T2, class U2, template <class> class TX, 
template <class> class UX>
-struct basic_common_reference<my_pair<T1, U1>, my_pair<T2, U2>, TX, UX> {
-  using type = my_pair<common_reference_t<TX<T1>, UX<T2>>, 
common_reference_t<TX<U1>, UX<U2>>>;
-};
-
-static_assert(__is_same(common_reference_base<my_pair<const int&, int&>, 
my_pair<int&, volatile int&>>, type_identity<my_pair<const int&, volatile 
int&>>));
-static_assert(__is_same(common_reference_base<const my_pair<int, int>&, 
my_pair<int&, volatile int&>>, type_identity<my_pair<const int&, const volatile 
int&>>));
-static_assert(__is_same(common_reference_base<const int&, const volatile 
int&>, type_identity<const volatile int&>));
-static_assert(__is_same(common_reference_base<int&&, const volatile int&>, 
type_identity<int>));
-static_assert(__is_same(common_reference_base<my_pair<int, int>&&, 
my_pair<int&, volatile int&>>, type_identity<my_pair<const int&, int>>));
-static_assert(__is_same(common_reference_base<my_pair<int, int>&&, 
my_pair<int&, int>&&>, type_identity<my_pair<const int&, int&&>>));
-
-struct conversion_operator {
-  operator volatile int&&() volatile;
-};
-
-static_assert(__is_same(common_reference_base<volatile conversion_operator&&, 
volatile int&&>, type_identity<volatile int&&>));
-
-struct reference_wrapper {
-  reference_wrapper(int&);
-  operator int&() const;
-};
-
-static_assert(__is_same(common_reference_base<const reference_wrapper&, int&>, 
empty_type));

diff  --git a/libcxx/include/__type_traits/common_reference.h 
b/libcxx/include/__type_traits/common_reference.h
index 297b6adbe1ca0..59badb64267de 100644
--- a/libcxx/include/__type_traits/common_reference.h
+++ b/libcxx/include/__type_traits/common_reference.h
@@ -18,37 +18,16 @@
 #include <__type_traits/is_reference.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/remove_reference.h>
-#include <__type_traits/type_identity.h>
 #include <__utility/declval.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
 
-#if _LIBCPP_STD_VER >= 20
-
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class...>
-struct _LIBCPP_NO_SPECIALIZATIONS common_reference;
-
-template <class... _Types>
-using common_reference_t = typename common_reference<_Types...>::type;
-
-template <class, class, template <class> class, template <class> class>
-struct basic_common_reference {};
-
-#  if __has_builtin(__builtin_common_reference)
-
-template <class _Tp, class _Up, template <class> class _Tx, template <class> 
class _Ux>
-using __basic_common_reference_t = basic_common_reference<_Tp, _Up, _Tx, 
_Ux>::type;
-
-template <class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS common_reference
-    : __builtin_common_reference<__basic_common_reference_t, common_type_t, 
type_identity, __empty, _Args...> {};
-
-#  else
-
+// common_reference
+#if _LIBCPP_STD_VER >= 20
 // Let COND_RES(X, Y) be:
 template <class _Xp, class _Yp>
 using __cond_res _LIBCPP_NODEBUG = decltype(false ? std::declval<_Xp 
(&)()>()() : std::declval<_Yp (&)()>()());
@@ -130,10 +109,19 @@ struct __common_ref {};
 
 // Note C: For the common_reference trait applied to a parameter pack [...]
 
+template <class...>
+struct _LIBCPP_NO_SPECIALIZATIONS common_reference;
+
+template <class... _Types>
+using common_reference_t = typename common_reference<_Types...>::type;
+
+template <class, class, template <class> class, template <class> class>
+struct basic_common_reference {};
+
 _LIBCPP_DIAGNOSTIC_PUSH
-#    if __has_warning("-Winvalid-specialization")
+#  if __has_warning("-Winvalid-specialization")
 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-specialization")
-#    endif
+#  endif
 // bullet 1 - sizeof...(T) == 0
 template <>
 struct common_reference<> {};
@@ -207,10 +195,8 @@ _LIBCPP_DIAGNOSTIC_POP
 template <class...>
 struct _LIBCPP_NO_SPECIALIZATIONS common_reference {};
 
-#  endif // __has_builtin(__builtin_common_reference)
+#endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
 
-#endif // _LIBCPP_STD_VER >= 20
-
 #endif // _LIBCPP___TYPE_TRAITS_COMMON_REFERENCE_H

diff  --git a/libcxx/include/module.modulemap.in 
b/libcxx/include/module.modulemap.in
index 5d2a92bf7905c..0ac5a1ade817f 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1517,7 +1517,6 @@ module std [system] {
       header "__iterator/iterator_traits.h"
       export std_core.type_traits.integral_constant
       export std_core.type_traits.is_convertible
-      export std_core.type_traits.nat
     }
     module iterator_with_data         { header 
"__iterator/iterator_with_data.h" }
     module iterator                   { header "__iterator/iterator.h" }


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to