Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/valgrind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,5 @@ jobs:
run: make all

- name: Run tests under Valgrind
run: |
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--error-exitcode=1 \
./build/cleaf test.clf
run: make valgrind-test

29 changes: 27 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,33 @@ asan-test:
CFLAGS="-fsanitize=address,undefined -g -O1" make test

valgrind-test:
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test.clf

@echo "Testing memory safety with valgrind..."
@echo "=== Testing normal execution ==="
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/full.clf
@echo "=== Testing lexer errors ==="
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/lexer_error.clf
@echo "=== Testing parser errors ==="
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_missing_semicolon.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_unmatched_brace.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_missing_paren.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_incomplete_function.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_missing_function_name.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_missing_var_name.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/parser_for_missing_increment.clf
@echo "=== Testing semantic errors ==="
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_function_reserved.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_undefined_vars.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_type_mismatch.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_var_redefinition.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_undefined_function.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_function_duplicate.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_function_args_error.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_return_type_error.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_unary_type_error.clf
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/semantic_control_flow_errors.clf
@echo "=== Testing combined errors ==="
valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./build/cleaf test/valgrind_case/combined_multiple_errors.clf
@echo "=== All valgrind tests passed ==="

clean:
rm -rf $(BUILD)
Expand Down
7 changes: 4 additions & 3 deletions src/frontend/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,8 @@ statement_t* parse_statement(parser_t* p)
return ast_parse_decl_stmt(p);
}

// for now, we can maybe assume that this is the always wanted fallback
// TODO: keep an eye on this
return ast_parse_expr_stmt(p);
if (p->pos < p->count)
return ast_parse_expr_stmt(p);

return NULL;
}
8 changes: 8 additions & 0 deletions test/valgrind_case/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Valgrind test case

The goal of this dir is to create cleaf program that valgrind will test to verify that there is no memory leaks.

Here is the strategy:

- maintain some base cleaf program that runs completely to check memory safety in a normal environment
- test every early compiler termination by adding cleaf files that should not compile to check that not running the compiler entirely don't cause memory leak
25 changes: 25 additions & 0 deletions test/valgrind_case/combined_multiple_errors.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
fn test(int a, int a): string {
var b = undefined_var + 5;
int c = "string" + 10;
var c = 20;
return 42;
}

fn test(): int {
return "duplicate function";
}

fn main() {
int x = missing_func(1, 2);
var y = test(5
string z = x + "text";

for (var i = 0; undef_var < 10; ++i) {
int i = 0;
var result = i + "string";
}

if (another_missing {
x = y;

}
36 changes: 36 additions & 0 deletions test/valgrind_case/full.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
fn main(): int {
var a = bar(0);
int b = bar(0);

string c = foo();

var d = a + b;

for (var i = 0; i < a + 10; ++i) {
if (b == 0) {
d++;
}
}

while (d > 0) {
d = d - b + 1;
}

if (d == 0) {
d = 4;
} else {
d = 0;
}

return 0;
}


fn foo(): string {
var b = "test";
return b;
}

fn bar(int a): int {
return a;
}
3 changes: 3 additions & 0 deletions test/valgrind_case/lexer_error.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
var a = @invalid;
}
5 changes: 5 additions & 0 deletions test/valgrind_case/parser_for_missing_increment.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
for (var i = 0; i < 10) {
i++;
}
}
1 change: 1 addition & 0 deletions test/valgrind_case/parser_incomplete_function.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main(
3 changes: 3 additions & 0 deletions test/valgrind_case/parser_missing_function_name.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn {
return 0;
}
3 changes: 3 additions & 0 deletions test/valgrind_case/parser_missing_paren.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
var a = (5 + 3;
}
4 changes: 4 additions & 0 deletions test/valgrind_case/parser_missing_semicolon.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
var a = 5
var b = 10;
}
3 changes: 3 additions & 0 deletions test/valgrind_case/parser_missing_var_name.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
var = 5;
}
6 changes: 6 additions & 0 deletions test/valgrind_case/parser_unmatched_brace.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
var a = 5;
if (a > 0) {
a = 10;

}
14 changes: 14 additions & 0 deletions test/valgrind_case/semantic_control_flow_errors.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fn main() {
int a = 5;
for (var i = 0; undefined_cond < 10; ++i) {
a++;
}

while (missing_var > 0) {
a--;
}

if (another_undef) {
a = 0;
}
}
9 changes: 9 additions & 0 deletions test/valgrind_case/semantic_function_args_error.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn add(int a, int b): int {
return a + b;
}

fn main() {
var x = add(5);
var y = add(1, 2, 3);
var z = add("test", 5);
}
11 changes: 11 additions & 0 deletions test/valgrind_case/semantic_function_duplicate.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn foo() {
return 0;
}

fn foo() {
return 1;
}

fn main() {
return 0;
}
3 changes: 3 additions & 0 deletions test/valgrind_case/semantic_function_reserved.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn var(): {
return 0;
}
7 changes: 7 additions & 0 deletions test/valgrind_case/semantic_return_type_error.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn test(): string {
return 42;
}

fn main(): int {
return "not an int";
}
6 changes: 6 additions & 0 deletions test/valgrind_case/semantic_type_mismatch.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
int a = 5;
string b = "test";
var c = a + b;
var d = b - 10;
}
6 changes: 6 additions & 0 deletions test/valgrind_case/semantic_unary_type_error.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
var a = -"string";
int b = !"test";
string c = "hello";
var d = ++c;
}
4 changes: 4 additions & 0 deletions test/valgrind_case/semantic_undefined_function.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
var result = undefined_function();
another_missing(5, 10);
}
4 changes: 4 additions & 0 deletions test/valgrind_case/semantic_undefined_vars.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
int a = undefined_var + 5;
var b = another_undef;
}
6 changes: 6 additions & 0 deletions test/valgrind_case/semantic_var_redefinition.clf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
int a = 5;
int a = 10;
var b = 3;
string b = "test";
}