diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fed0152..5b760ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,90 +7,68 @@ on: branches: [ main ] jobs: - format-check: + static-analysis: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Install clang-format + + - name: Install Linting Tools run: | sudo apt update --yes - sudo apt install --yes clang-format + sudo apt install --yes clang-format cppcheck + - name: Run clang-format run: | - clang-format -style=file -i --dry-run --Werror $(find . \( -name "*.cpp" -o -name "*.cc" -o -name "*.cxx" -o -name "*.c" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" -o -name "*.inl" \) -not -path "*/build*/*") + find . \( -name "*.cpp" -o -name "*.cc" -o -name "*.cxx" -o -name "*.c" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" -o -name "*.inl" \) \ + -not -path "*/build*/*" | xargs clang-format -style=file --dry-run --Werror - build-gcc14: - runs-on: ubuntu-22.04 - container: gcc:14 - steps: - - uses: actions/checkout@v4 - - name: Install dependencies - run: | - apt update --yes - apt install --yes cmake clang-tidy - - name: Build + - name: Run Cppcheck run: | - mkdir build-gcc14 - cd build-gcc14 - cmake -DBUILD_TESTS=ON -DPRODUCTION=ON ../ - make - - name: Archive build artifacts - uses: actions/upload-artifact@v4 - with: - name: build-gcc14 - path: build-gcc14/ + # --library=googletest: Pomaga zrozumieć makra TEST_F, EXPECT_EQ itp. + # -DTEST_F(A,B)=void A##B(): "Zaślepkowe" definicje makr, jeśli biblioteka nie wystarczy. + # -I include: Wskazuje folder z nagłówkami (dostosuj, jeśli masz inną nazwę). + cppcheck --enable=all \ + --suppress=unusedFunction \ + --suppress=missingIncludeSystem \ + --library=googletest \ + --inline-suppr \ + --error-exitcode=1 \ + -I include \ + . -i build/ - test-gcc14: + build-and-test: + needs: static-analysis runs-on: ubuntu-22.04 - container: gcc:14 - needs: build-gcc14 - steps: - - uses: actions/checkout@v4 - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: build-gcc14 - path: build-gcc14 - - name: Run unit tests - run: | - chmod +x build-gcc14/tests/minic_tests - cd build-gcc14 - ./tests/minic_tests + strategy: + fail-fast: false + matrix: + gcc_version: [14, 15] + build_type: [Debug, Release] + + container: gcc:${{ matrix.gcc_version }} - build-gcc15: - runs-on: ubuntu-22.04 - container: gcc:15 steps: - uses: actions/checkout@v4 - - name: Install dependencies + + - name: Install Build Dependencies run: | apt update --yes apt install --yes cmake clang-tidy + + - name: Configure CMake + run: | + cmake -B build -S . \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DUSE_SANITIZERS=${{ matrix.build_type == 'Debug' && 'ON' || 'OFF' }} \ + -DBUILD_TESTS=ON \ + -DBUILD_BENCHMARKS=${{ matrix.build_type == 'Release' && 'ON' || 'OFF' }} \ + -DPRODUCTION=${{ matrix.build_type == 'Release' && 'ON' || 'OFF' }} + - name: Build run: | - mkdir build-gcc15 - cd build-gcc15 - cmake -DBUILD_TESTS=ON -DPRODUCTION=ON ../ - make - - name: Archive build artifacts - uses: actions/upload-artifact@v4 - with: - name: build-gcc15 - path: build-gcc15/ + cmake --build build -j $(nproc) - test-gcc15: - runs-on: ubuntu-22.04 - container: gcc:15 - needs: build-gcc15 - steps: - - uses: actions/checkout@v4 - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: build-gcc15 - path: build-gcc15 - name: Run unit tests run: | - chmod +x build-gcc15/tests/minic_tests - cd build-gcc15 - ./tests/minic_tests + cd build + ctest --output-on-failure \ No newline at end of file diff --git a/include/minic/IR.hpp b/include/minic/IR.hpp index 92bd890..a7c2c07 100644 --- a/include/minic/IR.hpp +++ b/include/minic/IR.hpp @@ -61,7 +61,7 @@ class IRInstruction * @param op1 Optional first operand. * @param op2 Optional second operand. */ - IRInstruction(IROpcode op, + explicit IRInstruction(IROpcode op, const std::string& res = {}, const std::string& op1 = {}, const std::string& op2 = {}) diff --git a/include/minic/Parser.hpp b/include/minic/Parser.hpp index 80afcbb..276c8f6 100644 --- a/include/minic/Parser.hpp +++ b/include/minic/Parser.hpp @@ -25,7 +25,7 @@ class Parser * @brief Constructs a Parser with the given token stream. * @param tokens A reference to a vector of Token objects produced by the Lexer. */ - Parser(const std::vector& tokens); + explicit Parser(const std::vector& tokens); /** * @brief Parses the entire token stream and returns a Program AST. diff --git a/src/CodeGenerator.cpp b/src/CodeGenerator.cpp index 67066de..de9366d 100644 --- a/src/CodeGenerator.cpp +++ b/src/CodeGenerator.cpp @@ -383,12 +383,12 @@ std::string CodeGenerator::get_loc(const std::string& name) std::string CodeGenerator::find_label_with_substr(const std::string& substr) const { - for (const auto& lbl : block_labels_) - { - if (lbl.find(substr) != std::string::npos) - return lbl; - } - return ""; + auto it = std::find_if(block_labels_.begin(), block_labels_.end(), + [&substr](const std::string& lbl) + { + return lbl.find(substr) != std::string::npos; + }); + return it != block_labels_.end() ? *it : ""; } std::string CodeGenerator::infer_target_label_for_current_block() const @@ -432,8 +432,10 @@ void CodeGenerator::allocate_stack(const IRFunction& func) } std::vector params; - for (const auto& p : func.parameters) - params.push_back(p.name); + std::transform(func.parameters.begin(), func.parameters.end(), + std::back_inserter(params), + [](const auto& p) + { return p.name; }); std::vector locals; for (const auto& v : all_vars) diff --git a/tests/TestExample.cpp b/tests/TestExample.cpp deleted file mode 100644 index 50fc6b4..0000000 --- a/tests/TestExample.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include - -TEST(ExampleTest, Example) -{ - ASSERT_EQ(1, 1); -} diff --git a/tests/TestIRGenerator.cpp b/tests/TestIRGenerator.cpp index ed46a91..166a2dc 100644 --- a/tests/TestIRGenerator.cpp +++ b/tests/TestIRGenerator.cpp @@ -107,27 +107,24 @@ class IRGeneratorTest : public ::testing::Test { if (!block) return false; - for (const auto& instr : block->instructions) - { - if (instr.opcode == op && (res.empty() || instr.result == res) && (op1.empty() || instr.operand1 == op1) && (op2.empty() || instr.operand2 == op2)) + return std::any_of(block->instructions.begin(), block->instructions.end(), + [op, &res, &op1, &op2](const auto& instr) { - return true; - } - } - return false; + return instr.opcode == op && (res.empty() || instr.result == res) && (op1.empty() || instr.operand1 == op1) && (op2.empty() || instr.operand2 == op2); + }); } - // Helper to find block by label prefix - const minic::BasicBlock* FindBlockByLabelPrefix(const minic::IRFunction* func, const std::string& prefix) + const minic::BasicBlock* FindBlockByLabelPrefix(const minic::IRFunction* func, std::string_view prefix) { - for (const auto& block : func->blocks) - { - if (block->label.find(prefix) == 0) + if (!func) + return nullptr; + + auto it = std::find_if(func->blocks.begin(), func->blocks.end(), + [prefix](const auto& block) { - return block.get(); - } - } - return nullptr; + return block && block->label.compare(0, prefix.size(), prefix) == 0; + }); + return it != func->blocks.end() ? it->get() : nullptr; } }; @@ -741,17 +738,4 @@ TEST_F(IRGeneratorTest, PrivateCurrentPointers) EXPECT_EQ(generator_.current_function_->name, "test"); } -TEST_F(IRGeneratorTest, GenerateIRForFullProgram) -{ - std::string source = "int main() {\n" - " int x = 5;\n" - " if (x > 0) {\n" - " while (x < 10) {\n" - " x = x - 1;\n" - " }\n" - " }\n" - " return x;\n" - "}\n"; -} - } // namespace minic \ No newline at end of file