Repository navigation
Audit: portability & correctness bugs (hardcoded paths, CMake, BigInt, isIncomplete, version detection) #4
Description
Summary
Automated audit found multiple portability, correctness and maintainability bugs that should be fixed before enabling branch protection / release. Most are triggered on CI (ubuntu-24.04, LLVM 22 apt.llvm.org) or on a fresh clone away from /home/sergio.
1. CMakeLists.txt:23,38 – hardcoded clang-cpp / LLVM search – CI failure 🔴
Location: CMakeLists.txt:23 find_library(CLANG_CPP_LIB clang-cpp HINTS /usr/lib) and :38 find_library(LLVM_SINGLE_LIB LLVM-22 HINTS /usr/lib /usr/lib/llvm)
Evidence:
- CI log:
Found LLVM 22.1.8 at /usr/lib/llvm-22/lib/cmake/llvm→CMake Error at CMakeLists.txt:25 (message): clang-cpp not found libclang-cpp22-devonapt.llvm.org/nobleinstalls:Unversioned/usr/lib/llvm-22/lib/libclang-cpp.so -> libclang-cpp.so.22.1 /usr/lib/x86_64-linux-gnu/libclang-cpp.so.22.1 (versioned) /usr/lib/x86_64-linux-gnu/libclang-cpp22.so (dev)libclang-cpp.soonly exists at/usr/lib/llvm-22/lib, not in default system search. SimilarlylibLLVM-22.solives at/usr/lib/llvm-22/lib/libLLVM-22.so.- Arch layout (
/usr/lib/libclang-cpp.so,/usr/include) works locally, so bug only visible on CI.
Expected: Support both layouts:
find_library(CLANG_CPP_LIB NAMES clang-cpp clang-cpp-22
HINTS /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/llvm-22/lib ${LLVM_LIBRARY_DIRS} ${LLVM_DIR}/../..)
find_path(CLANG_INCLUDE_DIRS NAMES clang/Basic/Version.h
HINTS /usr/include /usr/lib/llvm-22/include ${LLVM_INCLUDE_DIRS})
find_library(LLVM_SINGLE_LIB NAMES LLVM-22 LLVM
HINTS /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/llvm-22/lib ${LLVM_LIBRARY_DIRS})2. src/interpreter/interpreter.cpp:54,57 – hardcoded absolute paths 🔴
compilerArgsStorage_.push_back("/usr/lib/clang/22");
compilerArgsStorage_.push_back("/home/sergio/Project/cpp-repl/include");/usr/lib/clang/22is the Arch path. On Ubuntu the resource dir is/usr/lib/llvm-22/lib/clang/22or discovered viaclang::CompilerInstance/llvm-config --prefix. Hardcoding breaks CI and any other install prefix./home/sergio/Project/cpp-repl/includemakes a freshgit cloneelsewhere fail to findcpp-repl/fix_np_headers.hpp(force-included at:59). Repro: clone to/tmp, build – builtin headers break. Should be derived fromPROJECT_SOURCE_DIR/CMAKE_CURRENT_SOURCE_DIRor installed prefix, or viatarget_include_directories.
Same issue in src/repl.cpp:27-28 (legacy Repl):
std::vector<const char *> args = {"-std=c++17", "-O0", "-resource-dir", "/usr/lib/clang/22"};3. Dead / non-portable Numpy-C-API hints 🔴
src/interpreter/interpreter.cpp:55,548,672,716 contains explanations and error hints referencing a local checkout:
Use -I /home/sergio/Project/Numpy-C-API/include and #include "np/np.hpp"
Try: cpp-repl -std=c++23 -I /home/sergio/Project/Numpy-C-API/include
These paths leak a developer's home dir into user-facing diagnostics and should be generic (/path/to/Numpy-C-API/include or just suggest -I <path>).
4. include/cpp-repl/fix_proxy.hpp:10 – unconditional external include 🔴
#include "np/detail/proxy.hpp"If this header were ever force-included, it fails unless Numpy-C-API is installed. File is currently dead (only fix_np_headers.hpp is -included) but still presents maintenance risk and breaks clang-tidy/cppcheck if enabled. Either remove or guard with #if __has_include.
5. src/interpreter/interpreter.cpp:266-329 – preprocessBigIntLiterals regex incomplete (functional bug) 🟡
Repro:
./build/cpp-repl --no-interactive -e 'bigint g = 12345678901234567890123456789012345678901234567890;'
# In file included from <<< inputs >>>:1:
# error: integer literal is too largeExpected: auto-wrap to bigint("..."). The regex only handles bigint|cpp_int|... \s+ \w+ \s*=\s* DIGITS ; but fails for:
const bigint,constexpr,staticqualifiers before type- multi-declaration or template types like
const std::vector<cpp_int>, though less common - The local uncommitted diff already adds handling but still misses
autoliterals used as function args, e.g.,foo(123456789...)
Should expand to handle qualifiers and report correcttypeextraction, or better rely onboost::multiprecision::cpp_int's user-defined literal if available.
6. src/repl/session.cpp:20-36 and src/interpreter/interpreter.cpp:824-843 – naive isIncomplete 🟡
Counts {, (, [ without stripping strings/comments. Example:
cpp> std::string s = "{";
...>incorrectly considered incomplete (open brace in string). Python REPL correctly handles this via tokenization. Should reuse stripCommentsAndStrings logic from VersionDetector or use clang lexing.
7. src/interpreter/interpreter.cpp:233-257,162-179 – reinitWithCurrentOptions/ensureVersion replays history unsafely 🟡
reinitWithCurrentOptionsandensureVersionclearvariables_/history_then replay viaeval(h, e)without handling re-entrancy: if replayed code triggers anotherensureVersionupgrade, recursion could double-reinit.variables_tracking via regexparseDeclarationis lossy (missesstd::string, templates,auto, etc.) and can silently corrupt undo state.undo()rebuilds from history but skips failedparseDeclaration, leaving stale entries.
8. src/utils/version_detector.cpp:88-111 – overly broad version detection 🟡
detect checks stripped.find("import") via contains("import ") etc., causing false positives on variable names like int important = 0; → triggers C++23 upgrade. Same for export, format, source_location. Should use containsWord.
9. Hardcoded version string 🟡
src/cli/cli.cpp:126-127 and README.md hardcode LLVM 22.1.3 / clang 22.1.8. CI now uses 22.1.8 for both. Should query LLVM_VERSION_MAJOR/PACKAGE_VERSION at cmake time and embed via configure_file.
10. Build: CMakeLists.txt missing dynamic resource-dir / include handling & HAS_READLINE 🟠
- No
clang -print-resource-dirdetection; should useexecute_process(clang -print-resource-dir)orClangConfig. - Latest
mainaddsREADLINEdetection at bottom butinterpreterdoesn't use it consistently (history handling).
Repro steps
cmake -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm # CI
# fails at clang-cpp not found before fix
./build/cpp-repl --no-interactive -e 'bigint g = 1234567890123456789012345678901234567890;'
# error: integer literal is too large
git clone elsewhere && cmake -B build && ./build/cpp-repl --no-interactive -e 'int x=1;'
# fails to find fix_np_headers.hpp due to hardcoded /home/sergio pathSuggested priority
- P0: chore(deps): bump actions/upload-artifact from 4 to 7 #1, Bump github/codeql-action from 3 to 4 #2 (breaks CI / fresh clone)
- P1: Audit: portability & correctness bugs (hardcoded paths, CMake, BigInt, isIncomplete, version detection) #4, Dev #5, Dev #6
- P2: feat: zsh-like dynamic completion for colon commands #7, chore(deps): bump actions/download-artifact from 4 to 8 #8, chore(deps): bump softprops/action-gh-release from 2 to 3 #9
Generated by local audit (grep, llvm-config, gh, smoke tests) on e6e94b7 + unstaged changes. Happy to PR the CMake fix above.
Activity
sergiorandria commentedon Sep 1, 2026
Update: Fixed root cause of the
bigintJIT failure reported in follow-up:Root cause:
CMakeLists.txt:13,145forced-fno-exceptions -fno-rtti(CMAKE_CXX_FLAGS_DEBUG+target_compile_options).llvm-config --cxxflagsindeed contains-fno-exceptions, butLLVMConfig.cmake: LLVM_ENABLE_RTTI=ONandboost::multiprecision::cpp_int(header-only) requires exceptions. With-fno-exceptions,BOOST_NO_EXCEPTIONSis defined (clang.hppchecks!__has_feature(cxx_exceptions)), soboost::throw_exception(std::exception&, source_location&)is declared as user-defined (notthrow-based) and never defined in the host binary. At runtime the JIT tries to resolvecpp_int_backend::do_assign_string,eval_add,throw_exceptionetc. from the host and fails → whole incremental module fails →xnever materialized → secondx*xalso fails.Repro:
bigint x = cpp_int("238493...392"); x * x→ first module fails, second reportsxnot found.Fix applied:
CMakeLists.txtRebuilt with
-G Ninja(clean) and verified:Also verified earlier fix for #1 (hardcoded
clang-cppsearch) still present:find_library(CLANG_CPP_LIB NAMES clang-cpp clang-cpp-22 HINTS /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/llvm-22/lib ${LLVM_LIBRARY_DIRS} ${LLVM_DIR}/../..)etc.If you prefer to keep
-fno-exceptionsfor LLVM-sensitive TUs, alternative is to provide a stub:but enabling exceptions is simpler and matches
LLVM_ENABLE_RTTI=ON.