From b1df9fcfdeacd656f50f54fa4c4a721d8fd75e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 31 Jan 2026 15:57:33 +0100 Subject: [PATCH 1/4] Compile with LLVM 19 --- include/ClangUtil.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ClangUtil.h b/include/ClangUtil.h index 2c1482f..7d6242e 100644 --- a/include/ClangUtil.h +++ b/include/ClangUtil.h @@ -108,7 +108,7 @@ inline std::string printToString(const clang::SourceManager& SM, clang::SourceRa template inline std::string try_demangle(String s) { std::string name = s; -#if LLVM_VERSION_MAJOR == 18 +#if LLVM_VERSION_MAJOR >= 18 auto demangle = llvm::itaniumDemangle(s.data()); #else auto demangle = llvm::itaniumDemangle(s.data(), nullptr, nullptr, nullptr); From c300b3373e6e871647aed82ec256a6dd0623e7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 7 Feb 2026 12:38:36 +0100 Subject: [PATCH 2/4] Testing setup (#5) --- .github/workflows/basic-ci.yml | 55 ++++++++++++++++-------- CMakeLists.txt | 8 +++- CMakePresets.json | 73 ++++++++++++++++++++++++++++++++ cmake/ToolchainOptions.cmake | 5 ++- cmake/modules/clang-format.cmake | 2 +- cmake/modules/clang-tidy.cmake | 12 +++--- cmake/modules/log-util.cmake | 4 +- cmake/modules/target-util.cmake | 55 +++++++++++++++++++++++- src/CMakeLists.txt | 8 ++-- src/main.cpp | 1 + src/printer/CMakeLists.txt | 8 ++-- test/CMakeLists.txt | 61 ++++++++++++++++++++++++++ test/codes/cli_color.cpp | 7 +++ test/codes/cli_source.cpp | 7 +++ test/codes/color.cpp | 8 ++++ test/codes/demangle.cpp | 7 +++ test/codes/dump.cpp | 9 ++++ test/codes/errors.cpp | 8 ++++ test/codes/list.cpp | 7 +++ test/codes/list_all.cpp | 10 +++++ test/codes/location.cpp | 12 ++++++ test/codes/location_range.cpp | 14 ++++++ test/codes/quit.cpp | 5 +++ test/codes/source.cpp | 7 +++ test/lit.cfg.py | 21 +++++++++ test/lit.site.cfg.py.in | 13 ++++++ 26 files changed, 388 insertions(+), 39 deletions(-) create mode 100644 CMakePresets.json create mode 100644 test/CMakeLists.txt create mode 100644 test/codes/cli_color.cpp create mode 100644 test/codes/cli_source.cpp create mode 100644 test/codes/color.cpp create mode 100644 test/codes/demangle.cpp create mode 100644 test/codes/dump.cpp create mode 100644 test/codes/errors.cpp create mode 100644 test/codes/list.cpp create mode 100644 test/codes/list_all.cpp create mode 100644 test/codes/location.cpp create mode 100644 test/codes/location_range.cpp create mode 100644 test/codes/quit.cpp create mode 100644 test/codes/source.cpp create mode 100644 test/lit.cfg.py create mode 100644 test/lit.site.cfg.py.in diff --git a/.github/workflows/basic-ci.yml b/.github/workflows/basic-ci.yml index ebf42e7..46cfd90 100644 --- a/.github/workflows/basic-ci.yml +++ b/.github/workflows/basic-ci.yml @@ -11,18 +11,30 @@ env: jobs: format-check: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main" | sudo tee /etc/apt/sources.list.d/llvm-18.list + + - name: Update apt + run: sudo apt-get update + + - name: Install clang-format + run: | + sudo apt-get remove clang-format-* + sudo apt-get install -t llvm-toolchain-noble-18 clang-format-18 - name: Format source code run: | - find demo lib test \ + find src include test \ -type f \ -a \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \ -print0 \ - | xargs -0 clang-format-14 -i + | xargs -0 clang-format-18 -i - name: Format check run: | @@ -33,28 +45,31 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 - - uses: codespell-project/actions-codespell@v2 + - uses: actions/checkout@v5 + - uses: codespell-project/actions-codespell@v2.2 build-project: strategy: fail-fast: false matrix: include: - - llvm-version: 12 - os: ubuntu-20.04 - preset: develop - llvm-version: 14 os: ubuntu-22.04 preset: develop - - llvm-version: 18 + - llvm-version: 21 os: ubuntu-24.04 preset: develop runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - name: LLVM apt + if: ${{ matrix.llvm-version >= 19 }} + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{ matrix.llvm-version }} main" | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.llvm-version }}.list - name: Update apt run: sudo apt-get update @@ -73,12 +88,18 @@ jobs: echo "CLANG_CMAKE_DIR=/usr/lib/llvm-${{ matrix.llvm-version }}/lib/cmake/clang" >> $GITHUB_ENV echo "EXTERNAL_LIT=/usr/lib/llvm-${{ matrix.llvm-version }}/build/utils/lit/lit.py" >> $GITHUB_ENV - - name: Build ASTPrinter - run: | - cmake -B build -DCMAKE_BUILD_TYPE=Debug -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} - cmake --build build --parallel - - name: Build ASTPrinter release run: | - cmake -B build_rel -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} + cmake --preset release -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} cmake --build build_rel --parallel --target install + + - name: Test and Coverage + run: | + cmake --preset coverage -DLLVM_DIR=${LLVM_CMAKE_DIR} -DClang_DIR=${CLANG_CMAKE_DIR} -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT} + cmake --build build_cov --target coverage-astprinter + + - name: Upload coverage + uses: actions/upload-artifact@v6 + with: + name: coverage-report-llvm${{ matrix.llvm-version }} + path: build_cov/coverage_report/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 7872b90..017ff6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.20) +CMAKE_MINIMUM_REQUIRED(VERSION 3.21) PROJECT(astprinter VERSION 0.3 ) @@ -17,7 +17,7 @@ list(APPEND CMAKE_MODULE_PATH include(ToolchainOptions) include(CMakePackageConfigHelpers) -add_format_target(format-sources +astprinter_add_format_target(astprinter-format-sources "Formats project source files" TARGETS src/*.cpp src/*.h @@ -25,3 +25,7 @@ add_format_target(format-sources ) add_subdirectory(src) + +if(PROJECT_IS_TOP_LEVEL) + add_subdirectory(test) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..0591b08 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,73 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "clang-toolchain", + "hidden": true, + "generator": "Unix Makefiles", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++" + } + }, + { + "name": "develop", + "displayName": "Develop (Debug)", + "description": "Default develop build options for Clang", + "binaryDir": "${sourceDir}/build", + "inherits": [ + "clang-toolchain" + ], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "release", + "displayName": "Release", + "description": "Default release build options for Clang", + "binaryDir": "${sourceDir}/build_rel", + "inherits": [ + "clang-toolchain" + ], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "coverage", + "displayName": "Coverage (LLVM)", + "description": "Default coverage build options for Clang (LLVM-based)", + "binaryDir": "${sourceDir}/build_cov", + "inherits": [ + "clang-toolchain" + ], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "ASTPRINTER_ENABLE_COVERAGE": "ON", + "CMAKE_C_FLAGS": "-fprofile-instr-generate -fcoverage-mapping", + "CMAKE_CXX_FLAGS": "-fprofile-instr-generate -fcoverage-mapping", + "CMAKE_EXE_LINKER_FLAGS": "-fprofile-instr-generate -fcoverage-mapping" + } + } + ], + "buildPresets": [ + { + "name": "develop", + "configurePreset": "develop" + }, + { + "name": "release", + "configurePreset": "release" + }, + { + "name": "coverage", + "configurePreset": "coverage" + } + ] +} diff --git a/cmake/ToolchainOptions.cmake b/cmake/ToolchainOptions.cmake index f2c24ff..7017ecb 100644 --- a/cmake/ToolchainOptions.cmake +++ b/cmake/ToolchainOptions.cmake @@ -27,7 +27,10 @@ include(clang-format) include(log-util) include(target-util) -set(LOG_LEVEL 0 CACHE STRING "Granularity of the logger. 3 is most verbose, 0 is least.") +set(ASTPRINTER_LOG_LEVEL 0 CACHE STRING "Granularity of the logger. 3 is most verbose, 0 is least.") + +option(ASTPRINTER_ENABLE_COVERAGE "Enable code coverage" OFF) +mark_as_advanced(ASTPRINTER_ENABLE_COVERAGE) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) diff --git a/cmake/modules/clang-format.cmake b/cmake/modules/clang-format.cmake index b1d2fa0..375f2e7 100644 --- a/cmake/modules/clang-format.cmake +++ b/cmake/modules/clang-format.cmake @@ -1,4 +1,4 @@ -function(add_format_target target comment) +function(astprinter_add_format_target target comment) macro(filter_dir _dir_name_) foreach (SOURCE_FILE ${ALL_CXX_FILES}) string(FIND ${SOURCE_FILE} ${_dir_name_} EXCLUDE_FOUND) diff --git a/cmake/modules/clang-tidy.cmake b/cmake/modules/clang-tidy.cmake index 068aa0f..72513fa 100644 --- a/cmake/modules/clang-tidy.cmake +++ b/cmake/modules/clang-tidy.cmake @@ -1,4 +1,4 @@ -function(add_tidy_target target comment) +function(astprinter_add_tidy_target target comment) macro(filter_dir _name_) foreach (SOURCE_FILE ${ARG_SOURCES}) string(FIND ${SOURCE_FILE} ${_name_} EXCLUDE_FOUND) @@ -33,23 +33,23 @@ function(add_tidy_target target comment) endif() endfunction() -function(add_tidy_fix_target target comment) +function(astprinter_add_tidy_fix_target target comment) cmake_parse_arguments(ARG "" "" "SOURCES;EXCLUDES;OTHER" ${ARGN}) - add_tidy_target(${target} "${comment}" + astprinter_add_tidy_target(${target} "${comment}" SOURCES ${ARG_SOURCES} EXCLUDES ${ARG_EXCLUDES} OTHER ${ARG_OTHER} -fix ) endfunction() -function(make_tidy_check name sources) - add_tidy_target(tidy-run-on-${name} +function(astprinter_make_tidy_check name sources) + astprinter_add_tidy_target(tidy-run-on-${name} "Clang-tidy run on ${name} translation units" SOURCES ${sources} OTHER --header-filter=${CMAKE_CURRENT_SOURCE_DIR} ) - add_tidy_fix_target(tidy-fix-on-${name} + astprinter_add_tidy_fix_target(tidy-fix-on-${name} "Clang-tidy run with fixes on ${name} translation units" SOURCES ${sources} OTHER --header-filter=${CMAKE_CURRENT_SOURCE_DIR} -checks=-*,modernize-*,llvm-namespace-comment,google-explicit-constructor diff --git a/cmake/modules/log-util.cmake b/cmake/modules/log-util.cmake index 43e7d10..5cadd9d 100644 --- a/cmake/modules/log-util.cmake +++ b/cmake/modules/log-util.cmake @@ -1,4 +1,4 @@ -function(target_define_file_basename targetname) +function(astprinter_define_file_basename targetname) get_target_property(source_files "${targetname}" SOURCES) foreach(sourcefile ${source_files}) @@ -10,7 +10,7 @@ function(target_define_file_basename targetname) get_filename_component(basename "${sourcefile}" NAME) list(APPEND compile_defs - "LOG_BASENAME_FILE=\"${basename}\"" + "ASTPRINTER_LOG_BASENAME_FILE=\"${basename}\"" ) set_source_files_properties("${sourcefile}" diff --git a/cmake/modules/target-util.cmake b/cmake/modules/target-util.cmake index b897089..72e10d5 100644 --- a/cmake/modules/target-util.cmake +++ b/cmake/modules/target-util.cmake @@ -1,4 +1,4 @@ -function(target_project_compile_options target) +function(astprinter_project_compile_options target) cmake_parse_arguments(ARG "" "" "PRIVATE_FLAGS;PUBLIC_FLAGS" ${ARGN}) target_compile_options(${target} PRIVATE @@ -22,7 +22,7 @@ function(target_project_compile_options target) endif () endfunction() -function(target_project_compile_definitions target) +function(astprinter_project_compile_definitions target) cmake_parse_arguments(ARG "" "" "PRIVATE_DEFS;PUBLIC_DEFS" ${ARGN}) target_compile_definitions(${target} PRIVATE "LLVM_VERSION_MAJOR=${LLVM_VERSION_MAJOR}") @@ -38,4 +38,55 @@ function(target_project_compile_definitions target) "${ARG_PUBLIC_DEFS}" ) endif () +endfunction() + +function(astprinter_find_llvm_progs target names) + cmake_parse_arguments(ARG "ABORT_IF_MISSING;SHOW_VAR" "DEFAULT_EXE" "HINTS" ${ARGN}) + set(TARGET_TMP ${target}) + + find_program( + ${target} + NAMES ${names} + PATHS ${LLVM_TOOLS_BINARY_DIR} + NO_DEFAULT_PATH + ) + if(NOT ${target}) + find_program( + ${target} + NAMES ${names} + HINTS ${ARG_HINTS} + ) + endif() + + if(NOT ${target}) + set(target_missing_message "") + if(ARG_DEFAULT_EXE) + unset(${target} CACHE) + set(${target} + ${ARG_DEFAULT_EXE} + CACHE + STRING + "Default value for ${TARGET_TMP}." + ) + set(target_missing_message "Using default: ${ARG_DEFAULT_EXE}") + endif() + + set(message_status STATUS) + if(ARG_ABORT_IF_MISSING AND NOT ARG_DEFAULT_EXE) + set(message_status SEND_ERROR) + endif() + message(${message_status} + "Did find LLVM program " "${names}" + " in ${LLVM_TOOLS_BINARY_DIR}, in system path or hints " "\"${ARG_HINTS}\"" ". " + ${target_missing_message} + ) + endif() + + set(${TARGET_TMP} "${${TARGET_TMP}}" PARENT_SCOPE) + + if(ARG_SHOW_VAR) + mark_as_advanced(CLEAR ${target}) + else() + mark_as_advanced(${target}) + endif() endfunction() \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aea7c36..a420404 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,11 +4,11 @@ add_executable(clang-ast-printer${EXE_SUFFIX} main.cpp ) -target_define_file_basename(clang-ast-printer${EXE_SUFFIX}) -target_project_compile_options(clang-ast-printer${EXE_SUFFIX}) -target_project_compile_definitions(clang-ast-printer${EXE_SUFFIX} +astprinter_define_file_basename(clang-ast-printer${EXE_SUFFIX}) +astprinter_project_compile_options(clang-ast-printer${EXE_SUFFIX}) +astprinter_project_compile_definitions(clang-ast-printer${EXE_SUFFIX} PRIVATE_DEFS - LOG_LEVEL=${LOG_LEVEL} + ASTPRINTER_LOG_LEVEL=${ASTPRINTER_LOG_LEVEL} ) target_include_directories(clang-ast-printer${EXE_SUFFIX} diff --git a/src/main.cpp b/src/main.cpp index 735fbd2..bc27641 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,6 +80,7 @@ int main(int argc, const char** argv) { NodeFinder visitor(ctx, llvm::outs()); visitor.showColor(color); + visitor.showSource(source); llvm::LineEditor le("ast-printer"); while (auto line = le.readLine()) { diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index 5add0c3..342e8a9 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -2,11 +2,11 @@ add_library(clang-ast-print STATIC NodeFinder.cpp ) -target_define_file_basename(clang-ast-print) -target_project_compile_options(clang-ast-print) -target_project_compile_definitions(clang-ast-print +astprinter_define_file_basename(clang-ast-print) +astprinter_project_compile_options(clang-ast-print) +astprinter_project_compile_definitions(clang-ast-print PRIVATE_DEFS - LOG_LEVEL=${LOG_LEVEL} + ASTPRINTER_LOG_LEVEL=${ASTPRINTER_LOG_LEVEL} ) target_include_directories(clang-ast-print diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..98866a4 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,61 @@ +set(LLVM_AST_PRINTER_BINARY $) + +astprinter_find_llvm_progs(ASTPRINTER_FILECHECK_EXEC "FileCheck-${LLVM_VERSION_MAJOR};FileCheck") + +if(LLVM_EXTERNAL_LIT) + cmake_path(GET LLVM_EXTERNAL_LIT PARENT_PATH LLVM_EXTERNAL_LIT_DIR) +endif() +astprinter_find_llvm_progs(ASTPRINTER_LIT_EXEC + "llvm-lit;lit;lit.py" + HINTS ${LLVM_EXTERNAL_LIT_DIR} /usr/lib/llvm-${LLVM_VERSION_MAJOR}/build/utils/lit + ABORT_IF_MISSING +) + +add_custom_target(check-astprinter + COMMAND ${ASTPRINTER_LIT_EXEC} -vv ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS clang-ast-printer${EXE_SUFFIX} + COMMENT "Running astprinter regression tests" + USES_TERMINAL +) + +astprinter_add_format_target(astprinter-format-tests + "Formats project source files" + TARGETS codes/*.cpp + codes/*.c + codes/*.h +) + +if(ASTPRINTER_ENABLE_COVERAGE) + set(COVERAGE_DIR ${CMAKE_BINARY_DIR}/coverage_report) + astprinter_find_llvm_progs(ASTPRINTER_PROFDATA_EXEC "llvm-profdata-${LLVM_VERSION_MAJOR};llvm-profdata") + astprinter_find_llvm_progs(ASTPRINTER_COV_EXEC "llvm-cov-${LLVM_VERSION_MAJOR};llvm-cov") + + set(IGNORE_REGEX ".*(test|build|build_cov|external).*") + + add_custom_target(coverage-astprinter + COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_DIR} + COMMAND ${CMAKE_COMMAND} -E rm -f "${CMAKE_CURRENT_BINARY_DIR}/*.profraw" "${CMAKE_CURRENT_BINARY_DIR}/merged.profdata" + # Execute tests + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target check-astprinter + # Merge all profraw files + COMMAND ${CMAKE_COMMAND} -E env bash -c "${ASTPRINTER_PROFDATA_EXEC} merge -sparse ${CMAKE_CURRENT_BINARY_DIR}/*.profraw -o ${CMAKE_CURRENT_BINARY_DIR}/merged.profdata" + # Generate HTML + COMMAND ${ASTPRINTER_COV_EXEC} show "${LLVM_AST_PRINTER_BINARY}" + "-instr-profile=${CMAKE_CURRENT_BINARY_DIR}/merged.profdata" + -format=html + "-output-dir=${COVERAGE_DIR}" + -show-line-counts-or-regions + "-ignore-filename-regex=${IGNORE_REGEX}" + # Show summary + COMMAND ${ASTPRINTER_COV_EXEC} report "${LLVM_AST_PRINTER_BINARY}" + "-instr-profile=${CMAKE_CURRENT_BINARY_DIR}/merged.profdata" + "-ignore-filename-regex=${IGNORE_REGEX}" + COMMENT "Generating coverage report" + DEPENDS check-astprinter + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + VERBATIM + ) +endif() + +configure_file(lit.site.cfg.py.in lit.site.cfg.py.tmp @ONLY) +file(GENERATE OUTPUT lit.site.cfg.py INPUT ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py.tmp) diff --git a/test/codes/cli_color.cpp b/test/codes/cli_color.cpp new file mode 100644 index 0000000..93c4181 --- /dev/null +++ b/test/codes/cli_color.cpp @@ -0,0 +1,7 @@ +// RUN: echo "color" | %clang-ast-printer --use-color=true %s -- | %filecheck %s + +// CHECK: Show color off. + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/cli_source.cpp b/test/codes/cli_source.cpp new file mode 100644 index 0000000..9d4d74d --- /dev/null +++ b/test/codes/cli_source.cpp @@ -0,0 +1,7 @@ +// RUN: echo "source" | %clang-ast-printer --source=true %s -- | %filecheck %s + +// CHECK: Show source off. + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/color.cpp b/test/codes/color.cpp new file mode 100644 index 0000000..d19503c --- /dev/null +++ b/test/codes/color.cpp @@ -0,0 +1,8 @@ +// RUN: printf "color\\ncolor\\nquit\\n" | %clang-ast-printer --use-color=false %s -- | %filecheck %s + +// CHECK: Show color on. +// CHECK: Show color off. + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/demangle.cpp b/test/codes/demangle.cpp new file mode 100644 index 0000000..7ebb42b --- /dev/null +++ b/test/codes/demangle.cpp @@ -0,0 +1,7 @@ +// RUN: printf "demangle _Z4mainiPPc\\nquit\\n" | %clang-ast-printer %s -- | %filecheck %s + +// CHECK: Demangled name: main + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/dump.cpp b/test/codes/dump.cpp new file mode 100644 index 0000000..9565324 --- /dev/null +++ b/test/codes/dump.cpp @@ -0,0 +1,9 @@ +// RUN: printf "print main\nquit\n" | %clang-ast-printer --use-color=false %s -- | %filecheck %s + +// CHECK: FunctionDecl {{.*}} main 'int ()' +// CHECK: CompoundStmt {{.*}} +// CHECK: ReturnStmt {{.*}} + +int main() { + return 0; +} diff --git a/test/codes/errors.cpp b/test/codes/errors.cpp new file mode 100644 index 0000000..ff40ef1 --- /dev/null +++ b/test/codes/errors.cpp @@ -0,0 +1,8 @@ +// RUN: printf "list [\\n1 2 3\\nquit\\n" | %clang-ast-printer %s -- | %filecheck %s + +// CHECK: Invalid regex ({{.*}}): "[" +// CHECK: Erroneous input of size: 3 + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/list.cpp b/test/codes/list.cpp new file mode 100644 index 0000000..8ca15b7 --- /dev/null +++ b/test/codes/list.cpp @@ -0,0 +1,7 @@ +// RUN: printf "list main\\nquit\\n" | %clang-ast-printer %s -- | %filecheck %s + +// CHECK: main:{{.*}} + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/list_all.cpp b/test/codes/list_all.cpp new file mode 100644 index 0000000..6395f93 --- /dev/null +++ b/test/codes/list_all.cpp @@ -0,0 +1,10 @@ +// RUN: printf "list\\nquit\\n" | %clang-ast-printer %s -- | %filecheck %s + +// CHECK: foo:{{.*}} +// CHECK: main:{{.*}} + +void foo() { +} +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/location.cpp b/test/codes/location.cpp new file mode 100644 index 0000000..f525fef --- /dev/null +++ b/test/codes/location.cpp @@ -0,0 +1,12 @@ +// RUN: printf "7\\nquit\\n" | %clang-ast-printer --source=false --use-color=false %s -- | %filecheck %s + +// CHECK: VarDecl {{.*}} x 'int' +// CHECK: IntegerLiteral {{.*}} 'int' 10 + +void foo() { + int x = 10; +} + +int main() { + return 0; +} diff --git a/test/codes/location_range.cpp b/test/codes/location_range.cpp new file mode 100644 index 0000000..a4d6a6b --- /dev/null +++ b/test/codes/location_range.cpp @@ -0,0 +1,14 @@ +// RUN: printf "8 10\\nquit\\n" | %clang-ast-printer --source=false --use-color=false %s -- | %filecheck %s + +// CHECK: ForStmt {{.*}} +// CHECK: BinaryOperator {{.*}} '<' +// CHECK: UnaryOperator {{.*}} '++' + +void foo() { + for (int i = 0; i < 10; ++i) { + } +} + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/codes/quit.cpp b/test/codes/quit.cpp new file mode 100644 index 0000000..be7ff9b --- /dev/null +++ b/test/codes/quit.cpp @@ -0,0 +1,5 @@ +// RUN: echo "quit" | %clang-ast-printer %s -- + +int main() { + return 0; +} diff --git a/test/codes/source.cpp b/test/codes/source.cpp new file mode 100644 index 0000000..3c6bf83 --- /dev/null +++ b/test/codes/source.cpp @@ -0,0 +1,7 @@ +// RUN: printf "source\\nquit\\n" | %clang-ast-printer %s -- | %filecheck %s + +// CHECK: Show source on. + +int main() { + return 0; +} \ No newline at end of file diff --git a/test/lit.cfg.py b/test/lit.cfg.py new file mode 100644 index 0000000..7dbb0b6 --- /dev/null +++ b/test/lit.cfg.py @@ -0,0 +1,21 @@ +import lit.formats +import os + +config.name = 'AST-PRINTER' +config.test_format = lit.formats.ShTest(execute_external=True) + +config.suffixes = ['.cpp', '.c', '.ll'] + +config.test_source_root = os.path.dirname(__file__) + +if config.llvm_version: + config.available_features.add(f"llvm-{config.llvm_version}") + +# Substitutions +config.substitutions.append(('%clang-ast-printer', config.llvm_ast_printer_binary)) +config.substitutions.append(('%filecheck', config.filecheck_binary)) +config.substitutions.append(('%llvm-profdata', config.llvm_profdata_exe)) +config.substitutions.append(('%llvm-cov', config.llvm_cov_exe)) + +if config.enable_coverage.upper() in ['ON', 'YES', 'TRUE', '1']: + config.environment['LLVM_PROFILE_FILE'] = os.path.join(config.test_exec_root, "test-%p.profraw") diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in new file mode 100644 index 0000000..eb2c2ae --- /dev/null +++ b/test/lit.site.cfg.py.in @@ -0,0 +1,13 @@ +import os + +config.llvm_ast_printer_binary = "@LLVM_AST_PRINTER_BINARY@" +config.filecheck_binary = "@ASTPRINTER_FILECHECK_EXEC@" +config.llvm_profdata_exe = "@ASTPRINTER_PROFDATA_EXEC@" +config.llvm_cov_exe = "@ASTPRINTER_COV_EXEC@" +config.enable_coverage = "@ASTPRINTER_ENABLE_COVERAGE@" +config.test_source_root = "@CMAKE_CURRENT_SOURCE_DIR@" +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +config.llvm_version = "@LLVM_VERSION_MAJOR@" + +# Let the main config do the real work. +lit_config.load_config(config, os.path.join(config.test_source_root, "lit.cfg.py")) From 1c43747b6a6486f5abe11eaa8599f174ad2f0ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 7 Feb 2026 12:54:26 +0100 Subject: [PATCH 3/4] Update readme and version --- CMakeLists.txt | 6 ++++-- README.md | 34 ++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 017ff6f..53fb202 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.21) PROJECT(astprinter - VERSION 0.3 + VERSION 0.4 ) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_VERBOSE_MAKEFILE ON) +if(PROJECT_IS_TOP_LEVEL) + set(CMAKE_VERBOSE_MAKEFILE ON) +endif() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index 70f38b2..3673c76 100644 --- a/README.md +++ b/README.md @@ -28,34 +28,48 @@ Assume *test.c* contains the code: In this example we 1) load `test.c` with standard Clang flags, 2) list all function declarations in `test.c`, - 3) print the AST definition of foo, and finally, - 4) print the AST of the return statement in line 2. + 3) print the AST definition of foo,, + 4) print the AST of the return statement in line 2, and, finally, + 5) enable source output; print the source *and* AST of foo in lines 1-3. ```console -ahueck@sys:~/astprint/install$ ./bin/astprinter ../test.c -- +ahueck@sys:~/astprint/install$ ./bin/clang-ast-printer ../test.c -- ast-printer> l -foo:~/astprint/install/../test.c:1:3->3:4 -main:~/astprint/install/../test.c:4:3->8:4 +foo:/path/to/test.c:1:3->3:4 +main:/path/to/test.c:4:3->8:4 ast-printer> p foo FunctionDecl 0x3977120 line:1:7 used foo 'int ()' `-CompoundStmt 0x3977238 `-ReturnStmt 0x3977220 `-IntegerLiteral 0x3977200 'int' 2 -~/astprint/install/../test.c:1:3->3:4 +/path/to/test.c:1:3->3:4 ast-printer> 2 ReturnStmt 0x1ba3220 `-IntegerLiteral 0x1ba3200 'int' 2 -~/astprint/install/../test.c:2:7->2:15 +/path/to/test.c:2:7->2:15 + +ast-printer> source +Show source on. +ast-printer> 1 3 +int foo() { + return 2; +} + +FunctionDecl 0x626544f903d8 line:1:5 used foo 'int ()' +`-CompoundStmt 0x626544f904f8 + `-ReturnStmt 0x626544f904e8 + `-IntegerLiteral 0x626544f904c8 'int' 2 +/path/to/test.c:1:1->3:2 ``` ## How to build ###### Requirements -- CMake >= 3.20 -- Clang/LLVM 12, 14, 18 (CMake needs to find the installation, see +- CMake >= 3.21 +- Clang/LLVM 14, 18-21 (CMake needs to find the installation, see the [LLVM CMake documentation](https://llvm.org/docs/CMake.html) or the [CI workflow](.github/workflows/basic-ci.yml)) - C++17 compiler @@ -64,6 +78,6 @@ ReturnStmt 0x1ba3220 In the root project folder, execute the following commands (see also [CI workflow](.github/workflows/basic-ci.yml)) ``` - cmake -B build -DCMAKE_INSTALL_PREFIX=*your path* + cmake -B build --preset=release cmake --build build --target install --parallel ``` From 7601c3760c916f7f0fb293b486eddb484151fe12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Sat, 7 Feb 2026 12:58:18 +0100 Subject: [PATCH 4/4] Readme --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 3673c76..c73b312 100644 --- a/README.md +++ b/README.md @@ -35,20 +35,20 @@ In this example we ```console ahueck@sys:~/astprint/install$ ./bin/clang-ast-printer ../test.c -- ast-printer> l -foo:/path/to/test.c:1:3->3:4 -main:/path/to/test.c:4:3->8:4 +foo:/path/to/test.c:1:1->3:2 +main:/path/to/test.c:4:1->8:2 ast-printer> p foo -FunctionDecl 0x3977120 line:1:7 used foo 'int ()' -`-CompoundStmt 0x3977238 - `-ReturnStmt 0x3977220 - `-IntegerLiteral 0x3977200 'int' 2 -/path/to/test.c:1:3->3:4 +FunctionDecl 0x62eed65573d8 line:1:5 used foo 'int ()' +`-CompoundStmt 0x62eed65574f8 + `-ReturnStmt 0x62eed65574e8 + `-IntegerLiteral 0x62eed65574c8 'int' 2 +/path/to/test.c:1:1->3:2 ast-printer> 2 -ReturnStmt 0x1ba3220 -`-IntegerLiteral 0x1ba3200 'int' 2 -/path/to/test.c:2:7->2:15 +ReturnStmt 0x62eed65574e8 +`-IntegerLiteral 0x62eed65574c8 'int' 2 +/path/to/test.c:2:5->2:13 ast-printer> source Show source on. @@ -57,10 +57,10 @@ int foo() { return 2; } -FunctionDecl 0x626544f903d8 line:1:5 used foo 'int ()' -`-CompoundStmt 0x626544f904f8 - `-ReturnStmt 0x626544f904e8 - `-IntegerLiteral 0x626544f904c8 'int' 2 +FunctionDecl 0x62eed65573d8 line:1:5 used foo 'int ()' +`-CompoundStmt 0x62eed65574f8 + `-ReturnStmt 0x62eed65574e8 + `-IntegerLiteral 0x62eed65574c8 'int' 2 /path/to/test.c:1:1->3:2 ```