Skip to content

Commit 55f9d1e

Browse files
committed
[Clang] Add __builtin_common_reference
1 parent 5ce4045 commit 55f9d1e

File tree

8 files changed

+629
-118
lines changed

8 files changed

+629
-118
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,23 @@ Builtin type aliases
16571657

16581658
Clang provides a few builtin aliases to improve the throughput of certain metaprogramming facilities.
16591659

1660+
__builtin_common_reference
1661+
--------------------------
1662+
1663+
.. code-block:: c++
1664+
1665+
template <template <class, class, template <class> class, template <class> class> class BasicCommonReferenceT,
1666+
template <class... Args> CommonTypeT,
1667+
template <class> HasTypeMember,
1668+
class HasNoTypeMember,
1669+
class... Ts>
1670+
using __builtin_common_reference = ...;
1671+
1672+
This alias is used for implementing ``std::common_refernce``. If ``std::common_reference`` should contain a ``type``
1673+
member, it is an alias to ``HasTypeMember<TheCommonReference>``. Otherwse it is an alias to ``HasNoTypeMember``. The
1674+
``CommonTypeT`` is usually ``std::common_type_t``. ``BasicCommonReferenceT`` is usually an alias template to
1675+
``basic_common_reference<T, U, TX, UX>::type``.
1676+
16601677
__builtin_common_type
16611678
---------------------
16621679

clang/include/clang/Basic/BuiltinTemplates.td

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ class TemplateArg<string name> {
1010
string Name = name;
1111
}
1212

13-
class Template<list<TemplateArg> args, string name> : TemplateArg<name> {
13+
class Template<list<TemplateArg> args, string name = ""> : TemplateArg<name> {
1414
list<TemplateArg> Args = args;
1515
}
1616

17-
class Class<string name, bit is_variadic = 0> : TemplateArg<name> {
17+
class Class<string name = "", bit is_variadic = 0> : TemplateArg<name> {
1818
bit IsVariadic = is_variadic;
1919
}
2020

@@ -50,3 +50,29 @@ def __builtin_common_type : BuiltinTemplate<
5050
Template<[Class<"TypeMember">], "HasTypeMember">,
5151
Class<"HasNoTypeMember">,
5252
Class<"Ts", /*is_variadic=*/1>]>;
53+
54+
// template <template <class,"
55+
// class,"
56+
// template <class> class,"
57+
// template <class> class> class BasicCommonReferenceT,"
58+
// template <class... Args> class CommonTypeT,"
59+
// template <class> class HasTypeMember,"
60+
// class HasNoTypeMember,"
61+
// class... Ts>"
62+
def __builtin_common_reference : BuiltinTemplate<
63+
[Template<[Class<>,
64+
Class<>,
65+
Template<[Class<>]>,
66+
Template<[Class<>]>], "BasicCommonReferenceT">,
67+
Template<[Class<"Args", /*is_variadic=*/1>], "CommonTypeT">,
68+
Template<[Class<>], "HasTypeMember">,
69+
Class<"HasNoTypeMember">,
70+
Class<"Ts", /*is_variadic=*/1>]>;
71+
72+
foreach Ref = ["", "lvalue", "rvalue"] in {
73+
foreach Const = ["", "const"] in {
74+
foreach Volatile = ["", "volatile"] in {
75+
def __clang_internal_xref_#Ref#Const#Volatile : BuiltinTemplate<[Class<>]>;
76+
}
77+
}
78+
}

clang/include/clang/Sema/Sema.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15026,15 +15026,34 @@ class Sema final : public SemaBase {
1502615026
QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
1502715027
QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
1502815028
SourceLocation Loc);
15029+
15030+
QualType BuiltinAddRValueReference(QualType BaseType, SourceLocation Loc) {
15031+
return BuiltinAddReference(BaseType, UnaryTransformType::AddRvalueReference,
15032+
Loc);
15033+
}
15034+
15035+
QualType BuiltinAddLValueReference(QualType BaseType, SourceLocation Loc) {
15036+
return BuiltinAddReference(BaseType, UnaryTransformType::AddLvalueReference,
15037+
Loc);
15038+
}
15039+
1502915040
QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
1503015041
SourceLocation Loc);
1503115042
QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
1503215043
SourceLocation Loc);
15044+
15045+
QualType BuiltinRemoveCVRef(QualType BaseType, SourceLocation Loc) {
15046+
return BuiltinRemoveReference(BaseType, UTTKind::RemoveCVRef, Loc);
15047+
}
15048+
1503315049
QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
1503415050
SourceLocation Loc);
1503515051
QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
1503615052
SourceLocation Loc);
1503715053

