mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 05:26:07 +00:00
Add two new AST nodes to represent initialization of an array in terms of
initialization of each array element: * ArrayInitLoopExpr is a prvalue of array type with two subexpressions: a common expression (an OpaqueValueExpr) that represents the up-front computation of the source of the initialization, and a subexpression representing a per-element initializer * ArrayInitIndexExpr is a prvalue of type size_t representing the current position in the loop This will be used to replace the creation of explicit index variables in lambda capture of arrays and copy/move construction of classes with array elements, and also C++17 structured bindings of arrays by value (which inexplicably allow copying an array by value, unlike all of C++'s other array declarations). No uses of these nodes are introduced by this change, however. llvm-svn: 289413
This commit is contained in:
parent
8c9cc8c86b
commit
410306bf6e
@ -4333,6 +4333,98 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a loop initializing the elements of an array.
|
||||
///
|
||||
/// The need to initialize the elements of an array occurs in a number of
|
||||
/// contexts:
|
||||
///
|
||||
/// * in the implicit copy/move constructor for a class with an array member
|
||||
/// * when a lambda-expression captures an array by value
|
||||
/// * when a decomposition declaration decomposes an array
|
||||
///
|
||||
/// There are two subexpressions: a common expression (the source array)
|
||||
/// that is evaluated once up-front, and a per-element initializer that
|
||||
/// runs once for each array element.
|
||||
///
|
||||
/// Within the per-element initializer, the common expression may be referenced
|
||||
/// via an OpaqueValueExpr, and the current index may be obtained via an
|
||||
/// ArrayInitIndexExpr.
|
||||
class ArrayInitLoopExpr : public Expr {
|
||||
Stmt *SubExprs[2];
|
||||
|
||||
explicit ArrayInitLoopExpr(EmptyShell Empty)
|
||||
: Expr(ArrayInitLoopExprClass, Empty), SubExprs{} {}
|
||||
|
||||
public:
|
||||
explicit ArrayInitLoopExpr(QualType T, Expr *CommonInit, Expr *ElementInit)
|
||||
: Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary, false,
|
||||
CommonInit->isValueDependent() || ElementInit->isValueDependent(),
|
||||
T->isInstantiationDependentType(),
|
||||
CommonInit->containsUnexpandedParameterPack() ||
|
||||
ElementInit->containsUnexpandedParameterPack()),
|
||||
SubExprs{CommonInit, ElementInit} {}
|
||||
|
||||
/// Get the common subexpression shared by all initializations (the source
|
||||
/// array).
|
||||
OpaqueValueExpr *getCommonExpr() const {
|
||||
return cast<OpaqueValueExpr>(SubExprs[0]);
|
||||
}
|
||||
|
||||
/// Get the initializer to use for each array element.
|
||||
Expr *getSubExpr() const { return cast<Expr>(SubExprs[1]); }
|
||||
|
||||
llvm::APInt getArraySize() const {
|
||||
return cast<ConstantArrayType>(getType()->castAsArrayTypeUnsafe())
|
||||
->getSize();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *S) {
|
||||
return S->getStmtClass() == ArrayInitLoopExprClass;
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY {
|
||||
return getCommonExpr()->getLocStart();
|
||||
}
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getCommonExpr()->getLocEnd();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(SubExprs, SubExprs + 2);
|
||||
}
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
};
|
||||
|
||||
/// \brief Represents the index of the current element of an array being
|
||||
/// initialized by an ArrayInitLoopExpr. This can only appear within the
|
||||
/// subexpression of an ArrayInitLoopExpr.
|
||||
class ArrayInitIndexExpr : public Expr {
|
||||
explicit ArrayInitIndexExpr(EmptyShell Empty)
|
||||
: Expr(ArrayInitIndexExprClass, Empty) {}
|
||||
|
||||
public:
|
||||
explicit ArrayInitIndexExpr(QualType T)
|
||||
: Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary,
|
||||
false, false, false, false) {}
|
||||
|
||||
static bool classof(const Stmt *S) {
|
||||
return S->getStmtClass() == ArrayInitIndexExprClass;
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
};
|
||||
|
||||
/// \brief Represents an implicitly-generated value initialization of
|
||||
/// an object of a given type.
|
||||
///
|
||||
|
@ -2399,6 +2399,8 @@ DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
|
||||
DEF_TRAVERSE_STMT(GNUNullExpr, {})
|
||||
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(NoInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(ArrayInitLoopExpr, {})
|
||||
DEF_TRAVERSE_STMT(ArrayInitIndexExpr, {})
|
||||
DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
|
||||
|
||||
DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
|
||||
|
@ -85,6 +85,8 @@ def DesignatedInitExpr : DStmt<Expr>;
|
||||
def DesignatedInitUpdateExpr : DStmt<Expr>;
|
||||
def ImplicitValueInitExpr : DStmt<Expr>;
|
||||
def NoInitExpr : DStmt<Expr>;
|
||||
def ArrayInitLoopExpr : DStmt<Expr>;
|
||||
def ArrayInitIndexExpr : DStmt<Expr>;
|
||||
def ParenListExpr : DStmt<Expr>;
|
||||
def VAArgExpr : DStmt<Expr>;
|
||||
def GenericSelectionExpr : DStmt<Expr>;
|
||||
|
@ -120,6 +120,16 @@ private:
|
||||
bool NRVO;
|
||||
};
|
||||
|
||||
struct VD {
|
||||
/// \brief The VarDecl, FieldDecl, or BindingDecl being initialized.
|
||||
ValueDecl *VariableOrMember;
|
||||
|
||||
/// \brief When Kind == EK_Member, whether this is an implicit member
|
||||
/// initialization in a copy or move constructor. These can perform array
|
||||
/// copies.
|
||||
bool IsImplicitFieldInit;
|
||||
};
|
||||
|
||||
struct C {
|
||||
/// \brief The name of the variable being captured by an EK_LambdaCapture.
|
||||
IdentifierInfo *VarID;
|
||||
@ -129,9 +139,8 @@ private:
|
||||
};
|
||||
|
||||
union {
|
||||
/// \brief When Kind == EK_Variable, EK_Member or EK_Binding, the VarDecl,
|
||||
/// FieldDecl or BindingDecl, respectively.
|
||||
ValueDecl *VariableOrMember;
|
||||
/// \brief When Kind == EK_Variable, EK_Member or EK_Binding, the variable.
|
||||
VD Variable;
|
||||
|
||||
/// \brief When Kind == EK_RelatedResult, the ObjectiveC method where
|
||||
/// result type was implicitly changed to accommodate ARC semantics.
|
||||
@ -165,7 +174,7 @@ private:
|
||||
/// \brief Create the initialization entity for a variable.
|
||||
InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
|
||||
: Kind(EK), Parent(nullptr), Type(Var->getType()),
|
||||
ManglingNumber(0), VariableOrMember(Var) { }
|
||||
ManglingNumber(0), Variable{Var, false} { }
|
||||
|
||||
/// \brief Create the initialization entity for the result of a
|
||||
/// function, throwing an object, performing an explicit cast, or
|
||||
@ -179,9 +188,11 @@ private:
|
||||
}
|
||||
|
||||
/// \brief Create the initialization entity for a member subobject.
|
||||
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
|
||||
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
|
||||
bool Implicit)
|
||||
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),
|
||||
ManglingNumber(0), VariableOrMember(Member) { }
|
||||
ManglingNumber(0), Variable{Member, Implicit} {
|
||||
}
|
||||
|
||||
/// \brief Create the initialization entity for an array element.
|
||||
InitializedEntity(ASTContext &Context, unsigned Index,
|
||||
@ -299,15 +310,17 @@ public:
|
||||
/// \brief Create the initialization entity for a member subobject.
|
||||
static InitializedEntity
|
||||
InitializeMember(FieldDecl *Member,
|
||||
const InitializedEntity *Parent = nullptr) {
|
||||
return InitializedEntity(Member, Parent);
|
||||
const InitializedEntity *Parent = nullptr,
|
||||
bool Implicit = false) {
|
||||
return InitializedEntity(Member, Parent, Implicit);
|
||||
}
|
||||
|
||||
/// \brief Create the initialization entity for a member subobject.
|
||||
static InitializedEntity
|
||||
InitializeMember(IndirectFieldDecl *Member,
|
||||
const InitializedEntity *Parent = nullptr) {
|
||||
return InitializedEntity(Member->getAnonField(), Parent);
|
||||
const InitializedEntity *Parent = nullptr,
|
||||
bool Implicit = false) {
|
||||
return InitializedEntity(Member->getAnonField(), Parent, Implicit);
|
||||
}
|
||||
|
||||
/// \brief Create the initialization entity for an array element.
|
||||
@ -401,6 +414,12 @@ public:
|
||||
getType()->getAsArrayTypeUnsafe());
|
||||
}
|
||||
|
||||
/// \brief Is this the implicit initialization of a member of a class from
|
||||
/// a defaulted constructor?
|
||||
bool isImplicitMemberInitializer() const {
|
||||
return getKind() == EK_Member && Variable.IsImplicitFieldInit;
|
||||
}
|
||||
|
||||
/// \brief Determine the location of the 'return' keyword when initializing
|
||||
/// the result of a function call.
|
||||
SourceLocation getReturnLoc() const {
|
||||
@ -708,6 +727,10 @@ public:
|
||||
/// \brief An initialization that "converts" an Objective-C object
|
||||
/// (not a point to an object) to another Objective-C object type.
|
||||
SK_ObjCObjectConversion,
|
||||
/// \brief Array indexing for initialization by elementwise copy.
|
||||
SK_ArrayLoopIndex,
|
||||
/// \brief Array initialization by elementwise copy.
|
||||
SK_ArrayLoopInit,
|
||||
/// \brief Array initialization (from an array rvalue).
|
||||
/// This is a GNU C extension.
|
||||
SK_ArrayInit,
|
||||
@ -1096,6 +1119,9 @@ public:
|
||||
/// always a no-op.
|
||||
void AddObjCObjectConversionStep(QualType T);
|
||||
|
||||
/// \brief Add an array initialization loop step.
|
||||
void AddArrayInitLoopStep(QualType T, QualType EltTy);
|
||||
|
||||
/// \brief Add an array initialization step.
|
||||
void AddArrayInitStep(QualType T);
|
||||
|
||||
|
@ -1292,10 +1292,14 @@ namespace clang {
|
||||
EXPR_DESIGNATED_INIT,
|
||||
/// \brief A DesignatedInitUpdateExpr record.
|
||||
EXPR_DESIGNATED_INIT_UPDATE,
|
||||
/// \brief An ImplicitValueInitExpr record.
|
||||
EXPR_IMPLICIT_VALUE_INIT,
|
||||
/// \brief An NoInitExpr record.
|
||||
EXPR_NO_INIT,
|
||||
/// \brief An ArrayInitLoopExpr record.
|
||||
EXPR_ARRAY_INIT_LOOP,
|
||||
/// \brief An ArrayInitIndexExpr record.
|
||||
EXPR_ARRAY_INIT_INDEX,
|
||||
/// \brief An ImplicitValueInitExpr record.
|
||||
EXPR_IMPLICIT_VALUE_INIT,
|
||||
/// \brief A VAArgExpr record.
|
||||
EXPR_VA_ARG,
|
||||
/// \brief An AddrLabelExpr record.
|
||||
|
@ -517,6 +517,8 @@ namespace {
|
||||
void VisitFloatingLiteral(const FloatingLiteral *Node);
|
||||
void VisitStringLiteral(const StringLiteral *Str);
|
||||
void VisitInitListExpr(const InitListExpr *ILE);
|
||||
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE);
|
||||
void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE);
|
||||
void VisitUnaryOperator(const UnaryOperator *Node);
|
||||
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
|
||||
void VisitMemberExpr(const MemberExpr *Node);
|
||||
@ -2024,6 +2026,14 @@ void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
|
||||
}
|
||||
}
|
||||
|
||||
void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
||||
void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
||||
void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
|
||||
VisitExpr(Node);
|
||||
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
|
||||
|
@ -2899,6 +2899,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
|
||||
case UnaryExprOrTypeTraitExprClass:
|
||||
case AddrLabelExprClass:
|
||||
case GNUNullExprClass:
|
||||
case ArrayInitIndexExprClass:
|
||||
case NoInitExprClass:
|
||||
case CXXBoolLiteralExprClass:
|
||||
case CXXNullPtrLiteralExprClass:
|
||||
@ -2975,6 +2976,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
|
||||
case ExtVectorElementExprClass:
|
||||
case DesignatedInitExprClass:
|
||||
case DesignatedInitUpdateExprClass:
|
||||
case ArrayInitLoopExprClass:
|
||||
case ParenListExprClass:
|
||||
case CXXPseudoDestructorExprClass:
|
||||
case CXXStdInitializerListExprClass:
|
||||
|
@ -185,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
||||
case Expr::ObjCIndirectCopyRestoreExprClass:
|
||||
case Expr::AtomicExprClass:
|
||||
case Expr::CXXFoldExprClass:
|
||||
case Expr::ArrayInitLoopExprClass:
|
||||
case Expr::ArrayInitIndexExprClass:
|
||||
case Expr::NoInitExprClass:
|
||||
case Expr::DesignatedInitUpdateExprClass:
|
||||
case Expr::CoyieldExprClass:
|
||||
|
@ -469,6 +469,10 @@ namespace {
|
||||
/// declaration whose initializer is being evaluated, if any.
|
||||
APValue *EvaluatingDeclValue;
|
||||
|
||||
/// The current array initialization index, if we're performing array
|
||||
/// initialization.
|
||||
uint64_t ArrayInitIndex = -1;
|
||||
|
||||
/// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further
|
||||
/// notes attached to it will also be stored, otherwise they will not be.
|
||||
bool HasActiveDiagnostic;
|
||||
@ -803,6 +807,20 @@ namespace {
|
||||
bool allowInvalidBaseExpr() const {
|
||||
return EvalMode == EM_DesignatorFold;
|
||||
}
|
||||
|
||||
class ArrayInitLoopIndex {
|
||||
EvalInfo &Info;
|
||||
uint64_t OuterIndex;
|
||||
|
||||
public:
|
||||
ArrayInitLoopIndex(EvalInfo &Info)
|
||||
: Info(Info), OuterIndex(Info.ArrayInitIndex) {
|
||||
Info.ArrayInitIndex = 0;
|
||||
}
|
||||
~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; }
|
||||
|
||||
operator uint64_t&() { return Info.ArrayInitIndex; }
|
||||
};
|
||||
};
|
||||
|
||||
/// Object used to treat all foldable expressions as constant expressions.
|
||||
@ -6190,6 +6208,7 @@ namespace {
|
||||
return handleCallExpr(E, Result, &This);
|
||||
}
|
||||
bool VisitInitListExpr(const InitListExpr *E);
|
||||
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
|
||||
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
|
||||
bool VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||
const LValue &Subobject,
|
||||
@ -6272,6 +6291,35 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
|
||||
FillerExpr) && Success;
|
||||
}
|
||||
|
||||
bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
|
||||
if (E->getCommonExpr() &&
|
||||
!Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false),
|
||||
Info, E->getCommonExpr()->getSourceExpr()))
|
||||
return false;
|
||||
|
||||
auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
|
||||
|
||||
uint64_t Elements = CAT->getSize().getZExtValue();
|
||||
Result = APValue(APValue::UninitArray(), Elements, Elements);
|
||||
|
||||
LValue Subobject = This;
|
||||
Subobject.addArray(Info, E, CAT);
|
||||
|
||||
bool Success = true;
|
||||
for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) {
|
||||
if (!EvaluateInPlace(Result.getArrayInitializedElt(Index),
|
||||
Info, Subobject, E->getSubExpr()) ||
|
||||
!HandleLValueArrayAdjustment(Info, E, Subobject,
|
||||
CAT->getElementType(), 1)) {
|
||||
if (!Info.noteFailure())
|
||||
return false;
|
||||
Success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
|
||||
return VisitCXXConstructExpr(E, This, &Result, E->getType());
|
||||
}
|
||||
@ -6427,6 +6475,16 @@ public:
|
||||
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
|
||||
return Success(E->getValue(), E);
|
||||
}
|
||||
|
||||
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
|
||||
if (Info.ArrayInitIndex == uint64_t(-1)) {
|
||||
// We were asked to evaluate this subexpression independent of the
|
||||
// enclosing ArrayInitLoopExpr. We can't do that.
|
||||
Info.FFDiag(E);
|
||||
return false;
|
||||
}
|
||||
return Success(Info.ArrayInitIndex, E);
|
||||
}
|
||||
|
||||
// Note, GNU defines __null as an integer, not a pointer.
|
||||
bool VisitGNUNullExpr(const GNUNullExpr *E) {
|
||||
@ -9590,6 +9648,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
|
||||
case Expr::CompoundLiteralExprClass:
|
||||
case Expr::ExtVectorElementExprClass:
|
||||
case Expr::DesignatedInitExprClass:
|
||||
case Expr::ArrayInitLoopExprClass:
|
||||
case Expr::ArrayInitIndexExprClass:
|
||||
case Expr::NoInitExprClass:
|
||||
case Expr::DesignatedInitUpdateExprClass:
|
||||
case Expr::ImplicitValueInitExprClass:
|
||||
|
@ -3301,6 +3301,8 @@ recurse:
|
||||
case Expr::AddrLabelExprClass:
|
||||
case Expr::DesignatedInitUpdateExprClass:
|
||||
case Expr::ImplicitValueInitExprClass:
|
||||
case Expr::ArrayInitLoopExprClass:
|
||||
case Expr::ArrayInitIndexExprClass:
|
||||
case Expr::NoInitExprClass:
|
||||
case Expr::ParenListExprClass:
|
||||
case Expr::LambdaExprClass:
|
||||
|
@ -1705,6 +1705,18 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
|
||||
// There's no way to express this expression in any of our supported
|
||||
// languages, so just emit something terse and (hopefully) clear.
|
||||
OS << "{";
|
||||
PrintExpr(Node->getSubExpr());
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
|
||||
OS << "*";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
|
||||
OS << "(";
|
||||
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
|
||||
|
@ -972,6 +972,14 @@ void StmtProfiler::VisitDesignatedInitUpdateExpr(
|
||||
"initializer");
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *S) {
|
||||
VisitExpr(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *S) {
|
||||
VisitExpr(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) {
|
||||
llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer");
|
||||
}
|
||||
|
@ -164,6 +164,7 @@ public:
|
||||
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
|
||||
void VisitChooseExpr(const ChooseExpr *CE);
|
||||
void VisitInitListExpr(InitListExpr *E);
|
||||
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
|
||||
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
|
||||
void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
|
||||
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
|
||||
@ -1308,6 +1309,85 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
||||
cleanupDominator->eraseFromParent();
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
|
||||
// Emit the common subexpression.
|
||||
CodeGenFunction::OpaqueValueMapping binding(CGF, E->getCommonExpr());
|
||||
|
||||
Address destPtr = EnsureSlot(E->getType()).getAddress();
|
||||
uint64_t numElements = E->getArraySize().getZExtValue();
|
||||
|
||||
if (!numElements)
|
||||
return;
|
||||
|
||||
// FIXME: Dig through nested ArrayInitLoopExprs to find the overall array
|
||||
// size, and only emit a single loop for a multidimensional array.
|
||||
|
||||
// destPtr is an array*. Construct an elementType* by drilling down a level.
|
||||
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
|
||||
llvm::Value *indices[] = {zero, zero};
|
||||
llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices,
|
||||
"arrayinit.begin");
|
||||
|
||||
QualType elementType = E->getSubExpr()->getType();
|
||||
CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
|
||||
CharUnits elementAlign =
|
||||
destPtr.getAlignment().alignmentOfArrayElement(elementSize);
|
||||
|
||||
// Prepare for a cleanup.
|
||||
QualType::DestructionKind dtorKind = elementType.isDestructedType();
|
||||
Address endOfInit = Address::invalid();
|
||||
EHScopeStack::stable_iterator cleanup;
|
||||
llvm::Instruction *cleanupDominator = nullptr;
|
||||
if (CGF.needsEHCleanup(dtorKind)) {
|
||||
endOfInit = CGF.CreateTempAlloca(begin->getType(), CGF.getPointerAlign(),
|
||||
"arrayinit.endOfInit");
|
||||
CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
|
||||
elementAlign,
|
||||
CGF.getDestroyer(dtorKind));
|
||||
cleanup = CGF.EHStack.stable_begin();
|
||||
} else {
|
||||
dtorKind = QualType::DK_none;
|
||||
}
|
||||
|
||||
llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
|
||||
llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body");
|
||||
|
||||
// Jump into the body.
|
||||
CGF.EmitBlock(bodyBB);
|
||||
llvm::PHINode *index =
|
||||
Builder.CreatePHI(zero->getType(), 2, "arrayinit.index");
|
||||
index->addIncoming(zero, entryBB);
|
||||
llvm::Value *element = Builder.CreateInBoundsGEP(begin, index);
|
||||
|
||||
// Tell the EH cleanup that we finished with the last element.
|
||||
if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
|
||||
|
||||
// Emit the actual filler expression.
|
||||
{
|
||||
CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index);
|
||||
LValue elementLV =
|
||||
CGF.MakeAddrLValue(Address(element, elementAlign), elementType);
|
||||
EmitInitializationToLValue(E->getSubExpr(), elementLV);
|
||||
}
|
||||
|
||||
// Move on to the next element.
|
||||
llvm::Value *nextIndex = Builder.CreateNUWAdd(
|
||||
index, llvm::ConstantInt::get(CGF.SizeTy, 1), "arrayinit.next");
|
||||
index->addIncoming(nextIndex, Builder.GetInsertBlock());
|
||||
|
||||
// Leave the loop if we're done.
|
||||
llvm::Value *done = Builder.CreateICmpEQ(
|
||||
nextIndex, llvm::ConstantInt::get(CGF.SizeTy, numElements),
|
||||
"arrayinit.done");
|
||||
llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end");
|
||||
Builder.CreateCondBr(done, endBB, bodyBB);
|
||||
|
||||
CGF.EmitBlock(endBB);
|
||||
|
||||
// Leave the partial-array cleanup if we entered one.
|
||||
if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator);
|
||||
}
|
||||
|
||||
void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
|
||||
AggValueSlot Dest = EnsureSlot(E->getType());
|
||||
|
||||
|
@ -311,6 +311,12 @@ public:
|
||||
|
||||
Value *VisitInitListExpr(InitListExpr *E);
|
||||
|
||||
Value *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
|
||||
assert(CGF.getArrayInitIndex() &&
|
||||
"ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
|
||||
return CGF.getArrayInitIndex();
|
||||
}
|
||||
|
||||
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
|
||||
return EmitNullValue(E->getType());
|
||||
}
|
||||
|
@ -918,6 +918,17 @@ public:
|
||||
e->getCommon());
|
||||
}
|
||||
|
||||
/// Build the opaque value mapping for an OpaqueValueExpr whose source
|
||||
/// expression is set to the expression the OVE represents.
|
||||
OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *OV)
|
||||
: CGF(CGF) {
|
||||
if (OV) {
|
||||
assert(OV->getSourceExpr() && "wrong form of OpaqueValueMapping used "
|
||||
"for OVE with no source expression");
|
||||
Data = OpaqueValueMappingData::bind(CGF, OV, OV->getSourceExpr());
|
||||
}
|
||||
}
|
||||
|
||||
OpaqueValueMapping(CodeGenFunction &CGF,
|
||||
const OpaqueValueExpr *opaqueValue,
|
||||
LValue lvalue)
|
||||
@ -1183,6 +1194,23 @@ public:
|
||||
CharUnits OldCXXThisAlignment;
|
||||
};
|
||||
|
||||
/// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
|
||||
/// current loop index is overridden.
|
||||
class ArrayInitLoopExprScope {
|
||||
public:
|
||||
ArrayInitLoopExprScope(CodeGenFunction &CGF, llvm::Value *Index)
|
||||
: CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) {
|
||||
CGF.ArrayInitIndex = Index;
|
||||
}
|
||||
~ArrayInitLoopExprScope() {
|
||||
CGF.ArrayInitIndex = OldArrayInitIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
CodeGenFunction &CGF;
|
||||
llvm::Value *OldArrayInitIndex;
|
||||
};
|
||||
|
||||
class InlinedInheritingConstructorScope {
|
||||
public:
|
||||
InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl GD)
|
||||
@ -1251,6 +1279,10 @@ private:
|
||||
/// this expression.
|
||||
Address CXXDefaultInitExprThis = Address::invalid();
|
||||
|
||||
/// The current array initialization index when evaluating an
|
||||
/// ArrayInitIndexExpr within an ArrayInitLoopExpr.
|
||||
llvm::Value *ArrayInitIndex = nullptr;
|
||||
|
||||
/// The values of function arguments to use when evaluating
|
||||
/// CXXInheritedCtorInitExprs within this context.
|
||||
CallArgList CXXInheritedCtorInitExprArgs;
|
||||
@ -1953,6 +1985,9 @@ public:
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// Get the index of the current ArrayInitLoopExpr, if any.
|
||||
llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
|
||||
|
||||
/// getAccessedFieldNo - Given an encoded value and a result number, return
|
||||
/// the input field number being accessed.
|
||||
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
|
||||
|
@ -1166,6 +1166,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
|
||||
case Expr::ExprWithCleanupsClass:
|
||||
case Expr::ExtVectorElementExprClass:
|
||||
case Expr::InitListExprClass:
|
||||
case Expr::ArrayInitLoopExprClass:
|
||||
case Expr::MemberExprClass:
|
||||
case Expr::ObjCIsaExprClass:
|
||||
case Expr::ObjCIvarRefExprClass:
|
||||
@ -1259,6 +1260,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
|
||||
case Expr::ImaginaryLiteralClass:
|
||||
case Expr::ImplicitValueInitExprClass:
|
||||
case Expr::IntegerLiteralClass:
|
||||
case Expr::ArrayInitIndexExprClass:
|
||||
case Expr::NoInitExprClass:
|
||||
case Expr::ObjCEncodeExprClass:
|
||||
case Expr::ObjCStringLiteralClass:
|
||||
|
@ -2910,7 +2910,7 @@ DeclarationName InitializedEntity::getName() const {
|
||||
case EK_Variable:
|
||||
case EK_Member:
|
||||
case EK_Binding:
|
||||
return VariableOrMember->getDeclName();
|
||||
return Variable.VariableOrMember->getDeclName();
|
||||
|
||||
case EK_LambdaCapture:
|
||||
return DeclarationName(Capture.VarID);
|
||||
@ -2938,7 +2938,7 @@ ValueDecl *InitializedEntity::getDecl() const {
|
||||
case EK_Variable:
|
||||
case EK_Member:
|
||||
case EK_Binding:
|
||||
return VariableOrMember;
|
||||
return Variable.VariableOrMember;
|
||||
|
||||
case EK_Parameter:
|
||||
case EK_Parameter_CF_Audited:
|
||||
@ -3065,6 +3065,8 @@ void InitializationSequence::Step::Destroy() {
|
||||
case SK_CAssignment:
|
||||
case SK_StringInit:
|
||||
case SK_ObjCObjectConversion:
|
||||
case SK_ArrayLoopIndex:
|
||||
case SK_ArrayLoopInit:
|
||||
case SK_ArrayInit:
|
||||
case SK_ParenthesizedArrayInit:
|
||||
case SK_PassByIndirectCopyRestore:
|
||||
@ -3307,6 +3309,17 @@ void InitializationSequence::AddArrayInitStep(QualType T) {
|
||||
Steps.push_back(S);
|
||||
}
|
||||
|
||||
void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) {
|
||||
Step S;
|
||||
S.Kind = SK_ArrayLoopIndex;
|
||||
S.Type = EltT;
|
||||
Steps.insert(Steps.begin(), S);
|
||||
|
||||
S.Kind = SK_ArrayLoopInit;
|
||||
S.Type = T;
|
||||
Steps.push_back(S);
|
||||
}
|
||||
|
||||
void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) {
|
||||
Step S;
|
||||
S.Kind = SK_ParenthesizedArrayInit;
|
||||
@ -3552,6 +3565,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
|
||||
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
|
||||
/// enumerates the constructors of the initialized entity and performs overload
|
||||
/// resolution to select the best.
|
||||
/// \param DestType The destination class type.
|
||||
/// \param DestArrayType The destination type, which is either DestType or
|
||||
/// a (possibly multidimensional) array of DestType.
|
||||
/// \param IsListInit Is this list-initialization?
|
||||
/// \param IsInitListCopy Is this non-list-initialization resulting from a
|
||||
/// list-initialization from {x} where x is the same
|
||||
@ -3560,6 +3576,7 @@ static void TryConstructorInitialization(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
MultiExprArg Args, QualType DestType,
|
||||
QualType DestArrayType,
|
||||
InitializationSequence &Sequence,
|
||||
bool IsListInit = false,
|
||||
bool IsInitListCopy = false) {
|
||||
@ -3703,7 +3720,7 @@ static void TryConstructorInitialization(Sema &S,
|
||||
// subsumed by the initialization.
|
||||
bool HadMultipleCandidates = (CandidateSet.size() > 1);
|
||||
Sequence.AddConstructorInitializationStep(
|
||||
Best->FoundDecl, CtorDecl, DestType, HadMultipleCandidates,
|
||||
Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates,
|
||||
IsListInit | IsInitListCopy, AsInitializerList);
|
||||
}
|
||||
|
||||
@ -3871,8 +3888,9 @@ static void TryListInitialization(Sema &S,
|
||||
S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
|
||||
Expr *InitListAsExpr = InitList;
|
||||
TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
|
||||
Sequence, /*InitListSyntax*/ false,
|
||||
/*IsInitListCopy*/ true);
|
||||
DestType, Sequence,
|
||||
/*InitListSyntax*/false,
|
||||
/*IsInitListCopy*/true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3927,7 +3945,7 @@ static void TryListInitialization(Sema &S,
|
||||
// - Otherwise, if T is a class type, constructors are considered.
|
||||
Expr *InitListAsExpr = InitList;
|
||||
TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
|
||||
Sequence, /*InitListSyntax*/ true);
|
||||
DestType, Sequence, /*InitListSyntax*/true);
|
||||
} else
|
||||
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
|
||||
return;
|
||||
@ -4580,8 +4598,10 @@ static void TryValueInitialization(Sema &S,
|
||||
MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0);
|
||||
bool InitListSyntax = InitList;
|
||||
|
||||
return TryConstructorInitialization(S, Entity, Kind, Args, T, Sequence,
|
||||
InitListSyntax);
|
||||
// FIXME: Instead of creating a CXXConstructExpr of non-array type here,
|
||||
// wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr.
|
||||
return TryConstructorInitialization(
|
||||
S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4604,7 +4624,8 @@ static void TryDefaultInitialization(Sema &S,
|
||||
// constructor for T is called (and the initialization is ill-formed if
|
||||
// T has no accessible default constructor);
|
||||
if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) {
|
||||
TryConstructorInitialization(S, Entity, Kind, None, DestType, Sequence);
|
||||
TryConstructorInitialization(S, Entity, Kind, None, DestType,
|
||||
Entity.getType(), Sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5030,6 +5051,42 @@ static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) {
|
||||
cast<FunctionDecl>(DRE->getDecl()));
|
||||
}
|
||||
|
||||
/// Determine whether we can perform an elementwise array copy for this kind
|
||||
/// of entity.
|
||||
static bool canPerformArrayCopy(const InitializedEntity &Entity) {
|
||||
switch (Entity.getKind()) {
|
||||
case InitializedEntity::EK_LambdaCapture:
|
||||
// C++ [expr.prim.lambda]p24:
|
||||
// For array members, the array elements are direct-initialized in
|
||||
// increasing subscript order.
|
||||
return true;
|
||||
|
||||
case InitializedEntity::EK_Variable:
|
||||
// C++ [dcl.decomp]p1:
|
||||
// [...] each element is copy-initialized or direct-initialized from the
|
||||
// corresponding element of the assignment-expression [...]
|
||||
return isa<DecompositionDecl>(Entity.getDecl());
|
||||
|
||||
case InitializedEntity::EK_Member:
|
||||
// C++ [class.copy.ctor]p14:
|
||||
// - if the member is an array, each element is direct-initialized with
|
||||
// the corresponding subobject of x
|
||||
return Entity.isImplicitMemberInitializer();
|
||||
|
||||
case InitializedEntity::EK_ArrayElement:
|
||||
// All the above cases are intended to apply recursively, even though none
|
||||
// of them actually say that.
|
||||
if (auto *E = Entity.getParent())
|
||||
return canPerformArrayCopy(*E);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitializationSequence::InitializeFrom(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
@ -5152,6 +5209,34 @@ void InitializationSequence::InitializeFrom(Sema &S,
|
||||
}
|
||||
}
|
||||
|
||||
// Some kinds of initialization permit an array to be initialized from
|
||||
// another array of the same type, and perform elementwise initialization.
|
||||
if (Initializer && isa<ConstantArrayType>(DestAT) &&
|
||||
S.Context.hasSameUnqualifiedType(Initializer->getType(),
|
||||
Entity.getType()) &&
|
||||
canPerformArrayCopy(Entity)) {
|
||||
// If source is a prvalue, use it directly.
|
||||
if (Initializer->getValueKind() == VK_RValue) {
|
||||
// FIXME: This produces a bogus extwarn
|
||||
AddArrayInitStep(DestType);
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit element-at-a-time copy loop.
|
||||
InitializedEntity Element =
|
||||
InitializedEntity::InitializeElement(S.Context, 0, Entity);
|
||||
QualType InitEltT =
|
||||
Context.getAsArrayType(Initializer->getType())->getElementType();
|
||||
OpaqueValueExpr OVE(SourceLocation(), InitEltT,
|
||||
Initializer->getValueKind());
|
||||
Expr *OVEAsExpr = &OVE;
|
||||
InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList,
|
||||
TreatUnavailableAsInvalid);
|
||||
if (!Failed())
|
||||
AddArrayInitLoopStep(Entity.getType(), InitEltT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: as an GNU C extension, we allow initialization of an
|
||||
// array from a compound literal that creates an array of the same
|
||||
// type, so long as the initializer has no side effects.
|
||||
@ -5225,7 +5310,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
|
||||
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
|
||||
S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType))))
|
||||
TryConstructorInitialization(S, Entity, Kind, Args,
|
||||
DestType, *this);
|
||||
DestType, DestType, *this);
|
||||
// - Otherwise (i.e., for the remaining copy-initialization cases),
|
||||
// user-defined conversion sequences that can convert from the source
|
||||
// type to the destination type or (when a conversion function is
|
||||
@ -5842,7 +5927,7 @@ PerformConstructorInitialization(Sema &S,
|
||||
// If the entity allows NRVO, mark the construction as elidable
|
||||
// unconditionally.
|
||||
if (Entity.allowsNRVO())
|
||||
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
|
||||
CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
|
||||
Step.Function.FoundDecl,
|
||||
Constructor, /*Elidable=*/true,
|
||||
ConstructorArgs,
|
||||
@ -5853,7 +5938,7 @@ PerformConstructorInitialization(Sema &S,
|
||||
ConstructKind,
|
||||
ParenOrBraceRange);
|
||||
else
|
||||
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
|
||||
CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
|
||||
Step.Function.FoundDecl,
|
||||
Constructor,
|
||||
ConstructorArgs,
|
||||
@ -6403,6 +6488,7 @@ InitializationSequence::Perform(Sema &S,
|
||||
Entity.getType();
|
||||
|
||||
ExprResult CurInit((Expr *)nullptr);
|
||||
SmallVector<Expr*, 4> ArrayLoopCommonExprs;
|
||||
|
||||
// For initialization steps that start with a single initializer,
|
||||
// grab the only argument out the Args and place it into the "current"
|
||||
@ -6430,6 +6516,8 @@ InitializationSequence::Perform(Sema &S,
|
||||
case SK_CAssignment:
|
||||
case SK_StringInit:
|
||||
case SK_ObjCObjectConversion:
|
||||
case SK_ArrayLoopIndex:
|
||||
case SK_ArrayLoopInit:
|
||||
case SK_ArrayInit:
|
||||
case SK_ParenthesizedArrayInit:
|
||||
case SK_PassByIndirectCopyRestore:
|
||||
@ -6813,13 +6901,15 @@ InitializationSequence::Perform(Sema &S,
|
||||
bool UseTemporary = Entity.getType()->isReferenceType();
|
||||
bool IsStdInitListInit =
|
||||
Step->Kind == SK_StdInitializerListConstructorCall;
|
||||
Expr *Source = CurInit.get();
|
||||
CurInit = PerformConstructorInitialization(
|
||||
S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step,
|
||||
S, UseTemporary ? TempEntity : Entity, Kind,
|
||||
Source ? MultiExprArg(Source) : Args, *Step,
|
||||
ConstructorInitRequiresZeroInit,
|
||||
/*IsListInitialization*/IsStdInitListInit,
|
||||
/*IsStdInitListInitialization*/IsStdInitListInit,
|
||||
/*LBraceLoc*/SourceLocation(),
|
||||
/*RBraceLoc*/SourceLocation());
|
||||
/*IsListInitialization*/ IsStdInitListInit,
|
||||
/*IsStdInitListInitialization*/ IsStdInitListInit,
|
||||
/*LBraceLoc*/ SourceLocation(),
|
||||
/*RBraceLoc*/ SourceLocation());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6898,6 +6988,28 @@ InitializationSequence::Perform(Sema &S,
|
||||
CurInit.get()->getValueKind());
|
||||
break;
|
||||
|
||||
case SK_ArrayLoopIndex: {
|
||||
Expr *Cur = CurInit.get();
|
||||
Expr *BaseExpr = new (S.Context)
|
||||
OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
|
||||
Cur->getValueKind(), Cur->getObjectKind(), Cur);
|
||||
Expr *IndexExpr =
|
||||
new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType());
|
||||
CurInit = S.CreateBuiltinArraySubscriptExpr(
|
||||
BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation());
|
||||
ArrayLoopCommonExprs.push_back(BaseExpr);
|
||||
break;
|
||||
}
|
||||
|
||||
case SK_ArrayLoopInit: {
|
||||
assert(!ArrayLoopCommonExprs.empty() &&
|
||||
"mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit");
|
||||
Expr *Common = ArrayLoopCommonExprs.pop_back_val();
|
||||
CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common,
|
||||
CurInit.get());
|
||||
break;
|
||||
}
|
||||
|
||||
case SK_ArrayInit:
|
||||
// Okay: we checked everything before creating this step. Note that
|
||||
// this is a GNU extension.
|
||||
@ -7851,6 +7963,14 @@ void InitializationSequence::dump(raw_ostream &OS) const {
|
||||
OS << "Objective-C object conversion";
|
||||
break;
|
||||
|
||||
case SK_ArrayLoopIndex:
|
||||
OS << "indexing for array initialization loop";
|
||||
break;
|
||||
|
||||
case SK_ArrayLoopInit:
|
||||
OS << "array initialization loop";
|
||||
break;
|
||||
|
||||
case SK_ArrayInit:
|
||||
OS << "array initialization";
|
||||
break;
|
||||
|
@ -3221,6 +3221,9 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
|
||||
if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
|
||||
Init = ExprTemp->getSubExpr();
|
||||
|
||||
if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
|
||||
Init = AIL->getCommonExpr();
|
||||
|
||||
if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
|
||||
Init = MTE->GetTemporaryExpr();
|
||||
|
||||
@ -9045,6 +9048,20 @@ TreeTransform<Derived>::TransformNoInitExpr(
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformArrayInitLoopExpr(ArrayInitLoopExpr *E) {
|
||||
llvm_unreachable("Unexpected ArrayInitLoopExpr outside of initializer");
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformArrayInitIndexExpr(ArrayInitIndexExpr *E) {
|
||||
llvm_unreachable("Unexpected ArrayInitIndexExpr outside of initializer");
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformImplicitValueInitExpr(
|
||||
|
@ -845,6 +845,16 @@ void ASTStmtReader::VisitNoInitExpr(NoInitExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->SubExprs[0] = Reader.ReadSubExpr();
|
||||
E->SubExprs[1] = Reader.ReadSubExpr();
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
|
||||
VisitExpr(E);
|
||||
}
|
||||
@ -3231,6 +3241,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
S = new (Context) NoInitExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_ARRAY_INIT_LOOP:
|
||||
S = new (Context) ArrayInitLoopExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_ARRAY_INIT_INDEX:
|
||||
S = new (Context) ArrayInitIndexExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_VA_ARG:
|
||||
S = new (Context) VAArgExpr(Empty);
|
||||
break;
|
||||
|
@ -792,6 +792,18 @@ void ASTStmtWriter::VisitNoInitExpr(NoInitExpr *E) {
|
||||
Code = serialization::EXPR_NO_INIT;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
|
||||
VisitExpr(E);
|
||||
Record.AddStmt(E->SubExprs[0]);
|
||||
Record.AddStmt(E->SubExprs[1]);
|
||||
Code = serialization::EXPR_ARRAY_INIT_LOOP;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
|
||||
VisitExpr(E);
|
||||
Code = serialization::EXPR_ARRAY_INIT_INDEX;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
|
||||
VisitExpr(E);
|
||||
Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
|
||||
|
@ -905,6 +905,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||
// Cases not handled yet; but will handle some day.
|
||||
case Stmt::DesignatedInitExprClass:
|
||||
case Stmt::DesignatedInitUpdateExprClass:
|
||||
case Stmt::ArrayInitLoopExprClass:
|
||||
case Stmt::ArrayInitIndexExprClass:
|
||||
case Stmt::ExtVectorElementExprClass:
|
||||
case Stmt::ImaginaryLiteralClass:
|
||||
case Stmt::ObjCAtCatchStmtClass:
|
||||
|
@ -243,6 +243,8 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||
case Stmt::ChooseExprClass:
|
||||
case Stmt::DesignatedInitExprClass:
|
||||
case Stmt::DesignatedInitUpdateExprClass:
|
||||
case Stmt::ArrayInitLoopExprClass:
|
||||
case Stmt::ArrayInitIndexExprClass:
|
||||
case Stmt::ExprWithCleanupsClass:
|
||||
case Stmt::ExpressionTraitExprClass:
|
||||
case Stmt::ExtVectorElementExprClass:
|
||||
|
Loading…
x
Reference in New Issue
Block a user