diff --git a/src/analysis.cpp b/src/analysis.cpp index a367361..25fba58 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -214,6 +214,9 @@ AnalysisResult analyze(Node &ast, Memory &memory) { throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier); Type type = try_string_to_type(type_string, type_token.pos); + if (type.type == TypeType::Void) + throw TypeError(ErrorType::IncompleteType, token.pos, {}); + memory.declare(identifier, type); return {}; @@ -229,6 +232,9 @@ AnalysisResult analyze(Node &ast, Memory &memory) { throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier); Type type = try_string_to_type(type_string, type_token.pos); + if (type.type == TypeType::Void) + throw TypeError(ErrorType::IncompleteType, token.pos, {}); + memory.declare(identifier, type); get_cast(type, analyze(node.children[2], memory), get_node_pos(node)); @@ -295,6 +301,15 @@ AnalysisResult analyze(Node &ast, Memory &memory) { } } + for (int i=1; i < (int)prototype.size(); i++) { + if (get<0>(prototype.at(i)).type == TypeType::Void) { + InnerNode args_node = get(node.children[2]); + InnerNode declaration_node = get(args_node.children[i-1]); + CodePosition type_pos = get_node_pos(declaration_node.children[0]); + throw TypeError(ErrorType::IncompleteType, type_pos, {}); + } + } + memory.declare(function_name, type); return {}; @@ -335,6 +350,15 @@ AnalysisResult analyze(Node &ast, Memory &memory) { } } + for (int i=1; i < (int)prototype.size(); i++) { + if (get<0>(prototype.at(i)).type == TypeType::Void) { + InnerNode args_node = get(node.children[2]); + InnerNode declaration_node = get(args_node.children[i-1]); + CodePosition type_pos = get_node_pos(declaration_node.children[0]); + throw TypeError(ErrorType::IncompleteType, type_pos, {}); + } + } + memory.declare(function_name, type); memory.update(function_name, node.children[3]); diff --git a/src/errors.cpp b/src/errors.cpp index ca5fc82..1a991fa 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -46,6 +46,7 @@ string UserError::get_message(void) const { case ErrorType::IncompatibleDefinition: return "Declaration of '"+get(this->data)+"' is incompatible with previous prototype"; case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get(this->data))+" arguments to function call"; case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type"; + case ErrorType::IncompleteType: return "Incomplete type is not allowed"; // Runtime case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get(this->data)+"'"; diff --git a/src/include/errors.h b/src/include/errors.h index 4e27a0c..4f9f2ae 100644 --- a/src/include/errors.h +++ b/src/include/errors.h @@ -45,6 +45,7 @@ enum class ErrorType { IncompatibleDefinition, // function declaration incompatible with prototype UnexpectedArgumentCount, IncompatibleReturnValue, + IncompleteType, // void x // Runtime UnknownIdentifier, diff --git a/test/functions.cpp b/test/functions.cpp index 5c42735..567af3f 100644 --- a/test/functions.cpp +++ b/test/functions.cpp @@ -98,5 +98,17 @@ int main() { true ); + _TEST_ASSERT( + _TEST_IS_EXCEPTION(execute("int f(int x, void y);"), ErrorType::IncompleteType), + "Argument void (prototype)", + true + ); + + _TEST_ASSERT( + _TEST_IS_EXCEPTION(execute("int f(int x, void y) { return x+2; };"), ErrorType::IncompleteType), + "Argument void (déclaration)", + true + ); + return 0; } \ No newline at end of file diff --git a/test/variables.cpp b/test/variables.cpp index b55ccdc..6938560 100644 --- a/test/variables.cpp +++ b/test/variables.cpp @@ -35,6 +35,12 @@ int main() { true ); + _TEST_ASSERT( + _TEST_IS_EXCEPTION(execute("void x;"), ErrorType::IncompleteType), + "Type void", + true + ); + _TEST_ASSERT( _TEST_NO_EXCEPTION(holds_alternative(execute("int x; { int x; }"))), "Identifieur déjà défini dans une autre scope",