Skip to content

Commit 3010ba7

Browse files
committed
[Clang] Add __builtin_common_reference
1 parent fa5025b commit 3010ba7

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
@@ -1677,6 +1677,23 @@ Builtin type aliases
16771677

16781678
Clang provides a few builtin aliases to improve the throughput of certain metaprogramming facilities.
16791679

1680+
__builtin_common_reference
1681+
--------------------------
1682+
1683+
.. code-block:: c++
1684+
1685+
template <template <class, class, template <class> class, template <class> class> class BasicCommonReferenceT,
1686+
template <class... Args> CommonTypeT,
1687+
template <class> HasTypeMember,
1688+
class HasNoTypeMember,
1689+
class... Ts>
1690+
using __builtin_common_reference = ...;
1691+
1692+
This alias is used for implementing ``std::common_refernce``. If ``std::common_reference`` should contain a ``type``
1693+
member, it is an alias to ``HasTypeMember<TheCommonReference>``. Otherwse it is an alias to ``HasNoTypeMember``. The
1694+
``CommonTypeT`` is usually ``std::common_type_t``. ``BasicCommonReferenceT`` is usually an alias template to
1695+
``basic_common_reference<T, U, TX, UX>::type``.
1696+
16801697
__builtin_common_type
16811698
---------------------
16821699

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
@@ -15076,15 +15076,34 @@ class Sema final : public SemaBase {
1507615076
QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
1507715077
QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
1507815078
SourceLocation Loc);
15079+
15080+
QualType BuiltinAddRValueReference(QualType BaseType, SourceLocation Loc) {
15081+
return BuiltinAddReference(BaseType, UnaryTransformType::AddRvalueReference,
15082+
Loc);
15083+
}
15084+
15085+
QualType BuiltinAddLValueReference(QualType BaseType, SourceLocation Loc) {
15086+
return BuiltinAddReference(BaseType, UnaryTransformType::AddLvalueReference,
15087+
Loc);
15088+
}
15089+
1507915090
QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
1508015091
SourceLocation Loc);
1508115092
QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
1508215093
SourceLocation Loc);
15094+
15095+
QualType BuiltinRemoveCVRef(QualType BaseType, SourceLocation Loc) {
15096+
return BuiltinRemoveReference(BaseType, UTTKind::RemoveCVRef, Loc);
15097+
}
15098+
1508315099
QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
1508415100
SourceLocation Loc);
1508515101
QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
1508615102
SourceLocation Loc);
1508715103

15104+
bool BuiltinIsConvertible(QualType From, QualType To, SourceLocation Loc,
15105+
bool CheckNothrow = false);
15106+
1508815107
/// Ensure that the type T is a literal type.
1508915108
///
1509015109
/// 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
@@ -5739,76 +5739,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
57395739
static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs,
57405740
const TypeSourceInfo *Rhs, SourceLocation KeyLoc);
57415741

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

59665895
if (Kind == clang::TT_IsNothrowConstructible)
@@ -6200,20 +6129,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
62006129
}
62016130
case BTT_IsConvertible:
62026131
case BTT_IsConvertibleTo:
6203-
case BTT_IsNothrowConvertible: {
6204-
if (RhsT->isVoidType())
6205-
return LhsT->isVoidType();
6206-
llvm::BumpPtrAllocator OpaqueExprAllocator;
6207-
ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, KeyLoc,
6208-
OpaqueExprAllocator);
6209-
if (Result.isInvalid())
6210-
return false;
6211-
6212-
if (BTT != BTT_IsNothrowConvertible)
6213-
return true;
6214-
6215-
return Self.canThrow(Result.get()) == CT_Cannot;
6216-
}
6132+
case BTT_IsNothrowConvertible:
6133+
return Self.BuiltinIsConvertible(LhsT, RhsT, KeyLoc,
6134+
BTT == BTT_IsNothrowConvertible);
62176135

62186136
case BTT_IsAssignable:
62196137
case BTT_IsNothrowAssignable:

0 commit comments

Comments
 (0)