When does ASTContext release memory?

Most AST nodes are allocated with new (ctx) SomeNode(...) (e.g. TupleElementExpr, ErrorExpr, ...), which calls SomeNode::operator new, and then ASTContext::Allocate, AlignedAlloc and posix_memalign. But when I try to find the corresponding AlignedFree and free, I find nothing. I feel like AST has a memory leak. What did I miss?

In the destructor ASTContext::~ASTContext(). I don't think there is any way to deallocate individual things:


(The doc comments here are from Clang, but the same points apply,
 Swiftc also has a `llvm::BumpPtrAllocator Allocator` in its implementation.)

/// The allocator used to create AST objects.
///
/// AST objects are never destructed; rather, all memory associated with the
/// AST objects will be released when the ASTContext itself is destroyed.
mutable llvm::BumpPtrAllocator BumpAlloc;

/// Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
/// invoking it directly; see the new operator for more details. This operator
/// is called implicitly by the compiler if a placement new expression using
/// the ASTContext throws in the object constructor.
inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
  C.Deallocate(Ptr);
}
void Deallocate(void *Ptr) const {}
1 Like

Oh I see, I was confused by LangOpts.UseMalloc, I didn't realize it was actually false by default. Thanks.

// ASTContext::Allocate
void *Allocate(unsigned long bytes, unsigned alignment,
               AllocationArena arena = AllocationArena::Permanent) const {
  if (bytes == 0)
    return nullptr;

  if (LangOpts.UseMalloc)
    return AlignedAlloc(bytes, alignment);

  if (arena == AllocationArena::Permanent && Stats)
    Stats->getFrontendCounters().NumASTBytesAllocated += bytes;
  return getAllocator(arena).Allocate(bytes, alignment);
}