From 1c2fb173ea3b674207badc721556ad72962b266e Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 2 Aug 2026 17:05:34 +0200 Subject: Check array property accessbility at compile time --- boot/evaluator.cc | 4 +- boot/name_analysis.cc | 14 +++--- boot/result.cc | 6 +-- boot/type_check.cc | 50 +++++++++++++--------- gcc/gcc/elna-builtins.cc | 9 ++-- gcc/gcc/elna-diagnostic.cc | 10 ++--- gcc/gcc/elna-generic.cc | 38 ++++++++-------- gcc/gcc/elna-tree.cc | 8 +++- gcc/gcc/elna1.cc | 36 ++++++++-------- include/elna/boot/result.h | 3 ++ include/elna/gcc/elna-tree.h | 8 ++-- include/elna/gcc/elna1.h | 1 + rakelib/gcc.rake | 7 +-- .../compilable/compile_time_array_length.elna | 5 +++ .../fail_compilation/compile_time_array_ptr.elna | 5 +++ testsuite/runnable/slice_equality.elna | 4 +- testsuite/runnable/slice_slice.elna | 2 +- 17 files changed, 119 insertions(+), 91 deletions(-) create mode 100644 testsuite/compilable/compile_time_array_length.elna create mode 100644 testsuite/fail_compilation/compile_time_array_ptr.elna 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) { 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(¶meter_type, declaration_type); - std::vector::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(¶meter_type)); + get_identifier(parameter_name.c_str()), function_args_iter_cond(¶meter_type)); DECL_CONTEXT(declaration_tree) = fndecl; DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_type); argument_chain = chainon(argument_chain, declaration_tree); function_args_iter_next(¶meter_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(); 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() != 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 *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 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(scode); - - switch (code) + switch (static_cast(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 + namespace elna::gcc { using symbol_table = boot::symbol_map; @@ -67,14 +69,14 @@ namespace elna::gcc template 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 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 *elna_global_decls; extern std::vector 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); -- cgit v1.2.3