Replace unreachable() with assert(false)
This commit is contained in:
parent
c99237fd9c
commit
88f6022dcd
@ -339,7 +339,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
std::shared_ptr<variable_info> variable_info::is_variable()
|
std::shared_ptr<variable_info> variable_info::is_variable()
|
||||||
{
|
{
|
||||||
return std::static_pointer_cast<variable_info>(shared_from_this());;
|
return std::static_pointer_cast<variable_info>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<symbol_table> builtin_symbol_table()
|
std::shared_ptr<symbol_table> builtin_symbol_table()
|
||||||
|
@ -148,7 +148,7 @@ namespace elna::gcc
|
|||||||
if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
|
if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
|
||||||
{
|
{
|
||||||
error_at(argument_location,
|
error_at(argument_location,
|
||||||
"cannot assign value of type '%s' to variable of type '%s'",
|
"Cannot assign value of type '%s' to variable of type '%s'",
|
||||||
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||||
print_type(TREE_VALUE(current_parameter)).c_str());
|
print_type(TREE_VALUE(current_parameter)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
@ -215,6 +215,49 @@ namespace elna::gcc
|
|||||||
void generic_visitor::visit(boot::procedure_call *call)
|
void generic_visitor::visit(boot::procedure_call *call)
|
||||||
{
|
{
|
||||||
location_t call_location = get_location(&call->position());
|
location_t call_location = get_location(&call->position());
|
||||||
|
|
||||||
|
if (boot::variable_expression *named_call = call->callable().is_variable())
|
||||||
|
{
|
||||||
|
if (named_call->name == "assert")
|
||||||
|
{
|
||||||
|
if (call->arguments.size() != 1)
|
||||||
|
{
|
||||||
|
error_at(call_location, "assert expects exactly one boolean argument, got %lu",
|
||||||
|
call->arguments.size());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
call->arguments.at(0)->accept(this);
|
||||||
|
tree argument_type = TREE_TYPE(this->current_expression);
|
||||||
|
|
||||||
|
if (argument_type != elna_bool_type_node)
|
||||||
|
{
|
||||||
|
error_at(call_location, "assert expects exactly one boolean argument, got %s",
|
||||||
|
print_type(argument_type).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
tree constant_expression = extract_constant(this->current_expression);
|
||||||
|
if (constant_expression == boolean_false_node)
|
||||||
|
{
|
||||||
|
tree *builtin = elna_global_decls->get("__builtin_unreachable");
|
||||||
|
gcc_assert(builtin != nullptr);
|
||||||
|
|
||||||
|
tree fndecl_type = build_function_type(void_type_node, TYPE_ARG_TYPES(*builtin));
|
||||||
|
tree builtin_addr = build1_loc(call_location, ADDR_EXPR,
|
||||||
|
build_pointer_type(fndecl_type), *builtin);
|
||||||
|
|
||||||
|
this->current_expression = build_call_nary(void_type_node, builtin_addr, 1,
|
||||||
|
this->current_expression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
call->callable().accept(this);
|
call->callable().accept(this);
|
||||||
|
|
||||||
tree expression_type = TYPE_P(this->current_expression)
|
tree expression_type = TYPE_P(this->current_expression)
|
||||||
@ -768,7 +811,7 @@ namespace elna::gcc
|
|||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
|
|
||||||
if (extract_constant(definition_location))
|
if (assert_constant(definition_location))
|
||||||
{
|
{
|
||||||
this->current_expression = fold_init(this->current_expression);
|
this->current_expression = fold_init(this->current_expression);
|
||||||
}
|
}
|
||||||
@ -1490,7 +1533,7 @@ namespace elna::gcc
|
|||||||
case_label->accept(this);
|
case_label->accept(this);
|
||||||
location_t case_location = get_location(&case_label->position());
|
location_t case_location = get_location(&case_label->position());
|
||||||
|
|
||||||
if (extract_constant(case_location)
|
if (assert_constant(case_location)
|
||||||
&& !is_assignable_from(unqualified_condition, this->current_expression))
|
&& !is_assignable_from(unqualified_condition, this->current_expression))
|
||||||
{
|
{
|
||||||
error_at(case_location, "Case type '%s' does not match the expression type '%s'",
|
error_at(case_location, "Case type '%s' does not match the expression type '%s'",
|
||||||
@ -1535,20 +1578,19 @@ namespace elna::gcc
|
|||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generic_visitor::extract_constant(location_t expression_location)
|
bool generic_visitor::assert_constant(location_t expression_location)
|
||||||
{
|
{
|
||||||
int code = TREE_CODE(this->current_expression);
|
tree constant_expression = extract_constant(this->current_expression);
|
||||||
|
|
||||||
if (code == CONST_DECL)
|
if (constant_expression == NULL_TREE)
|
||||||
{
|
|
||||||
this->current_expression = DECL_INITIAL(this->current_expression);
|
|
||||||
}
|
|
||||||
else if (TREE_CODE_CLASS(code) != tcc_constant)
|
|
||||||
{
|
{
|
||||||
error_at(expression_location, "Expected a constant expression");
|
error_at(expression_location, "Expected a constant expression");
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = constant_expression;
|
||||||
|
}
|
||||||
|
return this->current_expression != error_mark_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,4 +249,19 @@ namespace elna::gcc
|
|||||||
|
|
||||||
return label_decl;
|
return label_decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tree extract_constant(tree expression)
|
||||||
|
{
|
||||||
|
int code = TREE_CODE(expression);
|
||||||
|
|
||||||
|
if (code == CONST_DECL)
|
||||||
|
{
|
||||||
|
return DECL_INITIAL(expression);
|
||||||
|
}
|
||||||
|
else if (TREE_CODE_CLASS(code) == tcc_constant)
|
||||||
|
{
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ namespace elna::gcc
|
|||||||
bool expect_trait_type_only(boot::traits_expression *trait);
|
bool expect_trait_type_only(boot::traits_expression *trait);
|
||||||
bool expect_trait_for_integral_type(boot::traits_expression *trait);
|
bool expect_trait_for_integral_type(boot::traits_expression *trait);
|
||||||
void visit_statements(const std::vector<boot::statement *>& statements);
|
void visit_statements(const std::vector<boot::statement *>& statements);
|
||||||
bool extract_constant(location_t expression_location);
|
bool assert_constant(location_t expression_location);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generic_visitor(std::shared_ptr<symbol_table> symbol_table,
|
generic_visitor(std::shared_ptr<symbol_table> symbol_table,
|
||||||
|
@ -82,4 +82,6 @@ namespace elna::gcc
|
|||||||
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
|
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
|
||||||
tree build_global_pointer_type(tree type);
|
tree build_global_pointer_type(tree type);
|
||||||
tree build_label_decl(const char *name, location_t loc);
|
tree build_label_decl(const char *name, location_t loc);
|
||||||
|
|
||||||
|
tree extract_constant(tree expression);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user