[clang] [Clang][C++26] Implement Pack Indexing (P2662R3). (PR #72644)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 17 04:26:22 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clang-modules
Author: cor3ntin (cor3ntin)
<details>
<summary>Changes</summary>
https://isocpp.org/files/papers/P2662R3.pdf
Because there is a slight chance the syntax might change slightly (see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2994r0.html), the feature is not exposed in other language modes.
---
Patch is 101.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/72644.diff
69 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/include/clang-c/Index.h (+6-1)
- (modified) clang/include/clang/AST/ASTContext.h (+8)
- (modified) clang/include/clang/AST/ASTNodeTraverser.h (+6)
- (modified) clang/include/clang/AST/ExprCXX.h (+106)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+11)
- (modified) clang/include/clang/AST/Type.h (+66)
- (modified) clang/include/clang/AST/TypeLoc.h (+28)
- (modified) clang/include/clang/AST/TypeProperties.td (+14)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+7-1)
- (modified) clang/include/clang/Basic/Specifiers.h (+1)
- (modified) clang/include/clang/Basic/StmtNodes.td (+1)
- (modified) clang/include/clang/Basic/TokenKinds.def (+2)
- (modified) clang/include/clang/Basic/TypeNodes.td (+1)
- (modified) clang/include/clang/Parse/Parser.h (+9)
- (modified) clang/include/clang/Sema/DeclSpec.h (+23-2)
- (modified) clang/include/clang/Sema/Sema.h (+25)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+1)
- (modified) clang/include/clang/Serialization/TypeBitCodes.def (+2)
- (modified) clang/lib/AST/ASTContext.cpp (+43)
- (modified) clang/lib/AST/ASTImporter.cpp (+12)
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+10)
- (modified) clang/lib/AST/Expr.cpp (+8)
- (modified) clang/lib/AST/ExprCXX.cpp (+37)
- (modified) clang/lib/AST/ExprClassification.cpp (+3)
- (modified) clang/lib/AST/ExprConstant.cpp (+7)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+9)
- (modified) clang/lib/AST/MicrosoftMangle.cpp (+6)
- (modified) clang/lib/AST/StmtPrinter.cpp (+4)
- (modified) clang/lib/AST/StmtProfile.cpp (+6)
- (modified) clang/lib/AST/Type.cpp (+40)
- (modified) clang/lib/AST/TypePrinter.cpp (+18)
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+5)
- (modified) clang/lib/CodeGen/CGExpr.cpp (+2)
- (modified) clang/lib/CodeGen/CGExprAgg.cpp (+3)
- (modified) clang/lib/CodeGen/CGExprComplex.cpp (+4)
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+4)
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+3)
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+1)
- (modified) clang/lib/Parse/ParseCXXInlineMethods.cpp (+14)
- (modified) clang/lib/Parse/ParseDecl.cpp (+5)
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+101)
- (modified) clang/lib/Parse/ParseExpr.cpp (+13)
- (modified) clang/lib/Parse/ParseExprCXX.cpp (+67-1)
- (modified) clang/lib/Parse/ParseTentative.cpp (+13)
- (modified) clang/lib/Parse/Parser.cpp (+2-1)
- (modified) clang/lib/Sema/DeclSpec.cpp (+21)
- (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+23)
- (modified) clang/lib/Sema/SemaDecl.cpp (+1)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4)
- (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+1)
- (modified) clang/lib/Sema/SemaExpr.cpp (+3)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+24-8)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+5)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+16)
- (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+64-2)
- (modified) clang/lib/Sema/SemaType.cpp (+60)
- (modified) clang/lib/Sema/TreeTransform.h (+200)
- (modified) clang/lib/Serialization/ASTReader.cpp (+4)
- (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+22)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+5)
- (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+16)
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+1)
- (added) clang/test/PCH/pack_indexing.cpp (+16)
- (added) clang/test/Parser/cxx2b-pack-indexing.cpp (+65)
- (added) clang/test/SemaCXX/cxx2b-pack-indexing.cpp (+115)
- (modified) clang/tools/libclang/CIndex.cpp (+8)
- (modified) clang/tools/libclang/CXCursor.cpp (+4)
- (modified) clang/www/cxx_status.html (+1-1)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ed1a978b5382d71..dab670409077678 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -182,6 +182,8 @@ C++2c Feature Support
This is applied to both C++ standard attributes, and other attributes supported by Clang.
This completes the implementation of `P2361R6 Unevaluated Strings <https://wg21.link/P2361R6>`_
+- Implemented `P2662R3 Pack Indexing <https://wg21.link/P2662R3>`_.
+
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 64ab3378957c702..2c0b89a0d12b21e 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -1685,7 +1685,12 @@ enum CXCursorKind {
*/
CXCursor_CXXParenListInitExpr = 155,
- CXCursor_LastExpr = CXCursor_CXXParenListInitExpr,
+ /**
+ * Represents a C++26 pack indexing expression
+ */
+ CXCursor_PackIndexingExpr = 156,
+
+ CXCursor_LastExpr = CXCursor_PackIndexingExpr,
/* Statements */
CXCursor_FirstStmt = 200,
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 3e46a5da3fc043f..9e1c44eb19b805c 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -214,6 +214,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
DependentTypeOfExprTypes;
mutable llvm::ContextualFoldingSet<DependentDecltypeType, ASTContext &>
DependentDecltypeTypes;
+
+ mutable llvm::FoldingSet<PackIndexingType> DependentPackIndexingTypes;
+
mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;
mutable llvm::FoldingSet<SubstTemplateTypeParmType>
@@ -1713,6 +1716,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// C++11 decltype.
QualType getDecltypeType(Expr *e, QualType UnderlyingType) const;
+ QualType getPackIndexingType(QualType Pattern, Expr *IndexExpr,
+ bool FullyExpanded = false,
+ ArrayRef<QualType> Expansions = {},
+ int Index = -1) const;
+
/// Unary type transforms
QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
UnaryTransformType::UTTKind UKind) const;
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index cc8dab97f8b010f..950da2b8d2c4560 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -385,6 +385,12 @@ class ASTNodeTraverser
void VisitDecltypeType(const DecltypeType *T) {
Visit(T->getUnderlyingExpr());
}
+
+ void VisitPackIndexingType(const PackIndexingType *T) {
+ Visit(T->getPattern());
+ Visit(T->getIndexExpr());
+ }
+
void VisitUnaryTransformType(const UnaryTransformType *T) {
Visit(T->getBaseType());
}
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 24278016431837b..efd6558326099eb 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -4344,6 +4344,112 @@ class SizeOfPackExpr final
}
};
+class PackIndexingExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PackIndexingExpr, Expr *> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
+ SourceLocation EllipsisLoc;
+
+ // The location of the closing bracket
+ SourceLocation RSquareLoc;
+
+ // The pack being indexed, followed by the index
+ Stmt *SubExprs[2];
+
+ // The evaluated index
+ std::optional<int64_t> Index;
+
+ size_t TransformedExpressions;
+
+ PackIndexingExpr(QualType Type, SourceLocation EllipsisLoc,
+ SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr,
+ std::optional<int64_t> Index = std::nullopt,
+ ArrayRef<Expr *> SubstitutedExprs = {})
+ : Expr(PackIndexingExprClass, Type, VK_LValue, OK_Ordinary),
+ EllipsisLoc(EllipsisLoc), RSquareLoc(RSquareLoc),
+ SubExprs{PackIdExpr, IndexExpr}, Index(Index),
+ TransformedExpressions(SubstitutedExprs.size()) {
+
+ auto *Exprs = getTrailingObjects<Expr *>();
+ std::uninitialized_copy(SubstitutedExprs.begin(), SubstitutedExprs.end(),
+ Exprs);
+
+ ExprDependence D = IndexExpr->getDependence();
+ if (SubstitutedExprs.empty())
+ D |= (PackIdExpr->getDependence() |
+ ExprDependence::TypeValueInstantiation) &
+ ~ExprDependence::UnexpandedPack;
+ else if (!IndexExpr->isValueDependent()) {
+ assert(Index && *Index < int64_t(SubstitutedExprs.size()) &&
+ "pack index out of bound");
+ D |= SubstitutedExprs[*Index]->getDependence();
+ setValueKind(SubstitutedExprs[*Index]->getValueKind());
+ }
+ setDependence(D);
+ }
+
+ /// Create an empty expression.
+ PackIndexingExpr(EmptyShell Empty) : Expr(PackIndexingExprClass, Empty) {}
+
+ unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+ return TransformedExpressions;
+ }
+
+public:
+ static PackIndexingExpr *Create(ASTContext &Context,
+ SourceLocation EllipsisLoc,
+ SourceLocation RSquareLoc, Expr *PackIdExpr,
+ Expr *IndexExpr,
+ std::optional<int64_t> Index = std::nullopt,
+ ArrayRef<Expr *> SubstitutedExprs = {});
+ static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
+ unsigned NumTransformedExprs);
+
+ /// Determine the location of the 'sizeof' keyword.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// Determine the location of the parameter pack.
+ SourceLocation getPackLoc() const { return SubExprs[0]->getBeginLoc(); }
+
+ /// Determine the location of the right parenthesis.
+ SourceLocation getRSquareLoc() const { return RSquareLoc; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getPackLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RSquareLoc; }
+
+ Expr *getPackIdExpression() const { return cast<Expr>(SubExprs[0]); }
+
+ NamedDecl *getPackDecl() const;
+
+ Expr *getIndexExpr() const { return cast<Expr>(SubExprs[1]); }
+
+ Expr *getSelectedExpr() const {
+ assert(Index && !isInstantiationDependent() &&
+ "extracting the indexed expression of a dependant pack");
+ return getTrailingObjects<Expr *>()[*Index];
+ }
+
+ llvm::ArrayRef<Expr *> getExpressions() const {
+ if (TransformedExpressions == 0)
+ return {};
+ return {getTrailingObjects<Expr *>(), TransformedExpressions};
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PackIndexingExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(SubExprs, SubExprs + 2); }
+
+ const_child_range children() const {
+ return const_child_range(SubExprs, SubExprs + 2);
+ }
+};
+
/// Represents a reference to a non-type template parameter
/// that has been substituted with a template argument.
class SubstNonTypeTemplateParmExpr : public Expr {
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 53bc15e1b19f668..1c26f0512fa1342 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1063,6 +1063,11 @@ DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); })
DEF_TRAVERSE_TYPE(DecltypeType,
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
+DEF_TRAVERSE_TYPE(PackIndexingType, {
+ TRY_TO(TraverseType(T->getPattern()));
+ TRY_TO(TraverseStmt(T->getIndexExpr()));
+})
+
DEF_TRAVERSE_TYPE(UnaryTransformType, {
TRY_TO(TraverseType(T->getBaseType()));
TRY_TO(TraverseType(T->getUnderlyingType()));
@@ -1341,6 +1346,11 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPELOC(PackIndexingType, {
+ TRY_TO(TraverseType(TL.getPattern()));
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getIndexExpr()));
+})
+
DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
})
@@ -2857,6 +2867,7 @@ DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
DEF_TRAVERSE_STMT(PackExpansionExpr, {})
DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
+DEF_TRAVERSE_STMT(PackIndexingExpr, {})
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 6c147eb8f640623..a710766d1cf92f9 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -4884,6 +4884,72 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
Expr *E);
};
+class PackIndexingType final
+ : public Type,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<PackIndexingType, QualType> {
+ friend TrailingObjects;
+
+ const ASTContext &Context;
+ QualType Pattern;
+ Expr *IndexExpr;
+
+ unsigned Size;
+ int Index = -1;
+
+protected:
+ friend class ASTContext; // ASTContext creates these.
+ PackIndexingType(const ASTContext &Context, QualType Canonical,
+ QualType Pattern, Expr *IndexExpr,
+ ArrayRef<QualType> Expansions = {}, int Index = -1);
+
+public:
+ Expr *getIndexExpr() const { return IndexExpr; }
+ QualType getPattern() const { return Pattern; }
+
+ bool isSugared() const { return hasSelectedType(); }
+
+ QualType desugar() const {
+ if (hasSelectedType())
+ return getSelectedType();
+ return QualType(this, 0);
+ }
+
+ QualType getSelectedType() const {
+ assert(hasSelectedType() && "Type is dependant");
+ return *(getExpansionsPtr() + Index);
+ }
+
+ bool hasSelectedType() const { return Index != -1 && !isDependentType(); }
+
+ ArrayRef<QualType> getExpansions() const {
+ return {getExpansionsPtr(), Size};
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == PackIndexing;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ if (hasSelectedType())
+ getSelectedType().Profile(ID);
+ else
+ Profile(ID, Context, getPattern(), getIndexExpr());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType Pattern, Expr *E);
+
+private:
+ const QualType *getExpansionsPtr() const {
+ return getTrailingObjects<QualType>();
+ }
+
+ static TypeDependence computeDependence(QualType Pattern, Expr *IndexExpr,
+ ArrayRef<QualType> Expansions = {});
+
+ unsigned numTrailingObjects(OverloadToken<QualType>) const { return Size; }
+};
+
/// A unary type transform, which is a type constructed from another.
class UnaryTransformType : public Type {
public:
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 471deb14aba51fc..38e40ece425fb8f 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2055,6 +2055,34 @@ class DecltypeTypeLoc
}
};
+struct PackIndexingTypeLocInfo {
+ SourceLocation EllipsisLoc;
+};
+
+class PackIndexingTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, PackIndexingTypeLoc,
+ PackIndexingType, PackIndexingTypeLocInfo> {
+
+public:
+ Expr *getIndexExpr() const { return getTypePtr()->getIndexExpr(); }
+ QualType getPattern() const { return getTypePtr()->getPattern(); }
+
+ SourceLocation getEllipsisLoc() const { return getLocalData()->EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation Loc) { getLocalData()->EllipsisLoc = Loc; }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setEllipsisLoc(Loc);
+ }
+
+ TypeLoc getPatternLoc() const { return getInnerTypeLoc(); }
+
+ QualType getInnerType() const { return this->getTypePtr()->getPattern(); }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getEllipsisLoc(), getEllipsisLoc());
+ }
+};
+
struct UnaryTransformTypeLocInfo {
// FIXME: While there's only one unary transform right now, future ones may
// need different representations
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 682c869b0c58479..0ba172a4035fdb4 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -433,6 +433,20 @@ let Class = DecltypeType in {
}]>;
}
+let Class = PackIndexingType in {
+ def : Property<"pattern", QualType> {
+ let Read = [{ node->getPattern() }];
+ }
+ def : Property<"indexExpression", ExprRef> {
+ let Read = [{ node->getIndexExpr() }];
+ }
+
+ def : Creator<[{
+ return ctx.getPackIndexingType(pattern, indexExpression);
+ }]>;
+}
+
+
let Class = UnaryTransformType in {
def : Property<"baseType", QualType> {
let Read = [{ node->getBaseType() }];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a9dde041bc22a6d..5f80debb9a454f6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5681,9 +5681,15 @@ def err_function_parameter_pack_without_parameter_packs : Error<
def err_ellipsis_in_declarator_not_parameter : Error<
"only function and template parameters can be parameter packs">;
-def err_sizeof_pack_no_pack_name : Error<
+def err_expected_name_of_pack : Error<
"%0 does not refer to the name of a parameter pack">;
+def err_pack_index_out_of_bound : Error<
+ "%0 is not a valid index for pack %1 of size %2">;
+
+def err_pack_index_todo : Error<
+ "Pack index not implemented">;
+
def err_fold_expression_packs_both_sides : Error<
"binary fold expression has unexpanded parameter packs in both operands">;
def err_fold_expression_empty : Error<
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 87f29c8ae10bd9a..bff4c1616c1d027 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -94,6 +94,7 @@ namespace clang {
TST_auto_type, // __auto_type extension
TST_unknown_anytype, // __unknown_anytype extension
TST_atomic, // C11 _Atomic
+ TST_indexed_typename_pack,
#define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types
#include "clang/Basic/OpenCLImageTypes.def"
TST_error // erroneous type
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index cec301dfca2817b..9d03800840fcd0b 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -154,6 +154,7 @@ def UnresolvedMemberExpr : StmtNode<OverloadExpr>;
def CXXNoexceptExpr : StmtNode<Expr>;
def PackExpansionExpr : StmtNode<Expr>;
def SizeOfPackExpr : StmtNode<Expr>;
+def PackIndexingExpr : StmtNode<Expr>;
def SubstNonTypeTemplateParmExpr : StmtNode<Expr>;
def SubstNonTypeTemplateParmPackExpr : StmtNode<Expr>;
def FunctionParmPackExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 82a503d01068d53..6b5f8210fa6d0e3 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -836,6 +836,8 @@ ANNOTATION(primary_expr) // annotation for a primary expression, used when
// message send
ANNOTATION(decltype) // annotation for a decltype expression,
// e.g., "decltype(foo.bar())"
+ANNOTATION(indexed_pack_type) // annotation for an indexed pack of type,
+ // e.g., "T...[expr]"
// Annotation for #pragma unused(...)
// For each argument inside the parentheses the pragma handler will produce
diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
index 649b071cebb9404..6419762417371b9 100644
--- a/clang/include/clang/Basic/TypeNodes.td
+++ b/clang/include/clang/Basic/TypeNodes.td
@@ -103,6 +103,7 @@ def InjectedClassNameType : TypeNode<Type>, AlwaysDependent, LeafType;
def DependentNameType : TypeNode<Type>, AlwaysDependent;
def DependentTemplateSpecializationType : TypeNode<Type>, AlwaysDependent;
def PackExpansionType : TypeNode<Type>, AlwaysDependent;
+def PackIndexingType : TypeNode<Type>, NeverCanonicalUnlessDependent;
def ObjCTypeParamType : TypeNode<Type>, NeverCanonical;
def ObjCObjectType : TypeNode<Type>;
def ObjCInterfaceType : TypeNode<ObjCObjectType>, LeafType;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 30e0352c868637b..c7bbc3d6384306f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1884,6 +1884,10 @@ class Parser : public CodeCompletionHandler {
// C++ Expressions
ExprResult tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand,
Token &Replacement);
+
+ ExprResult tryParseCXXPackIndexingExpression(ExprResult PackIdExpression);
+ ExprResult ParseCXXPackIndexingExpression(ExprResult PackIdExpression);
+
ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
bool areTokensAdjacent(const Token &A, const Token &B);
@@ -2430,6 +2434,11 @@ class Parser : public CodeCompletionHandler {
DeclSpecContext DSC, LateParsedAttrList *LateAttrs,
ImplicitTypenameContext AllowImplicitTypename);
+ SourceLocation ParseIndexedTypeNamePack(DeclSpec &DS);
+ void AnnotateExistingIndexedTypeNamePack(ParsedType T,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
bool DiagnoseMissingSemiAfterTagDefinition(
DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext,
LateParsedAttrList *LateAttrs = nullptr);
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 4561cca929c0d0b..4726cbbd1af50c9 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -309,6 +309,7 @@ class DeclSpec {
static const TST TST_typeof_unqualExpr = clang::TST_typeof_unqualExpr;
static const TST TST_decltype = clang::TST_decltype;
static const TST TST_decltype_auto = clang::TST_decltype_auto;
+ static const TST TST_indexed_typename_pack = clang::TST_indexed_typename_pack;
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
static const TST TST_##Trait = clang::TST_##Trait;
#include "clang/Basic/TransformTypeTraits.def"
@@ -389,6 +390,7 @@ class DeclSpec {
Expr *ExprRep;
TemplateIdAnnotation *TemplateIdRep;
};
+ Expr *PackIndexingExpr = nullptr;
/// ExplicitSpecifier - Store information about explicit spicifer.
ExplicitSpecifier FS_explicit_specifier;
@@ -405,7 +407,7 @@ class DeclSpec {
SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
SourceRange TSWRange;
- SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc;
+ SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc, EllipsisLoc;
/// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
/// typename, then this is the location of the named type (if present);
/// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
@@ -427,7 +429,8 @@ class DeclSpec {
static bool isTypeRep(TST T) {
return T == TST_atomic || T == TST_typename || T == TST_typeofType ||
- T == TST_typeof_unqualType || isTransformTypeTrait(T);
+ T == TST_typeof_unqualType || isTransformTypeTrait(T) ||
+ T == TST_indexed_typename_pack;
}
static bool isExprRep(TST T) {
return T == TST_typeofExpr || T == TST_typeof_unqualExpr ||
@@ -530,6 +533,13 @@ class DeclSpec {
assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
return ExprRep;
}
+
+ Expr *getPackIndexingExpr() const {
+ assert(TypeSpecType == TST_indexed_ty...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/72644
More information about the cfe-commits
mailing list