Skip to content

Commit 4c2b4aa

Browse files
committed
Add a bunch of documentation
1 parent 2ff4de2 commit 4c2b4aa

File tree

3 files changed

+203
-11
lines changed

3 files changed

+203
-11
lines changed

clang/include/clang/AST/DeclTemplate.h

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3346,12 +3346,71 @@ class TemplateParamObjectDecl : public ValueDecl,
33463346
/// Represents a C++26 expansion statement declaration.
33473347
///
33483348
/// This is a bit of a hack, since expansion statements shouldn't really be
3349-
/// "declarations" per se (they don't declare anything). Nevertheless, we *do*
3349+
/// 'declarations' per se (they don't declare anything). Nevertheless, we *do*
33503350
/// need them to be declaration *contexts*, because the DeclContext is used to
3351-
/// compute the "template depth" of entities enclosed therein. In particular,
3352-
/// the "template depth" is used to find instantiations of parameter variables,
3351+
/// compute the 'template depth' of entities enclosed therein. In particular,
3352+
/// the 'template depth' is used to find instantiations of parameter variables,
33533353
/// and a lambda enclosed within an expansion statement cannot compute its
33543354
/// template depth without a pointer to the enclosing expansion statement.
3355+
///
3356+
/// For the remainder of this comment, let 'expanding' an expansion statement
3357+
/// refer to the process of performing template substitution on its body N
3358+
/// times, where N is the expansion size (how this size is determined depends on
3359+
/// the kind of expansion statement); by contrast we may sometimes 'instantiate'
3360+
/// an expansion statement (because it happens to be in a template). This is
3361+
/// just regular template instantiation.
3362+
///
3363+
/// Apart from a template parameter list that contains a template parameter used
3364+
/// as the expansion index, this node contains a 'CXXExpansionStmt' as well as a
3365+
/// 'CXXExpansionInstantiationStmt'. These two members correspond to distinct
3366+
/// representations of the expansion statement: the former is used prior to
3367+
/// expansion and contains all the parts needed to perform expansion; the latter
3368+
/// holds the expanded/desugared AST nodes that result from the expansion.
3369+
///
3370+
/// After expansion, the 'CXXExpansionStmt' is no longer updated and left as-is;
3371+
/// this also means that, if an already-expanded expansion statement is inside a
3372+
/// template, and that template is then instantiated, the 'CXXExpansionStmt' is
3373+
/// *not* instantiated; only the 'CXXExpansionInstantiationStmt' is. The latter
3374+
/// is also what's used for codegen and constant evaluation.
3375+
///
3376+
/// For example, if the user writes the following expansion statement:
3377+
/// \verbatim
3378+
/// std::array<int, 3> a {1, 2, 3};
3379+
/// template for (auto x : a) {
3380+
/// // ...
3381+
/// }
3382+
/// \endverbatim
3383+
///
3384+
/// The 'CXXExpansionStmt' of this particular 'ExpansionStmtDecl' is a
3385+
/// 'CXXDestructuringExpansionStmt', which stores, amongst other things, the
3386+
/// declaration of the variable 'x' as well as the expansion-initializer 'a'.
3387+
///
3388+
/// After expansion, we end up with a 'CXXExpansionInstantiationStmt' that
3389+
/// contains a DecompositionDecl and 3 CompoundStmts, one for each expansion:
3390+
///
3391+
/// \verbatim
3392+
/// {
3393+
/// auto [__u0, __u1, __u2] = a;
3394+
/// {
3395+
/// auto x = __u0;
3396+
/// // ...
3397+
/// }
3398+
/// {
3399+
/// auto x = __u1;
3400+
/// // ...
3401+
/// }
3402+
/// {
3403+
/// auto x = __u2;
3404+
/// // ...
3405+
/// }
3406+
/// }
3407+
/// \endverbatim
3408+
///
3409+
/// The outer braces shown above are implicit; we don't actually create another
3410+
/// CompoundStmt wrapping everything.
3411+
///
3412+
/// \see CXXExpansionStmt
3413+
/// \see CXXExpansionInstantiationStmt
33553414
class ExpansionStmtDecl : public Decl, public DeclContext {
33563415
CXXExpansionStmt *Expansion = nullptr;
33573416
TemplateParameterList *TParams;

clang/include/clang/AST/ExprCXX.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5501,8 +5501,9 @@ class BuiltinBitCastExpr final
55015501
}
55025502
};
55035503

