diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 50b253e..1e87106 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,13 +3,13 @@ # Url: https://hub.docker.com/layers/library/archlinux/latest/images/sha256-a10e51dd0694d6c4142754e9d06cbce7baf91ace8031a30df37064d1091ab414?context=explore FROM archlinux@sha256:a10e51dd0694d6c4142754e9d06cbce7baf91ace8031a30df37064d1091ab414 -# Update the package database and install clang +# Update the package database # 1. system tools # 2. build/test tools # 3. libraries RUN pacman -Syyu --noconfirm \ - && pacman -Syyu --noconfirm git less vim sudo base-devel python-pip \ - && pacman -Syyu --noconfirm clang cmake make ninja meson shellcheck \ + && pacman -Syyu --noconfirm git less vim sudo python-pip wget which pkgconf \ + && pacman -Syyu --noconfirm cmake make gcc ninja meson shellcheck \ && pacman -Syyu --noconfirm gtk4 gtkmm-4.0 boost spdlog fmt libxml++-5.0 # Create a non-root user 'dev' @@ -21,10 +21,49 @@ RUN useradd -ms /bin/bash dev \ COPY --from=library/docker:latest /usr/local/bin/docker /usr/bin/docker COPY --from=docker/compose:latest /usr/local/bin/docker-compose /usr/bin/docker-compose +# Allow dev to execute docker without sudo RUN groupadd docker &&\ usermod -aG docker dev &&\ newgrp docker +# Switch to the 'dev' user +USER dev + +# Add cached layer with the latest LLVM-${LLVM_VER} +ARG LLVM_VER=19.1.1 +ENV LLVM_VER=${LLVM_VER} +RUN sudo mkdir -p /home/artifacts +ADD https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/LLVM-${LLVM_VER}-Linux-X64.tar.xz /home/artifacts/ + +# Create the LLVM directory and extract only binaries into it +RUN sudo mkdir -p /home/LLVM-${LLVM_VER} +RUN sudo tar -xJf /home/artifacts/LLVM-${LLVM_VER}-Linux-X64.tar.xz -C /home/LLVM-${LLVM_VER} --strip-components=1 \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-19 \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang++ \ + LLVM-${LLVM_VER}-Linux-X64/bin/lld \ + LLVM-${LLVM_VER}-Linux-X64/bin/ld.lld \ + LLVM-${LLVM_VER}-Linux-X64/bin/ld64.lld \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-scan-deps \ + LLVM-${LLVM_VER}-Linux-X64/bin/llvm-symbolizer \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-format \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-tidy \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-apply-replacements \ + LLVM-${LLVM_VER}-Linux-X64/include/ \ + LLVM-${LLVM_VER}-Linux-X64/lib/ \ + LLVM-${LLVM_VER}-Linux-X64/libexec/ \ + LLVM-${LLVM_VER}-Linux-X64/local/ \ + LLVM-${LLVM_VER}-Linux-X64/share/ + +# Add /home/LLVM-${LLVM_VER}/bin to the PATH environment variable +ENV PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}" + +# Add extra tools +RUN sudo mkdir -p /home/tools +ADD https://raw.githubusercontent.com/llvm/llvm-project/refs/heads/main/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py /home/tools/ +RUN sudo chmod -R a+x /home/tools/ +RUN sudo chown -R dev /home/tools/ + # Add the custom bash prompt with branch info RUN printf '\n\ function modify_prompt { \n\ @@ -37,9 +76,6 @@ function modify_prompt { \n\ } \n\ modify_prompt\n' >> /home/dev/.bashrc -# Switch to the 'dev' user -USER dev - RUN git config --global core.editor vim # Set the default working directory diff --git a/.devcontainer/post_create_config.sh b/.devcontainer/post_create_config.sh index 65b424d..9941468 100755 --- a/.devcontainer/post_create_config.sh +++ b/.devcontainer/post_create_config.sh @@ -1,4 +1,7 @@ -sleep 1 +sleep 5 + +sudo chmod -R a+x /home/tools/ +sudo chown -R dev /home/tools/ # Check that ejabberd server started successfully red='\e[1;31m' diff --git a/.forgejo/workflows/pr_check.yaml b/.forgejo/workflows/pr_check.yaml new file mode 100644 index 0000000..3f7432e --- /dev/null +++ b/.forgejo/workflows/pr_check.yaml @@ -0,0 +1,188 @@ +name: PR Check +run-name: ${{ github.actor }} is testing +on: [push] +jobs: + on-push-commit-check: + runs-on: archlinux-latest + steps: + - name: Setup environment - Install pacman packages + shell: sh + run: | + pacman -Syyu --noconfirm + pacman -S --noconfirm git less vim sudo python-pip wget which pkgconf nodejs-lts-iron + pacman -S --noconfirm cmake make gcc ninja meson + pacman -S --noconfirm gtk4 gtkmm-4.0 boost spdlog fmt libxml++-5.0 + + - name: Setup environment - Install LLVM-19.1.1 + run: | + export LLVM_VER=19.1.1 + + echo "::group::Download LLVM-${LLVM_VER}" + wget https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/LLVM-${LLVM_VER}-Linux-X64.tar.xz -O /LLVM-${LLVM_VER}-Linux-X64.tar.xz + echo "::endgroup::" + + echo "::group::Extracting LLVM-${LLVM_VER}" + mkdir -p /home/LLVM-${LLVM_VER}/ + tar -xf /LLVM-${LLVM_VER}-Linux-X64.tar.xz -C "/home/LLVM-${LLVM_VER}/" --strip-components=1 \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-19 \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang++ \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-scan-deps \ + LLVM-${LLVM_VER}-Linux-X64/bin/llvm-symbolizer \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-format \ + LLVM-${LLVM_VER}-Linux-X64/bin/clang-tidy \ + LLVM-${LLVM_VER}-Linux-X64/include/ \ + LLVM-${LLVM_VER}-Linux-X64/lib/ \ + LLVM-${LLVM_VER}-Linux-X64/libexec/ \ + LLVM-${LLVM_VER}-Linux-X64/local/ \ + LLVM-${LLVM_VER}-Linux-X64/share/ + + rm /LLVM-${LLVM_VER}-Linux-X64.tar.xz + echo "::endgroup::" + + echo "LLVM version ${LLVM_VER}" + echo "Available LLVM binaries:" + ls -la /home/LLVM-${LLVM_VER}/bin/ + + - name: List CI environment variables + run: | + echo "Runner OS: ${{ runner.os }}" + echo "Job triggered event: ${{ github.event_name }}" + echo "Repository name: ${{ github.repository }}" + echo "Workspace path: ${{ github.workspace }}" + echo "Actor: ${{ github.actor }}" + echo "Ref: ${{ github.ref }}" + echo "Ref name: ${{ github.ref_name }}" + echo "SHA: ${{ github.sha }}" + echo "PATH: ${PATH}" + + - name: Check out repository code + run: | + export GIT_TERMINAL_PROMPT=0 + mkdir -p ${{ github.workspace }} + cd ${{ github.workspace }} + + echo "Configure project settings and remote credentials" + git init + git config credential.helper store + git remote add origin https://${{ github.token }}@helicopter.myftp.org/git/Larra/larra + + echo "Fetch repo state on pushed commit" + git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +${{ github.sha }}:${{ github.ref }} + + echo "Checkout to fetched repo state" + git checkout ${{ github.ref }} + + - name: Show repo content + run: | + echo "github.workspace content" + ls -la ${{ github.workspace }} + echo "This job's status is ${{ job.status }}." + + - name: Store list of repo files + run: | + cd ${{ github.workspace }} + find -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.c" -o -name "*.cpp" \) > repo_files_to_check.txt + find -type f \( -name "*.c" -o -name "*.cpp" \) > repo_sources_to_check.txt + + #- name: Delete cache + # run: | + # rm -rf ${{ runner.tool_cache }}/cache-llvm-19-restore + # + #- name: Try restore LLVM-19 binaries from cache + # id: cache-llvm-19-bins-restore + # uses: actions/cache@v4 + # with: + # path: /LLVM-${LLVM_VER}-Linux-X64-small.tar.xz + # key: LLVM-${LLVM_VER}-Linux-X64-small + # + #- name: Save LLVM-19 to cache + # if: steps.cache-llvm-19-bins-restore.outputs.cache-hit != 'true' + # id: cache-llvm-19-save + # uses: actions/cache/save@v4 + # with: + # path: /LLVM-${LLVM_VER}-Linux-X64-small.tar.xz + # key: LLVM-${LLVM_VER}-Linux-X64-small + + - name: Check clang-format + run: | + export LLVM_VER=19.1.1 + export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}" + cd ${{ github.workspace }} + export REPO_FILES=$(cat repo_files_to_check.txt) + + printf "\nList of files to be checked:\n" + echo "::group::files to be checked" + for FILE in $REPO_FILES; do printf "\t ${{ github.workspace }}/$FILE \n"; done + echo "::endgroup::" + + for FILE in $REPO_FILES; do clang-format -i ${{ github.workspace }}/$FILE --dry-run --Werror; done + echo "No clang-format violations detected!" + + - name: GCC build + run: | + mkdir -p ${{ github.workspace }}/build_gcc + cmake -Wno-dev \ + -DCMAKE_C_COMPILER=gcc \ + -DCMAKE_CXX_COMPILER=g++ \ + -S ${{ github.workspace }} \ + -B ${{ github.workspace }}/build_gcc \ + -GNinja -DCMAKE_BUILD_TYPE=Release \ + -DENABLE_EXAMPLES=ON \ + -DENABLE_TESTS=ON + cmake --build ${{ github.workspace }}/build_gcc --parallel `nproc` + + - name: GCC unit tests + run: | + cd ${{ github.workspace }}/build_gcc + ./larra_xmpp_tests + + - name: Check clang-tidy + run: | + export LLVM_VER=19.1.1 + export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}" + cd ${{ github.workspace }} + + sed -i 's|/usr/sbin/g++|/home/LLVM-19.1.1/bin/clang++ -stdlib=libc++ -I/home/LLVM-${LLVM_VER}/include/c++/v1|' build_gcc/compile_commands.json + sed -i 's|-fdeps-format=p1689r5||' build_gcc/compile_commands.json + sed -i 's|-fmodules-ts||' build_gcc/compile_commands.json + sed -i 's|-fmodule-mapper=.*\.modmap||' build_gcc/compile_commands.json + + wget https://raw.githubusercontent.com/llvm/llvm-project/refs/heads/main/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py + python run-clang-tidy.py \ + -warnings-as-errors=* \ + -use-color \ + -exclude-header-filter .*build.* \ + -header-filter .hpp \ + -p ${{ github.workspace }}/build_gcc/ \ + -config-file ${{ github.workspace }}/.clang-tidy \ + \ + ${{ github.workspace }}/examples \ + ${{ github.workspace }}/library/ \ + ${{ github.workspace }}/src/ + + echo "No clang-tidy violations detected!" + + #- name: Clang build with -fsanitize=address + # run: | + # export LLVM_VER=19.1.1 + # export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}" + # mkdir -p ${{ github.workspace }}/build_clang + # cmake -Wno-dev \ + # -DCMAKE_C_COMPILER=clang \ + # -DCMAKE_CXX_COMPILER=clang++ \ + # -S ${{ github.workspace }} \ + # -B ${{ github.workspace }}/build_clang \ + # -GNinja -DCMAKE_BUILD_TYPE=Release \ + # -DENABLE_EXAMPLES=ON \ + # -DENABLE_TESTS=ON \ + # -DCMAKE_CXX_FLAGS="-stdlib=libc++ -I/home/LLVM-${LLVM_VER}/include/c++/v1 -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr" \ + # -DCMAKE_EXE_LINKER_FLAGS="-L/home/LLVM-${LLVM_VER}/lib/ -Wl,-rpath,/home/LLVM-${LLVM_VER}/lib -lc++ -lc++abi -lm -lc -lgcc_s -lgcc -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr" + # cmake --build ${{ github.workspace }}/build_clang --parallel `nproc` + + #- name: Clang unit tests with -fsanitize=address + # run: | + # export LLVM_VER=19.1.1 + # export PATH="/home/LLVM-${LLVM_VER}/bin:${PATH}" + # cd ${{ github.workspace }}/build_clang + # ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests diff --git a/.gitignore b/.gitignore index da9f39d..d45daeb 100644 --- a/.gitignore +++ b/.gitignore @@ -29,5 +29,4 @@ ext/ libxmlplusplus-prefix/ spdlog.pc build* -larra temp* diff --git a/.vscode/launch.json b/.vscode/launch.json index 1ee66a5..2a94c2f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ "program": "${workspaceFolder}/build/examples/output/connect", "args": [], "cwd": "${workspaceFolder}", - "preLaunchTask": "Build Debug GCC" + "preLaunchTask": "GCC: Build" } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 55a74f4..ebd295f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,6 +3,45 @@ // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ + // + // Checkers/Analyzers tasks + // + { + "label": "Checker: clang-format dry-run", + "type": "shell", + "command": "for FILE in $(find . -type f \\( -name '*.c' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \\) ! -path '*build*'); do clang-format -i $FILE --dry-run --Werror; done" + }, + { + "label": "Checker: clang-format fix errors", + "type": "shell", + "command": "for FILE in $(find . -type f \\( -name '*.c' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \\) ! -path '*build*'); do clang-format -i $FILE --Werror; done" + }, + { + // https://clang.llvm.org/extra/clang-tidy/ + "label": "Checker: clang-tidy dry-run", + "type": "shell", + "command": [ + "python /home/tools/run-clang-tidy.py -exclude-header-filter .*build.* -use-color -warnings-as-errors=* -header-filter .hpp -p ${workspaceFolder}/build_clang/ -config-file ${workspaceFolder}/.clang-tidy", + " ${workspaceFolder}/examples", + " ${workspaceFolder}/library/", + " ${workspaceFolder}/src/" + ] + }, + { + // https://clang.llvm.org/extra/clang-tidy/ + "label": "Checker: clang-tidy fix errors", + "type": "shell", + "command": [ + "python /home/tools/run-clang-tidy.py -exclude-header-filter .*build.* -use-color -warnings-as-errors=* -header-filter .hpp -p ${workspaceFolder}/build_clang/ -config-file ${workspaceFolder}/.clang-tidy", + " -fix", + " ${workspaceFolder}/examples", + " ${workspaceFolder}/library/", + " ${workspaceFolder}/src/" + ] + }, + // + // Ejabberd tasks + // { "label": "Ejabberd: show logs", "type": "shell", @@ -11,54 +50,243 @@ ] }, { - "label": "Ejabberd: open shell", + "label": "Ejabberd: show localhost registered users", "type": "shell", "command": [ - "sudo docker exec -it ejabberd sh" + "sudo docker exec -it ejabberd ejabberdctl registered_users localhost" ] }, { - "label": "Build Debug GCC", + "label": "Ejabberd: open shell", + "type": "shell", + "command": [ + "printf 'Example cmd: ejabberdctl registered_users localhost\n\n';", + "sudo docker exec -it ejabberd sh" + ] + }, + // + // GCC build related tasks + // + { + "label": "GCC: Clean build folder", + "type": "shell", + "command": "if [ -n \"$(ls -A ${workspaceFolder}/build)\" ]; then rm -rf ${workspaceFolder}/build/*; fi", + "hide": true + }, + { + "label": "GCC: Configure Debug", "type": "shell", "command": [ "cd ${workspaceFolder} &&", "mkdir -p build && cd build &&", - "cmake -Wno-dev -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON .. &&", - "cmake --build . --parallel `nproc`", - "|| ( printf '\n\n\t\\e[31mERROR: Build failed!\\e[0m\n\n\n' && exit 1 )" - ], - "options": { - "env": {} - }, - "presentation": { - "clear": true - }, - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "Build Debug Clang", - "type": "shell", - "command": [ - "cd ${workspaceFolder} &&", - "mkdir -p build_clang && cd build_clang &&", - "cmake -Wno-dev -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON .. &&", - "cmake --build . --parallel `nproc`", - "|| ( printf '\n\n\t\\e[31mERROR: Build failed!\\e[0m\n\n\n' && exit 1 )" + "cmake cmake -Wno-dev ", + " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON .." ], "options": { "env": { - "CC": "/usr/sbin/clang", - "CXX": "/usr/sbin/clang++" + "CC": "/usr/sbin/gcc", + "CXX": "/usr/sbin/g++" } }, "presentation": { "clear": true }, - "problemMatcher": [] + "hide": true + }, + { + "label": "GCC: Build", + "type": "shell", + "command": [ + "cd ${workspaceFolder}/build &&", + "cmake --build . --parallel `nproc`", + "|| ( printf '\n\n\t\\e[31mERROR: Build failed!\\e[0m\n\n\n' && exit 1 )" + ], + "presentation": { + "clear": true + }, + "hide": true, + "group": { + "kind": "build" + } + }, + { + "label": "GCC: Configure and build Debug", + "type": "shell", + "command": "echo Finished!", + "presentation": { + "clear": true + }, + "dependsOrder": "sequence", + "dependsOn":[ + "GCC: Clean build folder", + "GCC: Configure Debug", + "GCC: Build" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + // + // Clang build related tasks + // + { + "label": "Clang: Configure Debug", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "cmake -Wno-dev ", + " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ", + " -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++\"", + " -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++\" .." + ], + "options": { + "env": { + "CC": "clang", + "CXX": "clang++" + } + }, + "presentation": { + "clear": true + }, + "hide": true + }, + { + "label": "Clang: Configure Debug with -fsanitize=address", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "cmake -Wno-dev ", + " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON", + // + // Uncomment for GCC standart library: libstdc++ + //" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"", + //" -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++ -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"", + // + " -DCMAKE_CXX_FLAGS=\"-stdlib=libc++ -I/home/LLVM-19.1.1/include/c++/v1 -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"", + " -DCMAKE_EXE_LINKER_FLAGS=\"-L/home/LLVM-19.1.1/lib/ -Wl,-rpath,/home/LLVM-19.1.1/lib -lc++ -lc++abi -lm -lc -lgcc_s -lgcc -fuse-ld=lld -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"", + " .." + ], + "options": { + "env": { + "CC": "clang", + "CXX": "clang++" + } + }, + "presentation": { + "clear": true + }, + "hide": true + }, + { + // + // Useful links: + // - https://github.com/google/sanitizers/wiki/addresssanitizerflags + // - https://clang.llvm.org/docs/AddressSanitizer.html + // + "label": "Clang: Exec gtest with -fsanitize=address", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "ASAN_SYMBOLIZER_PATH=llvm-symbolizer ASAN_OPTIONS=detect_stack_use_after_return=1:check_initialization_order=1:detect_leaks=1:atexit=1:abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"", + ], + "presentation": { + "clear": true + }, + "dependsOrder": "sequence", + "dependsOn":[ + "Clang: Clean build folder", + "Clang: Configure Debug with -fsanitize=address", + "Clang: Build" + ] + }, + { + "label": "Clang: Configure Debug with -fsanitize=memory", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "cmake -Wno-dev ", + " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ", + " -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\"", + " -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\" ..", + ], + "options": { + "env": { + "CC": "clang", + "CXX": "clang++" + } + }, + "presentation": { + "clear": true + }, + "hide": true + }, + { + // + // Useful links: + // - https://github.com/google/sanitizers/wiki/MemorySanitizer + // - https://clang.llvm.org/docs/MemorySanitizer.html + // + "label": "Clang: Exec gtest with -fsanitize=memory", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"", + ], + "presentation": { + "clear": true + }, + "dependsOrder": "sequence", + "dependsOn":[ + "Clang: Clean build folder", + "Clang: Configure Debug with -fsanitize=memory", + "Clang: Build" + ] + }, + { + "label": "Clang: Build", + "type": "shell", + "command": [ + "cd ${workspaceFolder}/build_clang &&", + "cmake --build . --parallel `nproc`", + "|| ( printf '\n\n\t\\e[31mERROR: Build failed!\\e[0m\n\n\n' && exit 1 )" + ], + "presentation": { + "clear": true + }, + "group": { + "kind": "build" + }, + "hide": true + }, + { + "label": "Clang: Configure and build Debug", + "type": "shell", + "command": [ + "cd ${workspaceFolder} &&", + "mkdir -p build_clang && cd build_clang &&", + "MSAN_SYMBOLIZER_PATH=llvm-symbolizer MSAN_OPTIONS=abort_on_error=1 ./larra_xmpp_tests ; echo \"exit code: $?\"", + ], + "presentation": { + "clear": true + }, + "dependsOrder": "sequence", + "dependsOn":[ + "Clang: Clean build folder", + "Clang: Configure Debug", + "Clang: Build" + ] + }, + { + "label": "Clang: Clean build folder", + "type": "shell", + "command": "if [ -n \"$(ls -A ${workspaceFolder}/build_clang)\" ]; then rm -rf ${workspaceFolder}/build_clang/*; fi", + "hide": true } ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c4cf7e..6193f1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,8 +163,10 @@ add_library(larra::larra_xmpp ALIAS larra_xmpp) target_compile_features(larra_xmpp PUBLIC cxx_std_23) - -target_compile_options(larra_xmpp PUBLIC -Wno-changes-meaning) +target_compile_options(larra_xmpp PUBLIC + "$<$:-Wno-changes-meaning>" + "$<$:-Wno-non-template-friend>" +) target_include_directories(larra_xmpp PUBLIC $ diff --git a/library/include/larra/client/client.hpp b/library/include/larra/client/client.hpp index ac91a07..5ee658c 100644 --- a/library/include/larra/client/client.hpp +++ b/library/include/larra/client/client.hpp @@ -74,7 +74,7 @@ struct Client { private: bool active = true; - XmlStream connection; + XmlStream connection{}; BareJid jid; }; diff --git a/library/include/larra/features.hpp b/library/include/larra/features.hpp index f4ffc2e..0c99448 100644 --- a/library/include/larra/features.hpp +++ b/library/include/larra/features.hpp @@ -11,7 +11,7 @@ namespace larra::xmpp { enum class Required : bool { kNotRequired = false, kRequired = true }; struct SaslMechanisms { - std::vector mechanisms; + std::vector mechanisms{}; [[nodiscard]] static auto Parse(const xmlpp::Element*) -> SaslMechanisms; }; diff --git a/library/include/larra/impl/public_cast.hpp b/library/include/larra/impl/public_cast.hpp new file mode 100644 index 0000000..111909a --- /dev/null +++ b/library/include/larra/impl/public_cast.hpp @@ -0,0 +1,34 @@ +#pragma once +#include +#include + +namespace larra::xmpp::impl { + +template +struct PublicCastTag { + friend constexpr auto MagicGetPrivateMember(PublicCastTag); +}; + +template +struct PublicCast {}; + +template +struct PublicCast { + friend constexpr auto MagicGetPrivateMember(PublicCastTag) { + return ptr; + } +}; + +template +struct PublicCast { + friend constexpr auto MagicGetPrivateMember(PublicCastTag) { + return ptr; + } +}; + +template +constexpr auto GetPrivateMember(const T&) { + return MagicGetPrivateMember(PublicCastTag, I>{}); +}; + +} // namespace larra::xmpp::impl diff --git a/library/include/larra/printer_stream.hpp b/library/include/larra/printer_stream.hpp index 5e3f8b6..d2cfdba 100644 --- a/library/include/larra/printer_stream.hpp +++ b/library/include/larra/printer_stream.hpp @@ -138,7 +138,7 @@ struct boost::asio::ssl::stream> : public boost auto next_layer() -> next_layer_type& { return static_cast(this->Base::next_layer()); } - auto next_layer() const -> const next_layer_type& { + [[nodiscard]] auto next_layer() const -> const next_layer_type& { return static_cast(this->Base::next_layer()); } }; diff --git a/library/include/larra/stream.hpp b/library/include/larra/stream.hpp index c66f4a1..e25b882 100644 --- a/library/include/larra/stream.hpp +++ b/library/include/larra/stream.hpp @@ -19,8 +19,8 @@ struct BasicStream { static constexpr auto kAddXmlDecl = true; static inline const std::string kDefaultPrefix = ""; static inline const std::string kDefaultName = "stream:stream"; - FromType from; - ToType to; + FromType from{}; + ToType to{}; std::optional id; std::optional version; std::optional xmlLang; @@ -46,7 +46,8 @@ struct BasicStream { } template - [[nodiscard]] constexpr auto XmlLang(this Self&& self, std::optional value) -> BasicStream { + [[nodiscard]] constexpr auto XmlLang(this Self&& self, std::optional value) // NOLINT(cppcoreguidelines-missing-std-forward) + -> BasicStream { return utils::FieldSetHelper::With<"xmlLang", BasicStream>(std::forward_like(self), std::move(value)); } diff --git a/library/include/larra/user_account.hpp b/library/include/larra/user_account.hpp index 906ea56..f46291f 100644 --- a/library/include/larra/user_account.hpp +++ b/library/include/larra/user_account.hpp @@ -20,7 +20,8 @@ struct PlainUserAccount { struct EncryptionUserAccount : PlainUserAccount { using PlainUserAccount::PlainUserAccount; constexpr EncryptionUserAccount(PlainUserAccount base) : PlainUserAccount{std::move(base)} {}; - constexpr EncryptionUserAccount(BareJid jid, std::string password) : PlainUserAccount{std::move(jid), std::move(password)} {}; + constexpr EncryptionUserAccount(BareJid jid, std::string password) : + PlainUserAccount{.jid = std::move(jid), .password = std::move(password)} {}; }; struct EncryptionRequiredUserAccount : EncryptionUserAccount { @@ -35,7 +36,7 @@ using UserAccountVariant = std::variant - constexpr auto Jid(this Self&& self, BareJid value) -> UserAccount { + constexpr auto Jid(this Self&& self, BareJid value) -> UserAccount { // NOLINT(cppcoreguidelines-missing-std-forward) return std::visit( [&](auto& ref) -> std::decay_t { return {std::forward_like(ref).Jid(std::move(value))}; @@ -43,7 +44,7 @@ struct UserAccount : UserAccountVariant { self); } template - constexpr auto Password(this Self&& self, std::string value) -> UserAccount { + constexpr auto Password(this Self&& self, std::string value) -> UserAccount { // NOLINT(cppcoreguidelines-missing-std-forward) return std::visit( [&](auto& ref) -> std::decay_t { return std::forward_like(ref).Password(std::move(value)); @@ -51,7 +52,7 @@ struct UserAccount : UserAccountVariant { self); } template - constexpr auto Jid(this Self&& self) -> decltype(auto) { + constexpr auto Jid(this Self&& self) -> decltype(auto) { // NOLINT(cppcoreguidelines-missing-std-forward) return std::visit(std::declval()))>( [](auto& ref) -> decltype(auto) { return std::forward_like(ref.jid); @@ -59,7 +60,7 @@ struct UserAccount : UserAccountVariant { self); } template - constexpr auto Password(this Self&& self) -> decltype(auto) { + constexpr auto Password(this Self&& self) -> decltype(auto) { // NOLINT(cppcoreguidelines-missing-std-forward) return std::visit(std::declval()))>( [](auto& ref) -> decltype(auto) { return std::forward_like(ref.password); diff --git a/library/include/larra/utils.hpp b/library/include/larra/utils.hpp index bca4277..bdd7574 100644 --- a/library/include/larra/utils.hpp +++ b/library/include/larra/utils.hpp @@ -83,9 +83,9 @@ struct FieldsDescription { * \param value new value for field * \return an object of type std::decay_t with data from T with fields from \ref self and the \ref value of the field \ref ptr */ - template // NOLINTNEXTLINE - constexpr auto With(Type(T::* ptr), Self&& self, Value&& value) const -> std::decay_t - requires(std::is_constructible_v...> && std::constructible_from, T> && + template + constexpr auto With(Type(T::* ptr), Self&& self, Value&& value) const // NOLINT(cppcoreguidelines-missing-std-forward) + requires(std::is_constructible_v...> && std::is_constructible_v, T> && std::is_constructible_v && impl::SetConcept) { return std::decay_t{utempl::Unpack(this->tuple, [&](auto... fs) -> T { diff --git a/library/include/larra/xml_stream.hpp b/library/include/larra/xml_stream.hpp index 168bfff..7aaeb4b 100644 --- a/library/include/larra/xml_stream.hpp +++ b/library/include/larra/xml_stream.hpp @@ -52,7 +52,7 @@ class Parser : private xmlpp::SaxParser { auto ParseChunk(std::string_view str) -> const _xmlError*; - std::stack context; + std::stack context{}; xmlpp::Document& doc; private: @@ -98,7 +98,7 @@ struct XmlStream : Stream { return *this; } - auto next_layer() const -> const Stream& { + [[nodiscard]] auto next_layer() const -> const Stream& { return *this; } @@ -313,7 +313,7 @@ struct XmlStream : Stream { XmlStream(XmlStream&& other) = default; - std::unique_ptr streambuf; // Not movable :( + std::unique_ptr streambuf{}; // Not movable :( }; } // namespace larra::xmpp diff --git a/library/src/encryption.cpp b/library/src/encryption.cpp index 5a7b2fd..986359a 100644 --- a/library/src/encryption.cpp +++ b/library/src/encryption.cpp @@ -53,33 +53,39 @@ struct DataHolder { }; consteval auto GetDataForTag(sha512sum::EncryptionTag) { - return DataHolder{[] { - return EVP_sha512(); - }, - kSha512ResultSize, - [](auto... args) { - return SHA512(args...); - }}; + return DataHolder{.first = + [] { + return EVP_sha512(); + }, + .second = kSha512ResultSize, + .third = + [](auto... args) { + return SHA512(args...); + }}; } consteval auto GetDataForTag(sha256sum::EncryptionTag) { - return DataHolder{[] { - return EVP_sha256(); - }, - kSha256ResultSize, - [](auto... args) { - return SHA256(args...); - }}; + return DataHolder{.first = + [] { + return EVP_sha256(); + }, + .second = kSha256ResultSize, + .third = + [](auto... args) { + return SHA256(args...); + }}; } consteval auto GetDataForTag(sha1sum::EncryptionTag) { - return DataHolder{[] { - return EVP_sha256(); - }, - kSha1ResultSize, - [](auto... args) { - return SHA1(args...); - }}; + return DataHolder{.first = + [] { + return EVP_sha256(); + }, + .second = kSha1ResultSize, + .third = + [](auto... args) { + return SHA1(args...); + }}; } template diff --git a/library/src/jid.cpp b/library/src/jid.cpp index f9ca838..76b80ab 100644 --- a/library/src/jid.cpp +++ b/library/src/jid.cpp @@ -4,17 +4,17 @@ namespace larra::xmpp { auto ParseBareJid(std::string_view jid, std::size_t at) -> BareJid { - return {static_cast(jid.substr(0, at)), static_cast(jid.substr(at + 1))}; + return {.username = static_cast(jid.substr(0, at)), .server = static_cast(jid.substr(at + 1))}; } auto ParseBareResourceJid(std::string_view jid, std::size_t slash) -> BareResourceJid { - return {static_cast(jid.substr(0, slash)), static_cast(jid.substr(slash + 1))}; + return {.server = static_cast(jid.substr(0, slash)), .resource = static_cast(jid.substr(slash + 1))}; } auto ParseFullJid(std::string_view jid, std::size_t at, std::size_t slash) -> FullJid { - return {static_cast(jid.substr(0, at)), - static_cast(jid.substr(at + 1, slash - at - 1)), - static_cast(jid.substr(slash + 1))}; + return {.username = static_cast(jid.substr(0, at)), + .server = static_cast(jid.substr(at + 1, slash - at - 1)), + .resource = static_cast(jid.substr(slash + 1))}; } auto BareJid::Parse(std::string_view jid) -> BareJid {