GCC Code Coverage Report


Directory: src/
File: src/analysis/analysis-unreachable.cpp
Date: 2025-10-24 11:14:59
Exec Total Coverage
Lines: 23 36 63.9%
Functions: 4 4 100.0%
Branches: 13 18 72.2%

Line Branch Exec Source
1 /* Copyright 2025 Jonathan S. Arney
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * https://github.com/jarney/gyoji/blob/master/LICENSE
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <gyoji-analysis.hpp>
16 #include <stdio.h>
17
18 using namespace Gyoji::mir;
19 using namespace Gyoji::context;
20 using namespace Gyoji::analysis;
21
22 28 AnalysisPassUnreachable::AnalysisPassUnreachable(CompilerContext & _compiler_context)
23 56 : AnalysisPass(_compiler_context, "unreachable analysis")
24 28 {}
25 112 AnalysisPassUnreachable::~AnalysisPassUnreachable()
26 112 {}
27
28 void
29 28 AnalysisPassUnreachable::check(const MIR & mir) const
30 {
31
2/2
✓ Branch 7 taken 270 times.
✓ Branch 8 taken 28 times.
298 for (const auto & function : mir.get_functions().get_functions()) {
32 270 check(*function);
33 }
34 28 }
35
36 270 void AnalysisPassUnreachable::check(const Function & function) const
37 {
38 // Note that we do assume that all empty unreachable
39 // blocks have already been culled.
40
41 // Check for operations after the terminator.
42 // These are by definition unreachable because
43 // the terminator stops execution, so nothing after
44 // that will be reachable.
45 270 const auto & blocks = function.get_blocks();
46
2/2
✓ Branch 5 taken 364 times.
✓ Branch 6 taken 270 times.
634 for (const auto & block_it : blocks) {
47 364 const BasicBlock & block = *block_it.second;
48 364 const std::vector<Gyoji::owned<Operation>> & operations = block.get_operations();
49
4/6
✓ Branch 2 taken 270 times.
✓ Branch 3 taken 94 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 270 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 364 times.
364 if (block.get_reachable_from().size() == 0 && block_it.first != 0) {
50 // Unreachable if the block is unreachable and has anything at all inside it.
51 if (operations.size() != 0) {
52 const auto & op = operations.at(operations.size()-1);
53 get_compiler_context()
54 .get_errors()
55 .add_simple_error(op->get_source_ref(),
56 "Unreachable statement",
57 std::string("Statement is unreachable.")
58 );
59 }
60 }
61 else {
62 // Unreachable if the block is reachable and
63 // there are statements after the return.
64 364 bool terminated = false;
65
2/2
✓ Branch 5 taken 4378 times.
✓ Branch 6 taken 364 times.
4742 for (const auto & op : operations) {
66 4378 const auto & operation = *op;
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4378 times.
4378 if (terminated) {
68 get_compiler_context()
69 .get_errors()
70 .add_simple_error(operation.get_source_ref(),
71 "Unreachable Statement",
72 std::string("Function ")
73 + function.get_name()
74 + std::string(" contains unreachable statement.")
75 );
76 break;
77 }
78 // We found a terminating operation.
79
2/2
✓ Branch 1 taken 364 times.
✓ Branch 2 taken 4014 times.
4378 if (operation.is_terminating()) {
80 364 terminated = true;
81 364 continue;
82 }
83 }
84 }
85 }
86 270 }
87