5504-
/// Represents an expansion-init-list to be expanded over by an expansion
5505-
/// statement.
5504+
/// Represents an expansion-init-list of an enumerating expansion statement.
5505+
///
5506+
/// \see CXXEnumeratingExpansionStmt
55065507
class CXXExpansionInitListExpr final
55075508
: public Expr,
55085509
llvm::TrailingObjects<CXXExpansionInitListExpr, Expr *> {
@@ -5562,6 +5563,8 @@ class CXXExpansionInitListExpr final
55625563

55635564
/// Helper that selects an expression from an expansion init list depending
55645565
/// on the current expansion index.
5566+
///
5567+
/// \see CXXEnumeratingExpansionStmt
55655568
class CXXExpansionInitListSelectExpr : public Expr {
55665569
friend class ASTStmtReader;
55675570

@@ -5606,6 +5609,12 @@ class CXXExpansionInitListSelectExpr : public Expr {
56065609
}
56075610
};
56085611

5612+
/// This class serves the same purpose as CXXExpansionInitListSelectExpr, but
5613+
/// for destructuring expansion statements; that is, instead of selecting among
5614+
/// a list of expressions, it selects from a list of 'BindingDecl's.
5615+
///
5616+
/// \see CXXEnumeratingExpansionStmt
5617+
/// \see CXXDestructuringExpansionStmt
56095618
class CXXDestructuringExpansionSelectExpr : public Expr {
56105619
friend class ASTStmtReader;
56115620

clang/include/clang/AST/StmtCXX.h

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,17 @@ class CoreturnStmt : public Stmt {
526526
};
527527

528528
/// CXXExpansionStmt - Base class for an unexpanded C++ expansion statement.
529+
///
530+
/// The main purpose for this class is to store the AST nodes common to all
531+
/// variants of expansion statements; it also provides storage for additional
532+
/// subexpressions required by its derived classes. This is to simplify the
533+
/// implementation of 'children()' and friends.
534+
///
535+
/// \see ExpansionStmtDecl
536+
/// \see CXXEnumeratingExpansionStmt
537+
/// \see CXXIteratingExpansionStmt
538+
/// \see CXXDestructuringExpansionStmt
539+
/// \see CXXDependentExpansionStmt
529540
class CXXExpansionStmt : public Stmt {
530541
friend class ASTStmtReader;
531542

@@ -622,7 +633,35 @@ class CXXExpansionStmt : public Stmt {
622633

623634
/// Represents an unexpanded enumerating expansion statement.
624635
///
625-
/// The expansion initializer of this is always a CXXExpansionInitListExpr.
636+
/// An 'enumerating' expansion statement is one whose expansion-initializer
637+
/// is a brace-enclosed expression-list; this list is syntactically similar to
638+
/// an initializer list, but it isn't actually an expression in and of itself
639+
/// (in that it is never evaluated or emitted) and instead is just treated as
640+
/// a group of expressions. The expansion initializer of this is always a
641+
/// 'CXXExpansionInitListExpr'.
642+
///
643+
/// Example:
644+
/// \verbatim
645+
/// template for (auto x : { 1, 2, 3 }) {
646+
/// // ...
647+
/// }
648+
/// \endverbatim
649+
///
650+
/// Note that the expression-list may also contain pack expansions, e.g.
651+
/// '{ 1, xs... }', in which case the expansion size is dependent.
652+
///
653+
/// Here, the '{ 1, 2, 3 }' is parsed as a 'CXXExpansionInitListExpr'. This node
654+
/// handles storing (and pack-expanding) the individual expressions.
655+
///
656+
/// Sema then wraps this with a 'CXXExpansionInitListSelectExpr', which also
657+
/// contains a reference to an integral NTTP that is used as the expansion
658+
/// index; this index is either dependent (if the expansion-size is dependent),
659+
/// or set to a value of I in the I-th expansion during the expansion process.
660+
///
661+
/// The actual expansion is done by 'BuildCXXExpansionInitListSelectExpr()': for
662+
/// example, during the 2nd expansion of '{ a, b, c }', I is equal to 1, and
663+
/// BuildCXXExpansionInitListSelectExpr(), when called via TreeTransform,
664+
/// 'instantiates' the expression '{ a, b, c }' to just 'b'.
626665
class CXXEnumeratingExpansionStmt : public CXXExpansionStmt {
627666
friend class ASTStmtReader;
628667

@@ -638,7 +677,24 @@ class CXXEnumeratingExpansionStmt : public CXXExpansionStmt {
638677
}
639678
};
640679

641-
/// Represents an expansion statement whose expansion-initializer is dependent.
680+
/// Represents an expansion statement whose expansion-initializer is
681+
/// type-dependent.
682+
///
683+
/// This will be instantiated as either a 'CXXIteratingExpansionStmt' or a
684+
/// 'CXXDestructuringExpansionStmt'. Dependent expansion statements can never
685+
/// be enumerating; those are always stored as a 'CXXEnumeratingExpansionStmt',
686+
/// even if the expansion size is dependent because the expression-list contains
687+
/// a pack.
688+
///
689+
/// Example:
690+
/// \verbatim
691+
/// template <typename T>
692+
/// void f() {
693+
/// template for (auto x : T()) {
694+
/// // ...
695+
/// }
696+
/// }
697+
/// \endverbatim
642698
class CXXDependentExpansionStmt : public CXXExpansionStmt {
643699
friend class ASTStmtReader;
644700

@@ -673,8 +729,20 @@ class CXXDependentExpansionStmt : public CXXExpansionStmt {
673729

674730
/// Represents an unexpanded iterating expansion statement.
675731
///
676-
/// The expression used to compute the size of the expansion is not stored in
677-
/// this as it is only created at the moment of expansion.
732+
/// An 'iterating' expansion statement is one whose expansion-initializer is a
733+
/// a range (i.e. it has a corresponding 'begin()'/'end()' pair that is
734+
/// determined based on a number of conditions as stated in [stmt.expand] and
735+
/// [stmt.ranged]).
736+
///
737+
/// The expression used to compute the size of the expansion is not stored and
738+
/// is only created at the moment of expansion.
739+
///
740+
/// \verbatim
741+
/// static constexpr std::string_view foo = "1234";
742+
/// template for (auto x : foo) {
743+
/// // ...
744+
/// }
745+
/// \endverbatim
678746
class CXXIteratingExpansionStmt : public CXXExpansionStmt {
679747
friend class ASTStmtReader;
680748

@@ -742,7 +810,29 @@ class CXXIteratingExpansionStmt : public CXXExpansionStmt {
742810
}
743811
};
744812

745-
/// Represents an expansion statement whose expansion-initializer is dependent.
813+
/// Represents an unexpanded destructuring expansion statement.
814+
///
815+
/// A 'destructuring' expansion statement is any expansion statement that is
816+
/// not enumerating or iterating (i.e. destructuring is the last thing we try,
817+
/// and if it doesn't work, the program is ill-formed).
818+
///
819+
/// This essentially involves treating the expansion-initializer as the
820+
/// initializer of a structured-binding declarations, with the number of
821+
/// bindings and expansion size determined by the usual means (array size,
822+
/// std::tuple_size, etc.).
823+
///
824+
/// Example:
825+
/// \verbatim
826+
/// std::array<int, 3> a {1, 2, 3};
827+
/// template for (auto x : a) {
828+
/// // ...
829+
/// }
830+
/// \endverbatim
831+
///
832+
/// Sema wraps the initializer with a CXXDestructuringExpansionSelectExpr, which
833+
/// selects a binding based on the current expansion index; this is analogous to
834+
/// how 'CXXExpansionInitListSelectExpr' is used; see the documentation of
835+
/// 'CXXEnumeratingExpansionStmt' for more details on this.
746836
class CXXDestructuringExpansionStmt : public CXXExpansionStmt {
747837
friend class ASTStmtReader;
748838

@@ -780,7 +870,7 @@ class CXXDestructuringExpansionStmt : public CXXExpansionStmt {
780870
}
781871
};
782872

783-
/// Represents the code generated for an instantiated expansion statement.
873+
/// Represents the code generated for an expanded expansion statement.
784874
///
785875
/// This holds 'shared statements' and 'instantiations'; these encode the
786876
/// general underlying pattern that all expansion statements desugar to:
@@ -797,6 +887,40 @@ class CXXDestructuringExpansionStmt : public CXXExpansionStmt {
797887
/// }
798888
/// }
799889
/// \endverbatim
890+
///
891+
/// Here, the only thing that is stored in the AST are the 'shared statements'
892+
/// and the 'CompoundStmt's that wrap the 'instantiations'. The outer braces
893+
/// shown above are implicit.
894+
///
895+
/// For example, the CXXExpansionInstantiationStmt that corresponds to the
896+
/// following expansion statement
897+
///
898+
/// \verbatim
899+
/// std::array<int, 3> a {1, 2, 3};
900+
/// template for (auto x : a) {
901+
/// // ...
902+
/// }
903+
/// \endverbatim
904+
///
905+
/// would be
906+
///
907+
/// \verbatim
908+
/// {
909+
/// auto [__u0, __u1, __u2] = a;
910+
/// {
911+
/// auto x = __u0;
912+
/// // ...
913+
/// }
914+
/// {
915+
/// auto x = __u1;
916+
/// // ...
917+
/// }
918+
/// {
919+
/// auto x = __u2;
920+
/// // ...
921+
/// }
922+
/// }
923+
/// \endverbatim
800924
class CXXExpansionInstantiationStmt final
801925
: public Stmt,
802926
llvm::TrailingObjects<CXXExpansionInstantiationStmt, Stmt *> {

0 commit comments

Comments
 (0)