15054+
bool BuiltinIsConvertible(QualType From, QualType To, SourceLocation Loc,
15055+
bool CheckNothrow = false);
15056+
1503815057
/// Ensure that the type T is a literal type.
1503915058
///
1504015059
/// This routine checks whether the type @p T is a literal type. If @p T is an

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 5 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5743,76 +5743,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
57435743
static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs,
57445744
const TypeSourceInfo *Rhs, SourceLocation KeyLoc);
57455745

5746-
static ExprResult CheckConvertibilityForTypeTraits(
5747-
Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs,
5748-
SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) {
5749-
5750-
QualType LhsT = Lhs->getType();
5751-
QualType RhsT = Rhs->getType();
5752-
5753-
// C++0x [meta.rel]p4:
5754-
// Given the following function prototype:
5755-
//
5756-
// template <class T>
5757-
// typename add_rvalue_reference<T>::type create();
5758-
//
5759-
// the predicate condition for a template specialization
5760-
// is_convertible<From, To> shall be satisfied if and only if
5761-
// the return expression in the following code would be
5762-
// well-formed, including any implicit conversions to the return
5763-
// type of the function:
5764-
//
5765-
// To test() {
5766-
// return create<From>();
5767-
// }
5768-
//
5769-
// Access checking is performed as if in a context unrelated to To and
5770-
// From. Only the validity of the immediate context of the expression
5771-
// of the return-statement (including conversions to the return type)
5772-
// is considered.
5773-
//
5774-
// We model the initialization as a copy-initialization of a temporary
5775-
// of the appropriate type, which for this expression is identical to the
5776-
// return statement (since NRVO doesn't apply).
5777-
5778-
// Functions aren't allowed to return function or array types.
5779-
if (RhsT->isFunctionType() || RhsT->isArrayType())
5780-
return ExprError();
5781-
5782-
// A function definition requires a complete, non-abstract return type.
5783-
if (!Self.isCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT) ||
5784-
Self.isAbstractType(Rhs->getTypeLoc().getBeginLoc(), RhsT))
5785-
return ExprError();
5786-
5787-
// Compute the result of add_rvalue_reference.
5788-
if (LhsT->isObjectType() || LhsT->isFunctionType())
5789-
LhsT = Self.Context.getRValueReferenceType(LhsT);
5790-
5791-
// Build a fake source and destination for initialization.
5792-
InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
5793-
Expr *From = new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())
5794-
OpaqueValueExpr(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
5795-
Expr::getValueKindForType(LhsT));
5796-
InitializationKind Kind =
5797-
InitializationKind::CreateCopy(KeyLoc, SourceLocation());
5798-
5799-
// Perform the initialization in an unevaluated context within a SFINAE
5800-
// trap at translation unit scope.
5801-
EnterExpressionEvaluationContext Unevaluated(
5802-
Self, Sema::ExpressionEvaluationContext::Unevaluated);
5803-
Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
5804-
Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
5805-
InitializationSequence Init(Self, To, Kind, From);
5806-
if (Init.Failed())
5807-
return ExprError();
5808-
5809-
ExprResult Result = Init.Perform(Self, To, Kind, From);
5810-
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
5811-
return ExprError();
5812-
5813-
return Result;
5814-
}
5815-
58165746
static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
58175747
SourceLocation KWLoc,
58185748
ArrayRef<TypeSourceInfo *> Args,
@@ -5934,9 +5864,8 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
59345864
S.Context.getPointerType(T.getNonReferenceType()));
59355865
TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo(
59365866
S.Context.getPointerType(U.getNonReferenceType()));
5937-
return !CheckConvertibilityForTypeTraits(S, UPtr, TPtr, RParenLoc,
5938-
OpaqueExprAllocator)
5939-
.isInvalid();
5867+
return S.BuiltinIsConvertible(UPtr->getType(), TPtr->getType(),
5868+
RParenLoc);
59405869
}
59415870

59425871
if (Kind == clang::TT_IsNothrowConstructible)
@@ -6167,20 +6096,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
61676096
}
61686097
case BTT_IsConvertible:
61696098
case BTT_IsConvertibleTo:
6170-
case BTT_IsNothrowConvertible: {
6171-
if (RhsT->isVoidType())
6172-
return LhsT->isVoidType();
6173-
llvm::BumpPtrAllocator OpaqueExprAllocator;
6174-
ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, KeyLoc,
6175-
OpaqueExprAllocator);
6176-
if (Result.isInvalid())
6177-
return false;
6178-
6179-
if (BTT != BTT_IsNothrowConvertible)
6180-
return true;
6181-
6182-
return Self.canThrow(Result.get()) == CT_Cannot;
6183-
}
6099+
case BTT_IsNothrowConvertible:
6100+
return Self.BuiltinIsConvertible(LhsT, RhsT, KeyLoc,
6101+
BTT == BTT_IsNothrowConvertible);
61846102

61856103
case BTT_IsAssignable:
61866104
case BTT_IsNothrowAssignable:

0 commit comments

Comments
 (0)