diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-12 02:53:20 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-12 02:53:20 +0000 |
commit | 410306bf6ed906af77978caa199e5d96376bae66 (patch) | |
tree | 811f32246733190c960c7785c3dd02587d43be1d /clang/lib/AST/ExprConstant.cpp | |
parent | 8c9cc8c86be80abd4224341314725d03551460d6 (diff) | |
download | bcm5719-llvm-410306bf6ed906af77978caa199e5d96376bae66.tar.gz bcm5719-llvm-410306bf6ed906af77978caa199e5d96376bae66.zip |
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
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 949ec6382fd..61bb2b9bc91 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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: |