fixed: ast memory leak leaf nodes

This commit is contained in:
Sven Vogel 2024-06-05 14:37:34 +02:00
parent f069d04ad1
commit 2de4f7b460
2 changed files with 44 additions and 20 deletions

View File

@ -41,6 +41,20 @@ AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind,
return node; 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__"}; static const char *lookup_table[AST_ELEMENT_COUNT] = {"__UNINIT__"};
void AST_init() { 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"); 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) { if (child == NULL) {
PANIC("child node is 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; return child;
} }
AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child) { AST_NODE_PTR AST_detach_child(AST_NODE_PTR child) {
assert(owner != NULL);
assert(child != NULL); assert(child != NULL);
assert(owner->children != NULL);
for (size_t i = 0; i < owner->children->len; i++) { for (size_t i = 0; i < AST_child_count(child->parent); i++) {
if (AST_get_node(owner, i) == child) { if (AST_get_node(child->parent, i) == child) {
return AST_remove_child(owner, i); 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); DEBUG("Deleting AST node: %p", node);
if (node->children == NULL) {
return;
}
if (node->parent != NULL) { 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); assert(child == node);
} }
for (size_t i = 0; i < node->children->len; i++) { if (node->children != NULL) {
// prevent detach of children node for (size_t i = 0; i < AST_child_count(node); i++) {
AST_NODE_PTR child = AST_get_node(node, i); AST_NODE_PTR child = AST_get_node(node, i);
child->parent = NULL; // prevent detach of children node
AST_delete_node(child); child->parent = NULL;
AST_delete_node(child);
}
g_array_free(node->children, TRUE);
} }
g_array_free(node->children, TRUE);
free(node); free(node);
} }

View File

@ -112,6 +112,20 @@ void AST_init(void);
[[gnu::nonnull(1)]] [[gnu::nonnull(1)]]
const char* AST_node_to_string(AST_NODE_PTR node); 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. * @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. * 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 * @brief Detach a child from its parent. This involves removing the child from its parent
* and marking the parent of the child as NULL. * and marking the parent of the child as NULL.
* @attention The returned pointer is still valid. It must be freed at some pointer later. * @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 * @param child the child to detach
* @return a pointer to child detached * @return a pointer to child detached
*/ */
[[nodiscard("pointer must be freed")]] [[nodiscard("pointer must be freed")]]
[[gnu::nonnull(1), gnu::nonnull(1)]] [[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 * @brief Return a pointer to the n-th child of a node