23#include "llvm/ADT/ScopeExit.h"
28struct IterableExpansionStmtData {
39 enum class IsIterableResult {
45 DeclStmt *RangeDecl =
nullptr;
46 DeclStmt *BeginDecl =
nullptr;
47 DeclStmt *IterDecl =
nullptr;
48 IsIterableResult TheState = IsIterableResult::NotIterable;
50 bool isIterable()
const {
return TheState == IsIterableResult::Iterable; }
51 bool hasError() {
return TheState == IsIterableResult::Error; }
75 return llvm::any_of(ILE->
inits(),
76 [](
const Expr *E) { return isa<PackExpansionExpr>(E); });
102 llvm_unreachable(
"invalid pattern kind");
109 IterableExpansionStmtData
Data;
124 bool FoundBeginEnd =
false;
149 if (!FoundBeginEnd && (!HasADLCandidate(BeginName.
getName()) ||
150 !HasADLCandidate(EndName.
getName())))
166 Data.TheState = IterableExpansionStmtData::IsIterableResult::Error;
203 if (BeginStmt.isInvalid())
207 S.
Diag(ColonLoc, diag::err_iterating_expansion_stmt_unsupported);
222 StmtResult IterVarStmt =
224 if (IterVarStmt.isInvalid())
229 cast<VarDecl>(RangeVar->getSingleDecl()), LifetimeExtendTemps);
232 Data.RangeDecl = RangeVar;
234 Data.TheState = IterableExpansionStmtData::IsIterableResult::Iterable;
260 for (
unsigned I = 0; I < *Arity; ++I)
272 DD->setConstexpr(
true);
288 Context.getTrivialTypeSourceInfo(ParmTy, TemplateKWLoc);
291 Context,
Context.getTranslationUnitDecl(), TemplateKWLoc, TemplateKWLoc,
292 TemplateDepth, 0,
nullptr, ParmTy,
319 if (!ExpansionInitializer || ExpansionInitializer->
containsErrors() ||
325 if (!DS->isSingleDecl()) {
326 Diag(DS->getBeginLoc(), diag::err_type_defined_in_for_range);
330 VarDecl *ExpansionVar = dyn_cast<VarDecl>(DS->getSingleDecl());
335 if (
auto *ILE = dyn_cast<InitListExpr>(ExpansionInitializer)) {
336 assert(ILE->isSyntacticForm());
344 ColonLoc, RParenLoc);
351 ExpansionInitializer = R.get();
358 ESD,
Init, DS, ExpansionInitializer, LParenLoc, ColonLoc, RParenLoc,
359 LifetimeExtendTemps);
380 Diag(ExpansionInitializer->
getBeginLoc(), diag::err_expansion_stmt_lambda);
387 Context, ESD,
Init, ExpansionVarStmt, ExpansionInitializer, LParenLoc,
388 ColonLoc, RParenLoc);
392 ExpansionInitializer->
getType(),
393 diag::err_expansion_stmt_incomplete))
397 Diag(ExpansionInitializer->
getExprLoc(), diag::err_expansion_stmt_vla)
398 << ExpansionInitializer->
getType();
405 *
this, ExpansionInitializer, Index, ColonLoc, ExpansionVar->
isConstexpr(),
406 LifetimeExtendTemps);
407 if (
Data.hasError()) {
412 if (
Data.isIterable()) {
416 IterVar, IterVar->getType().getNonReferenceType(),
VK_LValue, ColonLoc);
419 if (Deref.isInvalid()) {
431 Data.IterDecl, LParenLoc, ColonLoc, RParenLoc);
436 *
this, ExpansionInitializer, ColonLoc, ExpansionVar->
isConstexpr(),
437 LifetimeExtendTemps);
440 diag::err_expansion_stmt_invalid_init)
441 << ExpansionInitializer->
getType()
450 if (DD->isInvalidDecl())
457 Bindings.reserve(DD->bindings().size());
464 if (!ExpansionInitializer->
isLValue()) {
470 ColonLoc, tok::kw_static_cast, TSI, Element,
472 assert(!Cast.isInvalid() &&
"cast to rvalue reference type failed?");
473 Element = Cast.get();
493 Context, ESD,
Init, ExpansionVarStmt, DS, LParenLoc, ColonLoc, RParenLoc);
501 assert(!Expansion->getDecl()->getInstantiations() &&
502 "should not rebuild expansion statement after instantiation");
504 Expansion->setBody(Body);
515 if (!NumInstantiations)
526 if (Expansion->getInit())
527 Preamble.push_back(Expansion->getInit());
529 if (Expansion->isIterating()) {
530 Preamble.push_back(Expansion->getRangeVarStmt());
531 Preamble.push_back(Expansion->getBeginVarStmt());
532 }
else if (Expansion->isDestructuring()) {
533 Preamble.push_back(Expansion->getDecompositionDeclStmt());
539 if (*NumInstantiations == 0) {
540 Expansion->getDecl()->setInstantiations(
543 Expansion->isDestructuring()));
550 if (Expansion->isIterating())
551 StmtsToInstantiate.push_back(Expansion->getIterVarStmt());
552 StmtsToInstantiate.push_back(Expansion->getExpansionVarStmt());
553 StmtsToInstantiate.push_back(Body);
562 unsigned PtrDiffTWidth =
Context.getIntWidth(PtrDiffT);
564 for (uint64_t I = 0; I < *NumInstantiations; ++I) {
565 llvm::APInt IVal{PtrDiffTWidth, I};
567 Context, llvm::APSInt{std::move(IVal), PtrDiffTIsUnsigned}, PtrDiffT};
570 Expansion->getDecl()->getIndexTemplateParm()->getDepth());
580 Instantiations.push_back(Instantiation.
get());
585 Expansion->isDestructuring() || Expansion->isIterating());
587 Expansion->getDecl()->setInstantiations(InstantiationsStmt);
598 return Range->getInit(I);
601std::optional<uint64_t>
624 Diag(Loc, diag::err_iterating_expansion_stmt_unsupported);
632 Diag(Loc, diag::err_expansion_size_expr_not_ice);
633 for (
const auto &[Location,
PDiag] : Notes)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::MachO::Record Record
Defines the clang::Preprocessor interface.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
static bool FinalizeExpansionVar(Sema &S, VarDecl *ExpansionVar, ExprResult Initializer)
static bool HasDependentSize(const DeclContext *CurContext, const CXXExpansionStmtPattern *Pattern)
static DeclRefExpr * BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD)
static StmtResult BuildDestructuringDecompositionDecl(Sema &S, Expr *ExpansionInitializer, SourceLocation ColonLoc, bool VarIsConstexpr, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps)
static auto InitListContainsPack(const InitListExpr *ILE)
static IterableExpansionStmtData TryBuildIterableExpansionStmtInitializer(Sema &S, Expr *ExpansionInitializer, Expr *Index, SourceLocation ColonLoc, bool VarIsConstexpr, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps)
QualType getAutoRRefDeductType() const
C++11 deduction pattern for 'auto &&' type.
QualType getAutoType(DeducedKind DK, QualType DeducedAsType, AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept=nullptr, ArrayRef< TemplateArgument > TypeConstraintArgs={}) const
C++11 deduced auto type.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getAutoDeductType() const
C++11 deduction pattern for 'auto' type.
A binding in a decomposition declaration.
static BindingDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T)
Helper that selects an expression from an InitListExpr depending on the current expansion index.
Represents a C++26 expansion statement declaration.
static CXXExpansionStmtDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, NonTypeTemplateParmDecl *NTTP)
NonTypeTemplateParmDecl * getIndexTemplateParm()
static CXXExpansionStmtInstantiation * Create(ASTContext &C, CXXExpansionStmtDecl *Parent, ArrayRef< Stmt * > Instantiations, ArrayRef< Stmt * > PreambleStmts, bool ShouldApplyLifetimeExtensionToPreamble)
CXXExpansionStmtPattern - Represents an unexpanded C++ expansion statement.
bool isEnumerating() const
ExpansionStmtKind getKind() const
static CXXExpansionStmtPattern * CreateIterating(ASTContext &Context, CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVar, DeclStmt *Range, DeclStmt *Begin, DeclStmt *Iter, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc)
Create an iterating expansion statement pattern.
DecompositionDecl * getDecompositionDecl()
static CXXExpansionStmtPattern * CreateDependent(ASTContext &Context, CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVar, Expr *ExpansionInitializer, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc)
Create a dependent expansion statement pattern.
static CXXExpansionStmtPattern * CreateDestructuring(ASTContext &Context, CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVar, Stmt *DecompositionDeclStmt, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc)
Create a destructuring expansion statement pattern.
SourceLocation getColonLoc() const
bool isDestructuring() const
static CXXExpansionStmtPattern * CreateEnumerating(ASTContext &Context, CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVar, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc)
Create an enumerating expansion statement pattern.
VarDecl * getExpansionVariable()
bool isLambda() const
Determine whether this class describes a lambda function object.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
void addDecl(Decl *D)
Add the declaration D into this context.
bool isExpansionStmt() const
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
bool isInvalidDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
The name of a declaration.
ArrayRef< BindingDecl * > bindings() const
static DecompositionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation LSquareLoc, SourceLocation RSquareLoc, QualType T, TypeSourceInfo *TInfo, StorageClass S, ArrayRef< BindingDecl * > Bindings)
RAII object that enters a new expression evaluation context.
This represents one expression.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Represents difference between two FPOptions values.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Describes an C or C++ initializer list.
ArrayRef< Expr * > inits() const
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Represents the results of name lookup.
Data structure that captures multiple levels of template argument lists for use in template instantia...
void addOuterRetainedLevels(unsigned Num)
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....
@ CSK_Normal
Normal lookup.
SmallVectorImpl< OverloadCandidate >::iterator iterator
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best)
Find the best viable function on this overload set, if it exists.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
IdentifierTable & getIdentifierTable()
A (possibly-)qualified type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Scope - A scope is a transient data structure that is used while parsing the program.
unsigned getDepth() const
Returns the depth of this scope. The translation-unit has scope depth 0.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
std::optional< uint64_t > ComputeExpansionSize(CXXExpansionStmtPattern *Expansion)
ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp=false)
Unary Operators. 'Tok' is the token for the operator.
@ LookupMemberName
Member name lookup, which finds the names of class/struct/union members.
StmtResult BuildCXXForRangeRangeVar(Scope *S, Expr *Range, QualType Type, bool IsConstexpr=false)
Build the range variable of a range-based for loop or iterating expansion statement and return its De...
Preprocessor & getPreprocessor() const
void AddArgumentDependentLookupCandidates(DeclarationName Name, SourceLocation Loc, ArrayRef< Expr * > Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading=false)
Add function candidates found via argument-dependent lookup to the set of overloading candidates.
StmtResult BuildNonEnumeratingCXXExpansionStmtPattern(CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVarStmt, Expr *ExpansionInitializer, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps={})
StmtResult SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs)
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
StmtResult ActOnCXXExpansionStmtPattern(CXXExpansionStmtDecl *ESD, Stmt *Init, Stmt *ExpansionVarStmt, Expr *ExpansionInitializer, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps)
bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC)
If the given type contains an unexpanded parameter pack, diagnose the error.
void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse)
Perform marking for a reference to an arbitrary declaration.
StmtResult BuildCXXEnumeratingExpansionStmtPattern(Decl *ESD, Stmt *Init, Stmt *ExpansionVar, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation RParenLoc)
ExprResult ActOnCXXExpansionInitList(MultiExprArg SubExprs, SourceLocation LBraceLoc, SourceLocation RBraceLoc)
QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)
Build a reference type.
void ApplyForRangeOrExpansionStatementLifetimeExtension(VarDecl *RangeVar, ArrayRef< MaterializeTemporaryExpr * > Temporaries)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
QualType getDecltypeForExpr(Expr *E)
getDecltypeForExpr - Given an expr, will return the decltype for that expression, according to the ru...
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
CXXExpansionStmtDecl * ActOnCXXExpansionStmtDecl(unsigned TemplateDepth, SourceLocation TemplateKWLoc)
void ActOnInitializerError(Decl *Dcl)
ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...
CXXExpansionStmtDecl * BuildCXXExpansionStmtDecl(DeclContext *Ctx, SourceLocation TemplateKWLoc, NonTypeTemplateParmDecl *NTTP)
VarDecl * BuildForRangeVarDecl(SourceLocation Loc, QualType Type, IdentifierInfo *Name, bool IsConstexpr)
Helper used by the expansion statements and for-range code to build a variable declaration for e....
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ ImmediateFunctionContext
In addition of being constant evaluated, the current expression occurs in an immediate function conte...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx)
StmtResult FinishCXXExpansionStmt(Stmt *Expansion, Stmt *Body)
@ BFRK_Build
Initial building of a for-range statement.
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)
UnsignedOrNone GetDecompositionElementCount(QualType DecompType, SourceLocation Loc)
void ActOnDependentForRangeInitializer(VarDecl *LoopVar, BuildForRangeKind BFRK)
Set the type of a for-range declaration whose for-range or expansion initialiser is dependent.
ForRangeBeginEndInfo BuildCXXForRangeBeginEndVars(Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc, SourceLocation CoawaitLoc, ArrayRef< MaterializeTemporaryExpr * > LifetimeExtendTemps, BuildForRangeKind Kind, bool IsConstexpr, StmtResult *RebuildResult=nullptr, llvm::function_ref< StmtResult()> RebuildWithDereference={}, IdentifierInfo *BeginName=nullptr, IdentifierInfo *EndName=nullptr)
Determine begin-expr and end-expr and build variable declarations for them as per [stmt....
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a template argument.
A container of type source information.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isVariableArrayType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
const Expr * getInit() const
The JSON file list parser is used to communicate input to InstallAPI.
@ OR_No_Viable_Function
No viable function found.
@ DecltypeAuto
decltype(auto)
MutableArrayRef< Expr * > MultiExprArg
@ Result
The result type of a method or function.
OptionalUnsigned< unsigned > UnsignedOrNone
@ Undeduced
Not deduced yet. This is for example an 'auto' which was just parsed.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
ActionResult< Stmt * > StmtResult
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
DeclarationName getName() const
getName - Returns the embedded declaration name.
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Holds the 'begin' and 'end' variables of a range-based for loop or expansion statement; begin-expr an...
A stack object to be created when performing template instantiation.