aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-02 17:05:34 +0200
committerEugen Wissner <belka@caraus.de>2026-08-02 17:05:34 +0200
commit1c2fb173ea3b674207badc721556ad72962b266e (patch)
tree950b1d58b719f3302045e114eee35a426af8b0dd
parentc07c43bf911f62ad6363c024b3f81ceb4f95b16c (diff)
downloadelna-1c2fb173ea3b674207badc721556ad72962b266e.tar.gz
Check array property accessbility at compile time
-rw-r--r--boot/evaluator.cc4
-rw-r--r--boot/name_analysis.cc14
-rw-r--r--boot/result.cc6
-rw-r--r--boot/type_check.cc50
-rw-r--r--gcc/gcc/elna-builtins.cc9
-rw-r--r--gcc/gcc/elna-diagnostic.cc10
-rw-r--r--gcc/gcc/elna-generic.cc38
-rw-r--r--gcc/gcc/elna-tree.cc8
-rw-r--r--gcc/gcc/elna1.cc36
-rw-r--r--include/elna/boot/result.h3
-rw-r--r--include/elna/gcc/elna-tree.h8
-rw-r--r--include/elna/gcc/elna1.h1
-rw-r--r--rakelib/gcc.rake7
-rw-r--r--testsuite/compilable/compile_time_array_length.elna5
-rw-r--r--testsuite/fail_compilation/compile_time_array_ptr.elna5
-rw-r--r--testsuite/runnable/slice_equality.elna4
-rw-r--r--testsuite/runnable/slice_slice.elna2
17 files changed, 119 insertions, 91 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index 097b6a5..8f414fa 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -459,7 +459,7 @@ namespace elna::boot
{
switch (operation)
{
- using enum binary_operator;
+ using enum binary_operator;
case equals:
return constant_value{ true };
case not_equals:
@@ -472,7 +472,7 @@ namespace elna::boot
{
switch (operation)
{
- using enum binary_operator;
+ using enum binary_operator;
case sum:
if constexpr (std::is_same_v<T, integer_literal>)
{
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index e4f1920..3667dff 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -41,13 +41,14 @@ namespace elna::boot
{
switch (payload)
{
- case kind::undeclared_type:
+ using enum kind;
+ case undeclared_type:
return "Type '" + this->name + "' not declared";
- case kind::undeclared_trait:
+ case undeclared_trait:
return "Trait '#" + this->name + "' not declared";
- case kind::undeclared_symbol:
+ case undeclared_symbol:
return "Symbol '" + this->name + "' not declared";
- case kind::local_export:
+ case local_export:
return "Local symbol '" + this->name + "' cannot be exported";
default:
__builtin_unreachable();
@@ -77,9 +78,10 @@ namespace elna::boot
{
switch (error_kind)
{
- case kind::array_position:
+ using enum kind;
+ case array_position:
return "const must be written before the array size, not after";
- case kind::duplicate:
+ case duplicate:
return "Duplicate 'const' qualifier is not allowed";
default:
__builtin_unreachable();
diff --git a/boot/result.cc b/boot/result.cc
index b56046b..c47be95 100644
--- a/boot/result.cc
+++ b/boot/result.cc
@@ -424,9 +424,9 @@ namespace elna::boot
{
hash_accumulator result{};
- result.m_seed ^= that + hash_accumulator::golden_ratio
- // NOLINTNEXTLINE(readability-magic-numbers)
- + (this->m_seed << 6) + (this->m_seed >> 2);
+ result.m_seed ^= that + golden_ratio
+ + (this->m_seed << mix_shift_left)
+ + (this->m_seed >> mix_shift_right);
return result;
}
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 529f66a..78e975a 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -174,25 +174,26 @@ namespace elna::boot
{
switch (payload)
{
- case kind::record_base:
+ using enum kind;
+ case record_base:
return "Expected a record type, but got '"
+ this->actual.to_string() + "'";
- case kind::for_range:
+ case for_range:
return "Expected an array or slice type, but got '"
+ this->actual.to_string() + "'";
- case kind::condition:
+ case condition:
return "Condition must be a boolean expression, but got '"
+ this->actual.to_string() + "'";
- case kind::constant_assignment:
+ case constant_assignment:
return "Cannot assign to a value of type '" + this->actual.to_string()
+ "', because it is constant or contains constant members";
- case kind::array_index:
+ case array_index:
return "Array index must be an integral type, but got '"
+ this->actual.to_string() + "'";
- case kind::non_indexable:
+ case non_indexable:
return "Indexing is not allowed on type '"
+ this->actual.to_string() + "'";
- case kind::dereference_of_non_pointer:
+ case dereference_of_non_pointer:
return "Type '" + this->actual.to_string()
+ "' cannot be dereferenced, it is not a pointer";
default:
@@ -422,17 +423,24 @@ namespace elna::boot
bool assign_check::run()
{
- for (auto handler : {&assign_check::guard_const_laundering,
- &assign_check::check_exact_match,
- &assign_check::check_slice_conversion,
- &assign_check::check_pointer_hatch,
- &assign_check::check_pointer_conversion})
+ auto const assign_handlers = {
+ &assign_check::guard_const_laundering,
+ &assign_check::check_exact_match,
+ &assign_check::check_slice_conversion,
+ &assign_check::check_pointer_hatch,
+ &assign_check::check_pointer_conversion
+ };
+ for (auto handler : assign_handlers)
{
switch ((this->*handler)())
{
- case verdict::accept: return true;
- case verdict::reject: return false;
- case verdict::pass:;
+ using enum verdict;
+ case accept:
+ return true;
+ case reject:
+ return false;
+ case pass:
+ break;
}
}
return false;
@@ -441,11 +449,11 @@ namespace elna::boot
bool type_analysis_visitor::is_assignable_from(const type& assignee, const type& assignment)
{
return assign_check{
- resolve_aliases(assignee),
- resolve_aliases(assignment),
- resolve_underlying_type(assignee),
- resolve_underlying_type(assignment)
- }.run();
+ resolve_aliases(assignee),
+ resolve_aliases(assignment),
+ resolve_underlying_type(assignee),
+ resolve_underlying_type(assignment)
+ }.run();
}
type_analysis_visitor::type_analysis_visitor(symbol_bag bag, const target_info& target)
@@ -893,7 +901,7 @@ namespace elna::boot
switch (operation)
{
- using enum binary_operator;
+ using enum binary_operator;
case sum:
valid = (is_any_pointer_type(lhs_resolved) && is_integral_type(rhs_resolved))
|| (is_integral_type(lhs_resolved) && is_any_pointer_type(rhs_resolved))
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 7e47c30..7c4545e 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -90,7 +90,7 @@ namespace elna::gcc
}
for (tree field = TYPE_FIELDS(record_type); field != NULL_TREE; field = TREE_CHAIN(field))
{
- std::string field_name(IDENTIFIER_POINTER(DECL_NAME(field)));
+ const std::string field_name(IDENTIFIER_POINTER(DECL_NAME(field)));
DECL_FIELD_OFFSET(field) = size_int(record_layout.value().offset_map.find(field_name)->second);
DECL_FIELD_BIT_OFFSET(field) = bitsize_zero_node;
@@ -247,18 +247,15 @@ namespace elna::gcc
function_args_iterator parameter_type;
function_args_iter_init(&parameter_type, declaration_type);
- std::vector<std::string>::const_iterator parameter_name = info.names.cbegin();
-
- for (boot::type parameter : info.symbol.parameters)
+ for (const std::string& parameter_name : info.names)
{
tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(parameter_name->c_str()), function_args_iter_cond(&parameter_type));
+ get_identifier(parameter_name.c_str()), function_args_iter_cond(&parameter_type));
DECL_CONTEXT(declaration_tree) = fndecl;
DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(&parameter_type);
argument_chain = chainon(argument_chain, declaration_tree);
function_args_iter_next(&parameter_type);
- ++parameter_name;
}
DECL_ARGUMENTS(fndecl) = argument_chain;
TREE_ADDRESSABLE(fndecl) = 1;
diff --git a/gcc/gcc/elna-diagnostic.cc b/gcc/gcc/elna-diagnostic.cc
index 909869c..3bc274e 100644
--- a/gcc/gcc/elna-diagnostic.cc
+++ b/gcc/gcc/elna-diagnostic.cc
@@ -46,8 +46,8 @@ namespace elna::gcc
location_t make_range(const boot::source_position& position)
{
linemap_line_start(line_table, position.start().line(), 0);
- location_t caret = linemap_position_for_column(line_table, position.start().column());
- location_t start = caret;
+ const location_t caret = linemap_position_for_column(line_table, position.start().column());
+ const location_t start = caret;
location_t end;
if (position.is_span())
@@ -69,17 +69,17 @@ namespace elna::gcc
{
if (error->position.start().available())
{
- location_t loc = make_range(error->position);
+ const location_t loc = make_range(error->position);
error_at(loc, "%s", error->what().c_str());
}
else
{
- location_t gcc_location{ UNKNOWN_LOCATION };
+ const location_t gcc_location{ UNKNOWN_LOCATION };
error_at(gcc_location, "%s", error->what().c_str());
}
if (auto note = error->note())
{
- location_t note_loc = make_range(note->second);
+ const location_t note_loc = make_range(note->second);
inform(note_loc, "%s", note->first.c_str());
}
}
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index e59a438..aff5d9d 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -83,9 +83,9 @@ namespace elna::gcc
bool generic_visitor::build_builtin_procedures(boot::procedure_call *call)
{
- location_t call_location = get_location(&call->position());
+ const location_t call_location = get_location(&call->position());
- if (boot::named_expression *named_call = call->callable().is_named())
+ if (const boot::named_expression *named_call = call->callable().is_named())
{
if (named_call->name == "assert")
{
@@ -102,7 +102,7 @@ namespace elna::gcc
{
return;
}
- location_t call_location = get_location(&call->position());
+ const location_t call_location = get_location(&call->position());
call->callable().accept(this);
tree expression_type = TYPE_P(this->current_expression)
@@ -130,7 +130,7 @@ namespace elna::gcc
tree cast_target = get_inner_alias(expression->type_decoration, this->symbols);
expression->value().accept(this);
- location_t cast_location = get_location(&expression->position());
+ const location_t cast_location = get_location(&expression->position());
auto source_slice = resolve_underlying_type(expression->value().type_decoration)
.get<boot::slice_type>();
auto target_slice = resolve_underlying_type(expression->type_decoration)
@@ -178,6 +178,7 @@ namespace elna::gcc
tree field_decl = find_field_by_name(get_location(&expression->position()),
record_type, initializer.name());
initializer.value().accept(this);
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, this->current_expression);
}
this->current_expression = build_constructor(record_type, tree_arguments);
@@ -199,6 +200,7 @@ namespace elna::gcc
for (boot::expression *const element : expression->elements)
{
element->accept(this);
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(tree_arguments, index, this->current_expression);
index = int_const_binop(PLUS_EXPR, index, elna_word_one_node);
}
@@ -207,7 +209,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::slicing_expression *expression)
{
- location_t location = get_location(&expression->position());
+ const location_t location = get_location(&expression->position());
tree slice_type = get_inner_alias(expression->type_decoration, this->symbols);
tree ptr_field = TYPE_FIELDS(slice_type);
@@ -317,7 +319,7 @@ namespace elna::gcc
if (declaration->body.value().return_expression != nullptr)
{
- location_t position = get_location(&declaration->body.value().return_expression->position());
+ const location_t position = get_location(&declaration->body.value().return_expression->position());
tree set_result{ NULL_TREE };
if (TREE_THIS_VOLATILE(current_function_decl) != 1)
@@ -360,7 +362,7 @@ namespace elna::gcc
tree generic_visitor::build_equality_comparison(location_t loc, tree left, tree right,
const boot::type& left_type, tree_code equality_code)
{
- tree_code combination_code = equality_code == EQ_EXPR
+ const tree_code combination_code = equality_code == EQ_EXPR
? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
if (left_type.get<boot::slice_type>() != nullptr)
@@ -543,7 +545,7 @@ namespace elna::gcc
tree right = this->current_expression;
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
- location_t expression_location = get_location(&expression->position());
+ const location_t expression_location = get_location(&expression->position());
const bool is_pointer_arithmetic_operation
= expression->operation() == boot::binary_operator::sum
@@ -644,7 +646,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::unary_expression *expression)
{
expression->operand().accept(this);
- location_t location = get_location(&expression->position());
+ const location_t location = get_location(&expression->position());
switch (expression->operation())
{
@@ -685,7 +687,7 @@ namespace elna::gcc
{
for (const auto& variable_identifier : declaration->identifiers)
{
- location_t declaration_location = get_location(&declaration->position());
+ const location_t declaration_location = get_location(&declaration->position());
tree declaration_tree = this->symbols->lookup(variable_identifier.name());
auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();
@@ -752,7 +754,7 @@ namespace elna::gcc
{
expression->base().accept(this);
tree designator = this->current_expression;
- location_t location = get_location(&expression->position());
+ const location_t location = get_location(&expression->position());
expression->index().accept(this);
tree offset = fold_convert(elna_word_type_node, this->current_expression);
@@ -780,7 +782,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::field_access_expression *expression)
{
expression->base().accept(this);
- location_t expression_location = get_location(&expression->position());
+ const location_t expression_location = get_location(&expression->position());
tree aggregate_type = TREE_TYPE(this->current_expression);
if (TREE_CODE(aggregate_type) == ARRAY_TYPE && expression->field() == "length")
@@ -825,7 +827,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::dereference_expression *expression)
{
expression->base().accept(this);
- location_t expression_location = get_location(&expression->position());
+ const location_t expression_location = get_location(&expression->position());
this->current_expression = build_simple_mem_ref_loc(expression_location,
this->current_expression);
@@ -836,7 +838,7 @@ namespace elna::gcc
statement->lvalue().accept(this);
tree lvalue = this->current_expression;
- location_t statement_location = get_location(&statement->position());
+ const location_t statement_location = get_location(&statement->position());
statement->rvalue().accept(this);
tree rvalue = prepare_rvalue(this->current_expression);
@@ -925,7 +927,7 @@ namespace elna::gcc
{
statement->range().accept(this);
tree range_expression = this->current_expression;
- location_t location = get_location(&statement->position());
+ const location_t location = get_location(&statement->position());
tree start_pointer;
tree length;
@@ -954,7 +956,7 @@ namespace elna::gcc
// Declare control variable with the unqualified type. The constant_type wrapper
// is for semantic checking only, because GENERIC needs to modify the control variable.
auto control_variable_info = statement->symbols->lookup(statement->control_variable.name());
- boot::variable_info unqualified_info(
+ const boot::variable_info unqualified_info(
boot::resolve_underlying_type(control_variable_info->is_variable()->symbol),
control_variable_info->is_variable()->is_extern);
tree control_variable_declaration = declare_local_variable(
@@ -994,7 +996,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::while_statement *statement)
{
- location_t prerequisite_location = get_location(&statement->branch().prerequisite().position());
+ const location_t prerequisite_location = get_location(&statement->branch().prerequisite().position());
tree while_check_label = create_artificial_label(prerequisite_location);
tree while_end_label = create_artificial_label(UNKNOWN_LOCATION);
tree goto_check = build1(GOTO_EXPR, void_type_node, while_check_label);
@@ -1072,7 +1074,7 @@ namespace elna::gcc
for (boot::expression *const case_label : case_block.labels)
{
case_label->accept(this);
- location_t case_location = get_location(&case_label->position());
+ const location_t case_location = get_location(&case_label->position());
assert_constant(case_location);
tree case_label_declaration = create_artificial_label(case_location);
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index addb686..69ef37f 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -89,7 +89,7 @@ namespace elna::gcc
void defer(tree statement_tree)
{
- defer_scope new_defer{ .defer_block = statement_tree, .try_statements = alloc_stmt_list() };
+ const defer_scope new_defer{ .defer_block = statement_tree, .try_statements = alloc_stmt_list() };
vec_safe_insert(f_binding_level->defers, 0, new_defer);
}
@@ -212,7 +212,9 @@ namespace elna::gcc
tree ptr_field = TYPE_FIELDS(slice_type);
vec<constructor_elt, va_gc> *elements = nullptr;
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(elements, ptr_field, ptr);
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(elements, TREE_CHAIN(ptr_field), length);
return build_constructor(slice_type, elements);
@@ -256,7 +258,7 @@ namespace elna::gcc
tree extract_constant(tree expression)
{
- int code = TREE_CODE(expression);
+ const int code = TREE_CODE(expression);
if (code == CONST_DECL)
{
@@ -361,6 +363,7 @@ namespace elna::gcc
{
return NULL_TREE;
}
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, value_tree);
}
return build_constructor(type, tree_arguments);
@@ -385,6 +388,7 @@ namespace elna::gcc
{
return NULL_TREE;
}
+ // NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(tree_arguments, index, element_tree);
index = int_const_binop(PLUS_EXPR, index, elna_word_one_node);
}
diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc
index 0602b99..4eb01cc 100644
--- a/gcc/gcc/elna1.cc
+++ b/gcc/gcc/elna1.cc
@@ -86,7 +86,7 @@ static std::vector<std::filesystem::path> find_module(const elna::boot::import_d
}
else if (found.size() > 1)
{
- location_t gcc_location = elna::gcc::get_location(&declaration->position());
+ const location_t gcc_location = elna::gcc::get_location(&declaration->position());
error_at(gcc_location, "Module %s was found in more than one include path",
relative_path.native().c_str());
}
@@ -101,7 +101,7 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
{
fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename);
}
- elna::gcc::linemap_guard guard(filename);
+ const elna::gcc::linemap_guard guard(filename);
elna::boot::dependency outcome = elna::boot::read_source(entry_point);
elna::boot::symbol_bag outcome_bag{ std::move(outcome.unresolved), state.globals };
@@ -110,7 +110,7 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
{
for (const elna::boot::import_declaration* sub_tree : outcome.tree->imports)
{
- std::filesystem::path sub_path = find_module(sub_tree)[0];
+ const std::filesystem::path sub_path = find_module(sub_tree)[0];
dependency_state::const_iterator cached_import = state.find(sub_path);
if (cached_import == std::cend(state))
@@ -151,13 +151,15 @@ static void elna_langhook_parse_file()
elna::gcc::generic_visitor generic_visitor{ state.custom,
state.find(in_fnames[i])->second, elna::gcc::get_host_target() };
outcome.tree->accept(&generic_visitor);
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
+ linemap_add(line_table, LC_LEAVE, 0, nullptr, 0);
}
}
}
static tree elna_langhook_type_for_mode(enum machine_mode mode, int unsignedp)
{
+ const bool unsigned_wanted = unsignedp != 0;
+
if (mode == TYPE_MODE(float_type_node))
{
return float_type_node;
@@ -168,37 +170,35 @@ static tree elna_langhook_type_for_mode(enum machine_mode mode, int unsignedp)
}
if (mode == TYPE_MODE(intQI_type_node))
{
- return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+ return unsigned_wanted ? unsigned_intQI_type_node : intQI_type_node;
}
else if (mode == TYPE_MODE(intHI_type_node))
{
- return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+ return unsigned_wanted ? unsigned_intHI_type_node : intHI_type_node;
}
else if (mode == TYPE_MODE(intSI_type_node))
{
- return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+ return unsigned_wanted ? unsigned_intSI_type_node : intSI_type_node;
}
else if (mode == TYPE_MODE(intDI_type_node))
{
- return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+ return unsigned_wanted ? unsigned_intDI_type_node : intDI_type_node;
}
else if (mode == TYPE_MODE(intTI_type_node))
{
- return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+ return unsigned_wanted ? unsigned_intTI_type_node : intTI_type_node;
}
else if (mode == TYPE_MODE(integer_type_node))
{
- return unsignedp ? unsigned_type_node : integer_type_node;
+ return unsigned_wanted ? unsigned_type_node : integer_type_node;
}
else if (mode == TYPE_MODE(long_integer_type_node))
{
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ return unsigned_wanted ? long_unsigned_type_node : long_integer_type_node;
}
else if (mode == TYPE_MODE(long_long_integer_type_node))
{
- return unsignedp
- ? long_long_unsigned_type_node
- : long_long_integer_type_node;
+ return unsigned_wanted ? long_long_unsigned_type_node : long_long_integer_type_node;
}
if (COMPLEX_MODE_P(mode))
{
@@ -214,7 +214,7 @@ static tree elna_langhook_type_for_mode(enum machine_mode mode, int unsignedp)
{
return complex_long_double_type_node;
}
- if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp)
+ if (mode == TYPE_MODE(complex_integer_type_node) && !unsigned_wanted)
{
return complex_integer_type_node;
}
@@ -254,12 +254,10 @@ static bool elna_langhook_handle_option(
location_t loc ATTRIBUTE_UNUSED,
const struct cl_option_handlers * handlers ATTRIBUTE_UNUSED)
{
- opt_code code = static_cast<opt_code>(scode);
-
- switch (code)
+ switch (static_cast<opt_code>(scode))
{
case OPT_I:
- elna_include_dirs.push_back(arg);
+ elna_include_dirs.emplace_back(arg);
return true;
default:
return true;
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index c73799d..36be8ee 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -655,6 +655,9 @@ namespace elna::boot
private:
static constexpr std::size_t golden_ratio = 0x9e3779b9;
+ static constexpr int mix_shift_left = 6;
+ static constexpr int mix_shift_right = 2;
+
std::size_t m_seed{ 0 };
};
}
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
index 219acb1..8f7e306 100644
--- a/include/elna/gcc/elna-tree.h
+++ b/include/elna/gcc/elna-tree.h
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
#include "elna/boot/symbol.h"
#include "elna/gcc/elna1.h"
+#include <array>
+
namespace elna::gcc
{
using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
@@ -67,14 +69,14 @@ namespace elna::gcc
template<typename... Args>
tree call_built_in(location_t call_location, const char *name, tree return_type, Args... arguments)
{
- tree *builtin = elna_global_decls->get(name);
+ const tree *builtin = elna_global_decls->get(name);
gcc_assert(builtin != nullptr);
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(*builtin));
tree builtin_addr = build1_loc(call_location, ADDR_EXPR, build_pointer_type(fndecl_type), *builtin);
- tree argument_trees[sizeof...(Args)] = {arguments...};
+ std::array<tree, sizeof...(Args)> argument_trees = { arguments... };
- return fold_build_call_array(return_type, builtin_addr, sizeof...(Args), argument_trees);
+ return fold_build_call_array(return_type, builtin_addr, sizeof...(Args), argument_trees.data());
}
}
diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h
index 580526a..96043f9 100644
--- a/include/elna/gcc/elna1.h
+++ b/include/elna/gcc/elna1.h
@@ -31,6 +31,7 @@ enum elna_tree_index
ELNA_TI_MAX
};
+// NOLINTNEXTLINE(modernize-avoid-c-arrays)
extern GTY(()) tree elna_global_trees[ELNA_TI_MAX];
extern GTY(()) hash_map<nofree_string_hash, tree> *elna_global_decls;
extern std::vector<std::string> elna_include_dirs;
diff --git a/rakelib/gcc.rake b/rakelib/gcc.rake
index abdeb6d..558c8a2 100644
--- a/rakelib/gcc.rake
+++ b/rakelib/gcc.rake
@@ -159,9 +159,10 @@ namespace :gcc do
compile_db = Pathname.new 'compile_commands.json'
raise "#{compile_db} is missing. Run: bear -- rake gcc:make" unless compile_db.exist?
- sources = FileList['boot/*.cc', 'include/elna/boot/*.h'].exclude do |f|
- f.include?('generated/')
- end
+ sources = FileList['boot/*.cc', 'gcc/gcc/*.cc', 'include/elna/**/*.h']
+ .reject do |file|
+ ['/elna1.', '/elna-spec.'].any? { |pattern| file.include? pattern }
+ end
sh 'clang-tidy', '-p', compile_db.to_path, '--extra-arg=-w', '--warnings-as-errors=*', *sources
end
diff --git a/testsuite/compilable/compile_time_array_length.elna b/testsuite/compilable/compile_time_array_length.elna
new file mode 100644
index 0000000..1ce8956
--- /dev/null
+++ b/testsuite/compilable/compile_time_array_length.elna
@@ -0,0 +1,5 @@
+var
+ source: [3]Int := [3]Int{ 1, 2, 3}
+ target: Word := source.length
+
+end.
diff --git a/testsuite/fail_compilation/compile_time_array_ptr.elna b/testsuite/fail_compilation/compile_time_array_ptr.elna
new file mode 100644
index 0000000..dd626a6
--- /dev/null
+++ b/testsuite/fail_compilation/compile_time_array_ptr.elna
@@ -0,0 +1,5 @@
+var
+ source: [3]Int := [3]Int{ 1, 2, 3}
+ target: ^Int := source.ptr (* @Error Variable initializers must be constant expressions *)
+
+end.
diff --git a/testsuite/runnable/slice_equality.elna b/testsuite/runnable/slice_equality.elna
index 1969088..712ae7a 100644
--- a/testsuite/runnable/slice_equality.elna
+++ b/testsuite/runnable/slice_equality.elna
@@ -3,8 +3,8 @@ var
lhs, rhs: []Int
begin
- lhs := lhs_payload.ptr[1 to 3];
- rhs := rhs_payload.ptr[1 to 3];
+ lhs := lhs_payload[1 to 3];
+ rhs := rhs_payload[1 to 3];
assert(lhs = rhs)
end.
diff --git a/testsuite/runnable/slice_slice.elna b/testsuite/runnable/slice_slice.elna
index d6f309f..cce45ee 100644
--- a/testsuite/runnable/slice_slice.elna
+++ b/testsuite/runnable/slice_slice.elna
@@ -3,7 +3,7 @@ var
slice1, slice2: []Int
begin
- slice1 := array.ptr[1 to array.length];
+ slice1 := array[1 to array.length];
slice2 := slice1[2 to 4];
assert(slice2.length = 3u);