Skip to content

Commit f5be5cd

Browse files
authored
[Clang] Add __builtin_common_type (#99473)
This implements the logic of the `common_type` base template as a builtin alias. If there should be no `type` member, an empty class is returned. Otherwise a specialization of a `type_identity`-like class is returned. The base template (i.e. `std::common_type`) as well as the empty class and `type_identity`-like struct are given as arguments to the builtin.
1 parent 15e6b5d commit f5be5cd

16 files changed

+531
-6
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,46 @@ Attributes (N2335) C2
15161516
``#embed`` (N3017) C23 C89, C++
15171517
============================================ ================================ ============= =============
15181518

1519+
Builtin type aliases
1520+
====================
1521+
1522+
Clang provides a few builtin aliases to improve the throughput of certain metaprogramming facilities.
1523+
1524+
__builtin_common_type
1525+
---------------------
1526+
1527+
.. code-block:: c++
1528+
1529+
template <template <class... Args> class BaseTemplate,
1530+
template <class TypeMember> class HasTypeMember,
1531+
class HasNoTypeMember,
1532+
class... Ts>
1533+
using __builtin_common_type = ...;
1534+
1535+
This alias is used for implementing ``std::common_type``. If ``std::common_type`` should contain a ``type`` member,
1536+
it is an alias to ``HasTypeMember<TheCommonType>``. Otherwise it is an alias to ``HasNoTypeMember``. The
1537+
``BaseTemplate`` is usually ``std::common_type``. ``Ts`` are the arguments to ``std::common_type``.
1538+
1539+
__type_pack_element
1540+
-------------------
1541+
1542+
.. code-block:: c++
1543+
1544+
template <std::size_t Index, class... Ts>
1545+
using __type_pack_element = ...;
1546+
1547+
This alias returns the type at ``Index`` in the parameter pack ``Ts``.
1548+
1549+
__make_integer_seq
1550+
------------------
1551+
1552+
.. code-block:: c++
1553+
1554+
template <template <class IntSeqT, IntSeqT... Ints> class IntSeq, class T, T N>
1555+
using __make_integer_seq = ...;
1556+
1557+
This alias returns ``IntSeq`` instantiated with ``IntSeqT = T``and ``Ints`` being the pack ``0, ..., N - 1``.
1558+
15191559
Type Trait Primitives
15201560
=====================
15211561

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ C++ Language Changes
123123

124124
- Add ``__builtin_elementwise_popcount`` builtin for integer types only.
125125

126+
- The builtin type alias ``__builtin_common_type`` has been added to improve the
127+
performance of ``std::common_type``.
128+
126129
C++2c Feature Support
127130
^^^^^^^^^^^^^^^^^^^^^
128131

clang/include/clang/AST/ASTContext.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
403403
/// The identifier '__type_pack_element'.
404404
mutable IdentifierInfo *TypePackElementName = nullptr;
405405

406+
/// The identifier '__builtin_common_type'.
407+
mutable IdentifierInfo *BuiltinCommonTypeName = nullptr;
408+
406409
QualType ObjCConstantStringType;
407410
mutable RecordDecl *CFConstantStringTagDecl = nullptr;
408411
mutable TypedefDecl *CFConstantStringTypeDecl = nullptr;
@@ -610,6 +613,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
610613
mutable ExternCContextDecl *ExternCContext = nullptr;
611614
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
612615
mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
616+
mutable BuiltinTemplateDecl *BuiltinCommonTypeDecl = nullptr;
613617

614618
/// The associated SourceManager object.
615619
SourceManager &SourceMgr;
@@ -1134,6 +1138,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
11341138
ExternCContextDecl *getExternCContextDecl() const;
11351139
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
11361140
BuiltinTemplateDecl *getTypePackElementDecl() const;
1141+
BuiltinTemplateDecl *getBuiltinCommonTypeDecl() const;
11371142

11381143
// Builtin Types.
11391144
CanQualType VoidTy;
@@ -2025,6 +2030,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
20252030
return TypePackElementName;
20262031
}
20272032

2033+
IdentifierInfo *getBuiltinCommonTypeName() const {
2034+
if (!BuiltinCommonTypeName)
2035+
BuiltinCommonTypeName = &Idents.get("__builtin_common_type");
2036+
return BuiltinCommonTypeName;
2037+
}
2038+
20282039
/// Retrieve the Objective-C "instancetype" type, if already known;
20292040
/// otherwise, returns a NULL type;
20302041
QualType getObjCInstanceType() {

clang/include/clang/AST/DeclID.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ enum PredefinedDeclIDs {
8383
/// The internal '__type_pack_element' template.
8484
PREDEF_DECL_TYPE_PACK_ELEMENT_ID,
8585

86+
/// The internal '__builtin_common_type' template.
87+
PREDEF_DECL_COMMON_TYPE_ID,
88+
8689
/// The number of declaration IDs that are predefined.
8790
NUM_PREDEF_DECL_IDS
8891
};

clang/include/clang/Basic/Builtins.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,10 @@ enum BuiltinTemplateKind : int {
309309
BTK__make_integer_seq,
310310

311311
/// This names the __type_pack_element BuiltinTemplateDecl.
312-
BTK__type_pack_element
312+
BTK__type_pack_element,
313+
314+
/// This names the __builtin_common_type BuiltinTemplateDecl.
315+
BTK__builtin_common_type,
313316
};
314317

315318
} // end namespace clang

clang/lib/AST/ASTContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,13 @@ ASTContext::getTypePackElementDecl() const {
11841184
return TypePackElementDecl;
11851185
}
11861186

