diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-02-19 00:42:33 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-02-19 00:42:33 +0000 |
commit | 9f9269e810bfe9aea0a57b09250be215808fc1a2 (patch) | |
tree | d7cb45bf9e3387ffdacb0a1106cd2ceca04cf454 /lib/AST/Expr.cpp | |
parent | b9c903bc7c11adf86b1f1e68ad35cd49703dc654 (diff) |
Change InitListExpr to allocate the array for holding references
to initializer expressions in an array allocated using ASTContext.
This plugs a memory leak when ASTContext uses a BumpPtrAllocator to
allocate memory for AST nodes.
In my mind this isn't an ideal solution; it would be nice to have
a general "vector"-like class that allocates memory using ASTContext,
but whose guts could be separated from the methods of InitListExpr
itself. I haven't gone and taken this approach yet because it isn't
clear yet if we'll eventually want an alternate solution for recylcing
memory using by InitListExprs as we are constructing the ASTs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96642 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r-- | lib/AST/Expr.cpp | 85 |
1 files changed, 58 insertions, 27 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index fac65064c0..58776f47d9 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -713,40 +713,75 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { return OverOps[Opc]; } -InitListExpr::InitListExpr(SourceLocation lbraceloc, +InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, Expr **initExprs, unsigned numInits, SourceLocation rbraceloc) : Expr(InitListExprClass, QualType(), false, false), + InitExprs(0), NumInits(numInits), Capacity(numInits), LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), - UnionFieldInit(0), HadArrayRangeDesignator(false) -{ - for (unsigned I = 0; I != numInits; ++I) { - if (initExprs[I]->isTypeDependent()) + UnionFieldInit(0), HadArrayRangeDesignator(false) +{ + if (NumInits == 0) + return; + + InitExprs = new (C) Stmt*[Capacity]; + + for (unsigned I = 0; I != NumInits; ++I) { + Expr *Ex = initExprs[I]; + if (Ex->isTypeDependent()) TypeDependent = true; - if (initExprs[I]->isValueDependent()) + if (Ex->isValueDependent()) ValueDependent = true; + InitExprs[I] = Ex; } - - InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits); } -void InitListExpr::reserveInits(unsigned NumInits) { - if (NumInits > InitExprs.size()) - InitExprs.reserve(NumInits); +void InitListExpr::DoDestroy(ASTContext &C) { + DestroyChildren(C); + if (InitExprs) + C.Deallocate(InitExprs); + this->~InitListExpr(); + C.Deallocate((void*) this); } -void InitListExpr::resizeInits(ASTContext &Context, unsigned NumInits) { - for (unsigned Idx = NumInits, LastIdx = InitExprs.size(); - Idx < LastIdx; ++Idx) - InitExprs[Idx]->Destroy(Context); - InitExprs.resize(NumInits, 0); +void InitListExpr::reserveInits(ASTContext &C, unsigned newCapacity) { + if (newCapacity > Capacity) { + if (!Capacity) + Capacity = newCapacity; + else if ((Capacity *= 2) < newCapacity) + Capacity = newCapacity; + + Stmt **newInits = new (C) Stmt*[Capacity]; + if (InitExprs) { + memcpy(newInits, InitExprs, NumInits * sizeof(*InitExprs)); + C.Deallocate(InitExprs); + } + InitExprs = newInits; + } } -Expr *InitListExpr::updateInit(unsigned Init, Expr *expr) { - if (Init >= InitExprs.size()) { - InitExprs.insert(InitExprs.end(), Init - InitExprs.size() + 1, 0); - InitExprs.back() = expr; - return 0; +void InitListExpr::resizeInits(ASTContext &C, unsigned N) { + // If the new number of expressions is less than the old one, destroy + // the expressions that are beyond the new size. + for (unsigned i = N, LastIdx = NumInits; i < LastIdx; ++i) + InitExprs[i]->Destroy(C); + + // If we are expanding the number of expressions, reserve space. + reserveInits(C, N); + + // If we are expanding the number of expressions, zero out beyond our + // current capacity. + for (unsigned i = NumInits; i < N; ++i) + InitExprs[i] = 0; + + NumInits = N; +} + +Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { + if (Init >= NumInits) { + // Resize the number of initializers. This will adjust the amount + // of memory allocated as well as zero-pad the initializers. + resizeInits(C, Init+1); } Expr *Result = cast_or_null<Expr>(InitExprs[Init]); @@ -2586,12 +2621,8 @@ Stmt::child_iterator VAArgExpr::child_begin() { return &Val; } Stmt::child_iterator VAArgExpr::child_end() { return &Val+1; } // InitListExpr -Stmt::child_iterator InitListExpr::child_begin() { - return InitExprs.size() ? &InitExprs[0] : 0; -} -Stmt::child_iterator InitListExpr::child_end() { - return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0; -} +Stmt::child_iterator InitListExpr::child_begin() { return begin(); } +Stmt::child_iterator InitListExpr::child_end() { return end(); } // DesignatedInitExpr Stmt::child_iterator DesignatedInitExpr::child_begin() { |