diff options
-rw-r--r-- | clang/include/clang/AST/Expr.h | 3 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 26 |
3 files changed, 34 insertions, 0 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 3a91a707048..9ce86ef12d5 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1757,6 +1757,9 @@ public: InitExprs[Init] = expr; } + /// \brief Reserve space for some number of initializers. + void reserveInits(unsigned NumInits); + /// @brief Specify the number of initializers /// /// If there are more than @p NumInits initializers, the remaining diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index fd1092f64c7..330ba63b589 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -338,6 +338,11 @@ InitListExpr::InitListExpr(SourceLocation lbraceloc, InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits); } +void InitListExpr::reserveInits(unsigned NumInits) { + if (NumInits > InitExprs.size()) + InitExprs.reserve(NumInits); +} + void InitListExpr::resizeInits(ASTContext &Context, unsigned NumInits) { for (unsigned Idx = NumInits, LastIdx = InitExprs.size(); Idx < LastIdx; ++Idx) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 8a5e2c87d34..33641329108 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1450,6 +1450,32 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, Result->setType(CurrentObjectType); + // Pre-allocate storage for the structured initializer list. + unsigned NumElements = 0; + if (const ArrayType *AType + = SemaRef.Context.getAsArrayType(CurrentObjectType)) { + if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) { + NumElements = CAType->getSize().getZExtValue(); + // Simple heuristic so that we don't allocate a very large + // initializer with many empty entries at the end. + if (IList && NumElements > IList->getNumInits()) + NumElements = 0; + } + } else if (const VectorType *VType = CurrentObjectType->getAsVectorType()) + NumElements = VType->getNumElements(); + else if (const RecordType *RType = CurrentObjectType->getAsRecordType()) { + RecordDecl *RDecl = RType->getDecl(); + if (RDecl->isUnion()) + NumElements = 1; + else + NumElements = std::distance(RDecl->field_begin(), RDecl->field_end()); + } + + if (IList && NumElements < IList->getNumInits()) + NumElements = IList->getNumInits(); + + Result->reserveInits(NumElements); + // Link this new initializer list into the structured initializer // lists. if (StructuredList) |