From 2de4f7b46000fea3cb0327144233029e22b3d4a1 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 5 Jun 2024 14:37:34 +0200 Subject: [PATCH] fixed: ast memory leak leaf nodes --- src/ast/ast.c | 47 +++++++++++++++++++++++++++++------------------ src/ast/ast.h | 17 +++++++++++++++-- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 4c8caa4..d36b530 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -41,6 +41,20 @@ AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, return node; } +size_t AST_child_count(AST_NODE_PTR node) { + assert(node != NULL); + assert(node->children != NULL); + + return node->children->len; +} + +AST_NODE_PTR AST_get_last_node(AST_NODE_PTR node) { + assert(node != NULL); + assert(node->children != NULL); + + return AST_get_node(node, AST_child_count(node) - 1); +} + static const char *lookup_table[AST_ELEMENT_COUNT] = {"__UNINIT__"}; void AST_init() { @@ -175,7 +189,7 @@ AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, const size_t idx) { PANIC("AST owner node has no children"); } - AST_NODE_PTR child = ((AST_NODE_PTR*) owner->children->data)[idx]; + AST_NODE_PTR child = ((AST_NODE_PTR *) owner->children->data)[idx]; if (child == NULL) { PANIC("child node is NULL"); @@ -198,14 +212,12 @@ AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, const size_t idx) { return child; } -AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child) { - assert(owner != NULL); +AST_NODE_PTR AST_detach_child(AST_NODE_PTR child) { assert(child != NULL); - assert(owner->children != NULL); - for (size_t i = 0; i < owner->children->len; i++) { - if (AST_get_node(owner, i) == child) { - return AST_remove_child(owner, i); + for (size_t i = 0; i < AST_child_count(child->parent); i++) { + if (AST_get_node(child->parent, i) == child) { + return AST_remove_child(child->parent, i); } } @@ -217,23 +229,22 @@ void AST_delete_node(AST_NODE_PTR node) { DEBUG("Deleting AST node: %p", node); - if (node->children == NULL) { - return; - } - if (node->parent != NULL) { - AST_NODE_PTR child = AST_detach_child(node->parent, node); + AST_NODE_PTR child = AST_detach_child(node); assert(child == node); } - for (size_t i = 0; i < node->children->len; i++) { - // prevent detach of children node - AST_NODE_PTR child = AST_get_node(node, i); - child->parent = NULL; - AST_delete_node(child); + if (node->children != NULL) { + for (size_t i = 0; i < AST_child_count(node); i++) { + AST_NODE_PTR child = AST_get_node(node, i); + // prevent detach of children node + child->parent = NULL; + AST_delete_node(child); + } + + g_array_free(node->children, TRUE); } - g_array_free(node->children, TRUE); free(node); } diff --git a/src/ast/ast.h b/src/ast/ast.h index a619bb1..4fc8c88 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -112,6 +112,20 @@ void AST_init(void); [[gnu::nonnull(1)]] const char* AST_node_to_string(AST_NODE_PTR node); +/** + * @brief Return the amount of children + * @param node + * @return + */ +size_t AST_child_count(AST_NODE_PTR node); + +/** + * @brief Return the last node of the children + * @param node + * @return + */ +AST_NODE_PTR AST_get_last_node(AST_NODE_PTR node); + /** * @brief Create a new node struct on the system heap. Initializes the struct with the given values. * All other fields are set to either NULL or 0. No allocation for children array is preformed. @@ -162,13 +176,12 @@ AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, size_t idx); * @brief Detach a child from its parent. This involves removing the child from its parent * and marking the parent of the child as NULL. * @attention The returned pointer is still valid. It must be freed at some pointer later. - * @param owner the owner to remove the child from * @param child the child to detach * @return a pointer to child detached */ [[nodiscard("pointer must be freed")]] [[gnu::nonnull(1), gnu::nonnull(1)]] -AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child); +AST_NODE_PTR AST_detach_child(AST_NODE_PTR child); /** * @brief Return a pointer to the n-th child of a node