1187+
BuiltinTemplateDecl *ASTContext::getBuiltinCommonTypeDecl() const {
1188+
if (!BuiltinCommonTypeDecl)
1189+
BuiltinCommonTypeDecl = buildBuiltinTemplateDecl(
1190+
BTK__builtin_common_type, getBuiltinCommonTypeName());
1191+
return BuiltinCommonTypeDecl;
1192+
}
1193+
11871194
RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
11881195
RecordDecl::TagKind TK) const {
11891196
SourceLocation Loc;

clang/lib/AST/ASTImporter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5467,6 +5467,9 @@ ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
54675467
case BuiltinTemplateKind::BTK__type_pack_element:
54685468
ToD = Importer.getToContext().getTypePackElementDecl();
54695469
break;
5470+
case BuiltinTemplateKind::BTK__builtin_common_type:
5471+
ToD = Importer.getToContext().getBuiltinCommonTypeDecl();
5472+
break;
54705473
}
54715474
assert(ToD && "BuiltinTemplateDecl of unsupported kind!");
54725475
Importer.MapImported(D, ToD);

clang/lib/AST/DeclTemplate.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,13 +1608,69 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
16081608
nullptr);
16091609
}
16101610

1611+
static TemplateParameterList *createBuiltinCommonTypeList(const ASTContext &C,
1612+
DeclContext *DC) {
1613+
// class... Args
1614+
auto *Args =
1615+
TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
1616+
/*Depth=*/1, /*Position=*/0, /*Id=*/nullptr,
1617+
/*Typename=*/false, /*ParameterPack=*/true);
1618+
1619+
// <class... Args>
1620+
auto *BaseTemplateList = TemplateParameterList::Create(
1621+
C, SourceLocation(), SourceLocation(), Args, SourceLocation(), nullptr);
1622+
1623+
// template <class... Args> class BaseTemplate
1624+
auto *BaseTemplate = TemplateTemplateParmDecl::Create(
1625+
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
1626+
/*ParameterPack=*/false, /*Id=*/nullptr,
1627+
/*Typename=*/false, BaseTemplateList);
1628+
1629+
// class TypeMember
1630+
auto *TypeMember =
1631+
TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
1632+
/*Depth=*/1, /*Position=*/0, /*Id=*/nullptr,
1633+
/*Typename=*/false, /*ParameterPack=*/false);
1634+
1635+
// <class TypeMember>
1636+
auto *HasTypeMemberList =
1637+
TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
1638+
TypeMember, SourceLocation(), nullptr);
1639+
1640+
// template <class TypeMember> class HasTypeMember
1641+
auto *HasTypeMember = TemplateTemplateParmDecl::Create(
1642+
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/1,
1643+
/*ParameterPack=*/false, /*Id=*/nullptr,
1644+
/*Typename=*/false, HasTypeMemberList);
1645+
1646+
// class HasNoTypeMember
1647+
auto *HasNoTypeMember = TemplateTypeParmDecl::Create(
1648+
C, DC, {}, {}, /*Depth=*/0, /*Position=*/2, /*Id=*/nullptr,
1649+
/*Typename=*/false, /*ParameterPack=*/false);
1650+
1651+
// class... Ts
1652+
auto *Ts = TemplateTypeParmDecl::Create(
1653+
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/3,
1654+
/*Id=*/nullptr, /*Typename=*/false, /*ParameterPack=*/true);
1655+
1656+
// template <template <class... Args> class BaseTemplate,
1657+
// template <class TypeMember> class HasTypeMember, class HasNoTypeMember,
1658+
// class... Ts>
1659+
return TemplateParameterList::Create(
1660+
C, SourceLocation(), SourceLocation(),
1661+
{BaseTemplate, HasTypeMember, HasNoTypeMember, Ts}, SourceLocation(),
1662+
nullptr);
1663+
}
1664+
16111665
static TemplateParameterList *createBuiltinTemplateParameterList(
16121666
const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
16131667
switch (BTK) {
16141668
case BTK__make_integer_seq:
16151669
return createMakeIntegerSeqParameterList(C, DC);
16161670
case BTK__type_pack_element:
16171671
return createTypePackElementParameterList(C, DC);
1672+
case BTK__builtin_common_type:
1673+
return createBuiltinCommonTypeList(C, DC);
16181674
}
16191675

16201676
llvm_unreachable("unhandled BuiltinTemplateKind!");

clang/lib/Lex/PPMacroExpansion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
18361836
// Report builtin templates as being builtins.
18371837
.Case("__make_integer_seq", getLangOpts().CPlusPlus)
18381838
.Case("__type_pack_element", getLangOpts().CPlusPlus)
1839+
.Case("__builtin_common_type", getLangOpts().CPlusPlus)
18391840
// Likewise for some builtin preprocessor macros.
18401841
// FIXME: This is inconsistent; we usually suggest detecting
18411842
// builtin macros via #ifdef. Don't add more cases here.

clang/lib/Sema/SemaLookup.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,10 +928,15 @@ bool Sema::LookupBuiltin(LookupResult &R) {
928928
if (II == getASTContext().getMakeIntegerSeqName()) {
929929
R.addDecl(getASTContext().getMakeIntegerSeqDecl());
930930
return true;
931-
} else if (II == getASTContext().getTypePackElementName()) {
931+
}
932+
if (II == getASTContext().getTypePackElementName()) {
932933
R.addDecl(getASTContext().getTypePackElementDecl());
933934
return true;
934935
}
936+
if (II == getASTContext().getBuiltinCommonTypeName()) {
937+
R.addDecl(getASTContext().getBuiltinCommonTypeDecl());
938+
return true;
939+
}
935940
}
936941

937942
// Check if this is an OpenCL Builtin, and if so, insert its overloads.

0 commit comments

Comments
 (0)