├── .clang-format ├── .devcontainer ├── Dockerfile ├── devcontainer.json └── features │ ├── emscripten │ ├── devcontainer-feature.json │ └── install.sh │ └── wasi-sdk │ ├── devcontainer-feature.json │ └── install.sh ├── .dockerignore ├── .github └── workflows │ ├── ci.yml │ ├── mlir.yaml │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── Config.cmake.in ├── Dockerfile.emsdk ├── Dockerfile.wasi ├── LICENSE ├── README.md ├── clangd.in ├── clangd_emscripten.in ├── package-lock.json ├── package.json ├── packages ├── cxx-frontend │ ├── .gitignore │ ├── .npmignore │ ├── .prettierignore │ ├── package.json │ ├── scripts │ │ └── build.js │ ├── src │ │ ├── AST.ts │ │ ├── ASTCursor.ts │ │ ├── ASTKind.ts │ │ ├── ASTSlot.ts │ │ ├── ASTSlotKind.ts │ │ ├── ASTVisitor.ts │ │ ├── Diagnostic.ts │ │ ├── Lexer.ts │ │ ├── Parser.ts │ │ ├── Preprocessor.ts │ │ ├── RecursiveASTVisitor.ts │ │ ├── SourceLocation.ts │ │ ├── Token.ts │ │ ├── TokenKind.ts │ │ ├── TranslationUnit.ts │ │ ├── Unit.ts │ │ ├── cxx-js.d.ts │ │ ├── cxx.ts │ │ └── index.ts │ └── tsconfig.json ├── cxx-gen-ast │ ├── .eslintrc.json │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── cpy_header.ts │ │ ├── gen.ts │ │ ├── gen_ast_cc.ts │ │ ├── gen_ast_decoder_cc.ts │ │ ├── gen_ast_decoder_h.ts │ │ ├── gen_ast_encoder_cc.ts │ │ ├── gen_ast_encoder_h.ts │ │ ├── gen_ast_fbs.ts │ │ ├── gen_ast_fwd_h.ts │ │ ├── gen_ast_h.ts │ │ ├── gen_ast_kind_h.ts │ │ ├── gen_ast_kind_ts.ts │ │ ├── gen_ast_pretty_printer_cc.ts │ │ ├── gen_ast_pretty_printer_h.ts │ │ ├── gen_ast_printer_cc.ts │ │ ├── gen_ast_printer_h.ts │ │ ├── gen_ast_recursive_visitor_ts.ts │ │ ├── gen_ast_slot_cc.ts │ │ ├── gen_ast_slot_ts.ts │ │ ├── gen_ast_ts.ts │ │ ├── gen_ast_visitor_cc.ts │ │ ├── gen_ast_visitor_h.ts │ │ ├── gen_ast_visitor_ts.ts │ │ ├── gen_keywords_kwgen.ts │ │ ├── gen_syntax_cc.ts │ │ ├── gen_syntax_h.ts │ │ ├── gen_token_fwd_h.ts │ │ ├── gen_tokenkind_ts.ts │ │ ├── getAllMemberSlotNames.ts │ │ ├── get_ast_slot_h.ts │ │ ├── groupNodesByBaseType.ts │ │ ├── new_ast_op.ts │ │ ├── new_ast_op_cc.ts │ │ ├── new_ast_op_h.ts │ │ ├── new_ast_rewriter.ts │ │ ├── new_ast_rewriter_cc.ts │ │ ├── new_ast_rewriter_h.ts │ │ ├── parseAST.ts │ │ └── tokens.ts │ └── tsconfig.json ├── cxx-gen-lsp │ ├── .eslintrc.json │ ├── .gitignore │ ├── .prettierrc │ ├── package.json │ ├── src │ │ ├── MetaModel.ts │ │ ├── copyrightHeader.ts │ │ ├── gen_enums_cc.ts │ │ ├── gen_enums_h.ts │ │ ├── gen_fwd_h.ts │ │ ├── gen_requests_cc.ts │ │ ├── gen_requests_h.ts │ │ ├── gen_types_cc.ts │ │ ├── gen_types_h.ts │ │ └── main.ts │ └── tsconfig.json └── cxx-storybook │ ├── .gitignore │ ├── .storybook │ ├── main.ts │ ├── preview.css │ └── preview.ts │ ├── eslint.config.js │ ├── index.html │ ├── package.json │ ├── src │ ├── CxxFrontendClient.tsx │ ├── CxxFrontendProvider.tsx │ ├── Editor.tsx │ ├── SyntaxTree.tsx │ ├── cppLinter.tsx │ ├── stories │ │ ├── Editor.stories.tsx │ │ ├── EditorWithSyntaxTree.stories.tsx │ │ └── EditorWithSyntaxTree.tsx │ ├── useConfigureEditor.tsx │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── patches └── utfcpp.patch ├── scripts ├── ast-dump.mjs ├── build-mlir.mjs ├── build-wasi.mjs ├── cxx-wasmtime.mjs ├── devcontainer-post-create.sh ├── download-lsp-model.mjs ├── setup-venv.mjs ├── update-launch-configs.mjs ├── update-predefined-macros.mjs └── update-tests.mjs ├── specs └── grammar.txt ├── src ├── CMakeLists.txt ├── frontend │ ├── CMakeLists.txt │ └── cxx │ │ ├── frontend.cc │ │ ├── verify_diagnostics_client.cc │ │ └── verify_diagnostics_client.h ├── js │ ├── CMakeLists.txt │ └── cxx │ │ └── api.cc ├── lib │ ├── CMakeLists.txt │ └── cxx │ │ ├── CMakeLists.txt │ │ └── include │ │ ├── stdarg.h │ │ └── stddef.h ├── lsp │ ├── CMakeLists.txt │ ├── cxx │ │ └── lsp │ │ │ ├── cxx_document.cc │ │ │ ├── cxx_document.h │ │ │ ├── enums.cc │ │ │ ├── enums.h │ │ │ ├── fwd.h │ │ │ ├── lsp.cc │ │ │ ├── lsp_server.cc │ │ │ ├── lsp_server.h │ │ │ ├── requests.cc │ │ │ ├── requests.h │ │ │ ├── sync_queue.cc │ │ │ ├── sync_queue.h │ │ │ ├── types.cc │ │ │ └── types.h │ └── tests │ │ ├── CMakeLists.txt │ │ └── test_types.cc ├── mlir │ ├── CMakeLists.txt │ └── cxx │ │ └── mlir │ │ ├── CMakeLists.txt │ │ ├── CxxOps.td │ │ ├── codegen.cc │ │ ├── codegen.h │ │ ├── cxx_dialect.cc │ │ └── cxx_dialect.h └── parser │ ├── CMakeLists.txt │ └── cxx │ ├── arena.h │ ├── ast.cc │ ├── ast.fbs │ ├── ast.h │ ├── ast_cursor.cc │ ├── ast_cursor.h │ ├── ast_fwd.h │ ├── ast_interpreter.cc │ ├── ast_interpreter.h │ ├── ast_kind.h │ ├── ast_pretty_printer.cc │ ├── ast_pretty_printer.h │ ├── ast_printer.cc │ ├── ast_printer.h │ ├── ast_rewriter.cc │ ├── ast_rewriter.h │ ├── ast_slot.cc │ ├── ast_slot.h │ ├── ast_visitor.cc │ ├── ast_visitor.h │ ├── base_classes.cc │ ├── binder.cc │ ├── binder.h │ ├── builtins.kwgen │ ├── cli.cc │ ├── cli.h │ ├── const_value.cc │ ├── const_value.h │ ├── control.cc │ ├── control.h │ ├── cxx.cc │ ├── cxx_fwd.h │ ├── decl.cc │ ├── decl.h │ ├── decl_specs.cc │ ├── decl_specs.h │ ├── diagnostic.cc │ ├── diagnostic.h │ ├── diagnostics_client.cc │ ├── diagnostics_client.h │ ├── external_name_encoder.cc │ ├── external_name_encoder.h │ ├── flatbuffers │ ├── ast_decoder.cc │ └── ast_encoder.cc │ ├── gcc_linux_toolchain.cc │ ├── gcc_linux_toolchain.h │ ├── keywords.kwgen │ ├── lexer.cc │ ├── lexer.h │ ├── literals.cc │ ├── literals.h │ ├── literals_fwd.h │ ├── macos_toolchain.cc │ ├── macos_toolchain.h │ ├── memory_layout.cc │ ├── memory_layout.h │ ├── name_lookup.cc │ ├── name_lookup.h │ ├── name_printer.cc │ ├── names.cc │ ├── names.h │ ├── names_fwd.h │ ├── parser.cc │ ├── parser.h │ ├── parser_fwd.h │ ├── path.cc │ ├── pp_keywords.kwgen │ ├── preprocessor.cc │ ├── preprocessor.h │ ├── preprocessor_fwd.h │ ├── private │ ├── ast_decoder.h │ ├── ast_encoder.h │ └── path.h │ ├── scope.cc │ ├── scope.h │ ├── source_location.cc │ ├── source_location.h │ ├── symbol_chain_view.cc │ ├── symbol_instantiation.cc │ ├── symbol_instantiation.h │ ├── symbol_printer.cc │ ├── symbols.cc │ ├── symbols.h │ ├── symbols_fwd.h │ ├── token.cc │ ├── token.h │ ├── token_fwd.h │ ├── toolchain.cc │ ├── toolchain.h │ ├── translation_unit.cc │ ├── translation_unit.h │ ├── type_checker.cc │ ├── type_checker.h │ ├── type_printer.cc │ ├── type_traits.cc │ ├── type_traits.h │ ├── types.cc │ ├── types.h │ ├── types_fwd.h │ ├── util.cc │ ├── util.h │ ├── views │ ├── base_classes.h │ └── symbol_chain.h │ ├── wasm32_wasi_toolchain.cc │ ├── wasm32_wasi_toolchain.h │ ├── windows_toolchain.cc │ └── windows_toolchain.h ├── templates ├── .gitignore ├── cxx-browser-esm-vite │ ├── .gitignore │ ├── index.html │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── main.ts │ │ └── vite-env.d.ts │ └── tsconfig.json ├── cxx-parse-esm │ ├── index.js │ └── package.json └── cxx-parse │ ├── index.js │ └── package.json ├── tests ├── CMakeLists.txt ├── api_tests │ ├── CMakeLists.txt │ ├── test_control.cc │ ├── test_external_names.cc │ ├── test_rewriter.cc │ ├── test_substitution.cc │ ├── test_type_printer.cc │ └── test_utils.h ├── manual │ └── source.cc └── unit_tests │ ├── CMakeLists.txt │ ├── ast │ ├── CMakeLists.txt │ ├── access_declaration_01.cc │ ├── array_to_pointer_conv_01.cc │ ├── asm_declaration_01.cc │ ├── binary_expression_01.cc │ ├── bitfield_declaration_01.cc │ ├── bool_literals_01.cc │ ├── boolean_conv_01.cc │ ├── class_definition_01.cc │ ├── complex_type_specifier_01.cc │ ├── consteval_if_01.cc │ ├── constrained_template_parameter_01.cc │ ├── ctor_initializer_01.cc │ ├── deduce_this_01.cc │ ├── deduction_guide_01.cc │ ├── deduction_guide_02.cc │ ├── designated_initializer_01.cc │ ├── enum_definition_01.cc │ ├── equal_initializer_01.cc │ ├── floating_integral_conv_01.cc │ ├── floating_point_conv_01.cc │ ├── floating_point_promotion_01.cc │ ├── for_range_statement_01.cc │ ├── for_range_statement_02.cc │ ├── function_definition_01.cc │ ├── function_to_pointer_conv_01.cc │ ├── if_statement_01.cc │ ├── integral_conversion_01.cc │ ├── integral_promotion_conv_01.cc │ ├── lambda_specifier_01.cc │ ├── namespace_definition_01.cc │ ├── nested_templates_01.cc │ ├── new_expression_01.cc │ ├── pack_expansion_01.cc │ ├── parameter_pack_01.cc │ ├── reflect_01.cc │ ├── reflect_02.cc │ ├── return_statement_01.cc │ ├── struct_alias_01.cc │ ├── structured_binding_declaration_01.cc │ ├── template_lambda_01.cc │ ├── template_member_expression_01.cc │ ├── template_nested_name_specifier_01.cc │ ├── template_type_parameter_01.cc │ ├── underlying_type_specifier_01.cc │ ├── using_enum_declaration_01.cc │ ├── variadic_function_01.cc │ └── variadic_function_02.cc │ ├── lit.cfg.py │ ├── lit.site.cfg.py.in │ ├── lsp │ ├── CMakeLists.txt │ ├── code_completion_01.yml │ ├── document_01.yml │ ├── document_symbols.yml │ └── lifecycle_01.yml │ ├── parser │ ├── CMakeLists.txt │ └── postfix_expr_conflicts.cc │ ├── preprocessor │ ├── CMakeLists.txt │ ├── bol_001.cc │ ├── counter.001.cc │ ├── define.001.cc │ ├── define.002.cc │ ├── define.003.cc │ ├── define.004.cc │ ├── elifdef_001.cc │ ├── file.001.cc │ ├── file.001.h │ ├── line.001.cc │ ├── merge_01.cc │ ├── va_args_001.cc │ ├── va_args_002.cc │ └── warning.001.cc │ ├── requirements.txt │ ├── sema │ ├── CMakeLists.txt │ ├── address_op_01.cc │ ├── alignof_01.cc │ ├── bitwise_not_01.cc │ ├── class_01.cc │ ├── conditional_expr_01.cc │ ├── constant_expression_01.cc │ ├── ctor_01.cc │ ├── decltype_01.cc │ ├── function_params_01.cc │ ├── fwd_class_01.cc │ ├── incr_01.cc │ ├── is_base_of_01.cc │ ├── is_final_01.cc │ ├── logical_neg_01.cc │ ├── member_access_01.cc │ ├── member_access_02.cc │ ├── sizeof_01.cc │ ├── static_assert_01.cc │ ├── static_cast_01.cc │ ├── static_cast_02.cc │ ├── subtraction_01.cc │ ├── template_alias_01.cc │ ├── template_alias_02.cc │ ├── template_class_01.cc │ ├── template_class_02.cc │ ├── template_class_03.cc │ ├── template_class_04.cc │ ├── trailing_return_type_01.cc │ ├── trailing_return_type_02.cc │ ├── type_traits_01.cc │ ├── unary_minus_01.cc │ ├── unary_plus_01.cc │ ├── using_decl_01.cc │ └── wasm_stdlib_01.cc │ └── tokens │ ├── CMakeLists.txt │ ├── raw_string.001.cc │ └── string.001.cc └── tools └── kwgen ├── CMakeLists.txt └── kwgen.cc /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: google 3 | 4 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:25.04 2 | 3 | RUN userdel -f -r ubuntu 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | bash-completion \ 7 | build-essential \ 8 | clang-format \ 9 | clangd \ 10 | cmake \ 11 | lldb \ 12 | ninja-build \ 13 | pipx \ 14 | python3-pip \ 15 | python3-venv \ 16 | valgrind \ 17 | wget 18 | 19 | RUN wget -nd -P /tmp/ https://github.com/watchexec/watchexec/releases/download/v2.3.0/watchexec-2.3.0-$(uname -m)-unknown-linux-gnu.deb \ 20 | && dpkg -i /tmp/watchexec-2.3.0-$(uname -m)-unknown-linux-gnu.deb \ 21 | && rm -f /tmp/watchexec-2.3.0-$(uname -m)-unknown-linux-gnu.deb 22 | 23 | RUN wget -nd -P /tmp/ https://github.com/bytecodealliance/wasmtime/releases/download/v31.0.0/wasmtime-v31.0.0-$(uname -m)-linux.tar.xz \ 24 | && tar -C /usr/local/bin -xvf /tmp/wasmtime-v31.0.0-$(uname -m)-linux.tar.xz --strip-components=1 --wildcards 'wasmtime-*-linux/wasmtime' \ 25 | && rm -f /tmp/wasmtime-v31.0.0-$(uname -m)-linux.tar.xz 26 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ubuntu 25.04", 3 | 4 | "build": { 5 | "dockerfile": "Dockerfile" 6 | }, 7 | 8 | "runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"], 9 | 10 | "postCreateCommand": "./scripts/devcontainer-post-create.sh", 11 | 12 | "containerUser": "vscode", 13 | 14 | "features": { 15 | "ghcr.io/devcontainers/features/common-utils:2": { 16 | "configureZshAsDefaultShell": false, 17 | "installOhMyZsh": false, 18 | "installOhMyZshConfig": false, 19 | "installZsh": false, 20 | "nonFreePackages": false, 21 | "upgradePackages": true, 22 | "userUid": "1000", 23 | "userGid": "1000" 24 | }, 25 | "ghcr.io/devcontainers/features/github-cli:1": {}, 26 | "ghcr.io/devcontainers/features/node:1": { 27 | "version": "latest" 28 | }, 29 | "./features/emscripten": {}, 30 | "./features/wasi-sdk": {} 31 | }, 32 | 33 | "customizations": { 34 | "vscode": { 35 | "extensions": [ 36 | "llvm-vs-code-extensions.vscode-clangd", 37 | "llvm-vs-code-extensions.lldb-dap", 38 | "ms-vscode.cmake-tools", 39 | "esbenp.prettier-vscode" 40 | ], 41 | "settings": { 42 | "clangd.arguments": ["--completion-style=bundled"] 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.devcontainer/features/emscripten/devcontainer-feature.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "emscripten", 3 | "version": "1.0.0", 4 | "name": "Emscripten", 5 | "dependsOn": { 6 | "ghcr.io/devcontainers/features/common-utils": {} 7 | }, 8 | "containerEnv": { 9 | "EMSCRIPTEN_ROOT": "/opt/emsdk/upstream/emscripten" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.devcontainer/features/emscripten/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | git clone --depth 1 http://github.com/emscripten-core/emsdk.git /opt/emsdk 6 | cd /opt/emsdk 7 | ./emsdk install latest 8 | ./emsdk activate latest 9 | -------------------------------------------------------------------------------- /.devcontainer/features/wasi-sdk/devcontainer-feature.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "wasi-sdk", 3 | "version": "1.0.0", 4 | "name": "Wasi SDK", 5 | "dependsOn": { 6 | "ghcr.io/devcontainers/features/common-utils": {} 7 | }, 8 | "containerEnv": { 9 | "WASI_SDK_PATH": "/opt/wasi-sdk" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.devcontainer/features/wasi-sdk/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | arch=$(uname -m) 6 | 7 | if [ "$arch" == "aarch64" ]; then 8 | arch="arm64" 9 | fi 10 | 11 | wget -nd -P /tmp/ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-${arch}-linux.deb 12 | 13 | dpkg -i /tmp/wasi-sdk-25.0-${arch}-linux.deb 14 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .venv 3 | build 4 | build.em 5 | build.wasm 6 | out 7 | -------------------------------------------------------------------------------- /.github/workflows/mlir.yaml: -------------------------------------------------------------------------------- 1 | name: MLIR 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | build-mlir-emscripten: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v4 11 | 12 | - name: Install emsdk 13 | run: | 14 | git clone --depth 1 http://github.com/emscripten-core/emsdk.git /opt/emsdk 15 | /opt/emsdk/emsdk install latest 16 | /opt/emsdk/emsdk activate latest 17 | 18 | - name: Install dependencies 19 | run: | 20 | npm ci 21 | 22 | - name: Build 23 | run: | 24 | source "/opt/emsdk/emsdk_env.sh" 25 | npm run build:mlir 26 | 27 | - name: Upload artifacts 28 | uses: actions/upload-artifact@v4 29 | with: 30 | name: mlir 31 | path: | 32 | build.em/llvm-project/install/ 33 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | release: 7 | types: [created] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | packages: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Setup emscripten cache 19 | uses: actions/cache@v4 20 | with: 21 | path: ~/.emscripten-cache 22 | key: ${{ runner.os }}-emscripten 23 | restore-keys: | 24 | ${{ runner.os }}-emscripten 25 | 26 | - uses: actions/setup-node@v4 27 | with: 28 | registry-url: https://registry.npmjs.org/ 29 | 30 | - name: Build 31 | run: | 32 | npm ci 33 | npm -w cxx-frontend run build 34 | 35 | - name: Publish 36 | working-directory: packages/cxx-frontend 37 | run: npm publish 38 | env: 39 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /build*/ 3 | out 4 | .venv 5 | node_modules 6 | *.tgz 7 | .vscode/launch.json 8 | .cache 9 | .clangd 10 | *.pch 11 | -------------------------------------------------------------------------------- /Config.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | @PACKAGE_INIT@ 21 | 22 | include("${CMAKE_CURRENT_LIST_DIR}/cxxTargets.cmake") 23 | 24 | check_required_components(cxx) 25 | -------------------------------------------------------------------------------- /Dockerfile.emsdk: -------------------------------------------------------------------------------- 1 | FROM emscripten/emsdk:4.0.6 as em 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | ninja-build \ 5 | wget \ 6 | unzip 7 | 8 | COPY tools/kwgen/kwgen.cc /tmp/kwgen.cc 9 | 10 | RUN g++ -std=c++20 /tmp/kwgen.cc -o /usr/bin/kwgen 11 | 12 | RUN wget https://github.com/google/flatbuffers/releases/download/v25.1.24/Linux.flatc.binary.clang++-18.zip && \ 13 | unzip Linux.flatc.binary.clang++-18.zip && \ 14 | mv flatc /usr/bin/flatc && \ 15 | rm Linux.flatc.binary.clang++-18.zip 16 | -------------------------------------------------------------------------------- /Dockerfile.wasi: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/webassembly/wasi-sdk:wasi-sdk-25 as wasi 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | g++ \ 5 | git \ 6 | binaryen \ 7 | wget \ 8 | unzip \ 9 | ninja-build 10 | 11 | COPY tools/kwgen/kwgen.cc /tmp/kwgen.cc 12 | 13 | RUN g++ -std=c++20 /tmp/kwgen.cc -o /usr/bin/kwgen 14 | 15 | RUN wget https://github.com/google/flatbuffers/releases/download/v25.1.24/Linux.flatc.binary.clang++-18.zip && \ 16 | unzip Linux.flatc.binary.clang++-18.zip && \ 17 | mv flatc /usr/bin/flatc && \ 18 | rm Linux.flatc.binary.clang++-18.zip 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2025 Roberto Raggi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /clangd.in: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | CompilationDatabase: build/ 3 | -------------------------------------------------------------------------------- /clangd_emscripten.in: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | CompilationDatabase: build.em/ 3 | Add: 4 | [ 5 | -target, 6 | wasm32-unknown-emscripten, 7 | -fvisibility=default, 8 | -isysroot, 9 | @EMSCRIPTEN_ROOT_PATH@/cache/sysroot, 10 | -iwithsysroot/include/fakesdl, 11 | -iwithsysroot/include/compat, 12 | -iwithsysroot/include/c++/v1, 13 | -iwithsysroot/include, 14 | ] 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cplusplus", 3 | "version": "1.1.27", 4 | "description": "A compiler frontend for C++23", 5 | "private": true, 6 | "keywords": [ 7 | "c++", 8 | "compiler", 9 | "lexer", 10 | "parser", 11 | "preprocessor", 12 | "syntax" 13 | ], 14 | "author": { 15 | "name": "Roberto Raggi", 16 | "email": "roberto.raggi@gmail.com" 17 | }, 18 | "license": "MIT", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/robertoraggi/cplusplus.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/robertoraggi/cplusplus/issues" 25 | }, 26 | "devDependencies": { 27 | "zx": "latest", 28 | "jsonc-cli": "latest" 29 | }, 30 | "workspaces": [ 31 | "packages/*" 32 | ], 33 | "scripts": { 34 | "build:cxx-frontend": "npm run build -w cxx-frontend", 35 | "build:storybook": "npm run build-storybook -w @robertoraggi/cxx-storybook", 36 | "build:emscripten": "npm run build -w cxx-frontend", 37 | "build:wasi": "zx scripts/build-wasi.mjs", 38 | "build:mlir": "zx scripts/build-mlir.mjs", 39 | "storybook": "npm run storybook -w @robertoraggi/cxx-storybook", 40 | "setup-venv": "zx scripts/setup-venv.mjs", 41 | "update-tests": "zx scripts/update-tests.mjs", 42 | "cxx-gen-ast": "node packages/cxx-gen-ast", 43 | "cxx-gen-lsp": "node packages/cxx-gen-lsp packages/cxx-gen-lsp/metaModel.json packages/cxx-gen-lsp -o src/lsp/cxx/lsp", 44 | "download-lsp-model": "zx scripts/download-lsp-model.mjs", 45 | "download-mlir": "gh run download -n mlir --dir build.em/llvm-project/install/" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/cxx-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | out 3 | node_modules 4 | docs 5 | *.tgz 6 | README.md 7 | CHANGELOG.md 8 | cxx-js.js 9 | package-lock.json 10 | -------------------------------------------------------------------------------- /packages/cxx-frontend/.npmignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | *.map 3 | src 4 | scripts 5 | examples 6 | .prettierignore 7 | docs 8 | -------------------------------------------------------------------------------- /packages/cxx-frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | *.md 3 | -------------------------------------------------------------------------------- /packages/cxx-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cxx-frontend", 3 | "version": "1.1.27", 4 | "description": "A compiler front end for the C++ language", 5 | "main": "dist/cjs/index.cjs", 6 | "module": "dist/esm/index.js", 7 | "types": "dist/dts/index.d.ts", 8 | "type": "module", 9 | "browser": { 10 | "url": false 11 | }, 12 | "scripts": { 13 | "watch": "watchexec --print-events -r npm run build", 14 | "build": "zx scripts/build.js", 15 | "docs": "typedoc src/index.ts", 16 | "prettier": "npx prettier --check .", 17 | "prettier:fix": "npx prettier --write . " 18 | }, 19 | "keywords": [ 20 | "c++", 21 | "compiler", 22 | "lexer", 23 | "parser", 24 | "preprocessor", 25 | "syntax" 26 | ], 27 | "author": { 28 | "name": "Roberto Raggi", 29 | "email": "roberto.raggi@gmail.com" 30 | }, 31 | "license": "MIT", 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/robertoraggi/cplusplus.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/robertoraggi/cplusplus/issues" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "latest", 41 | "esbuild": "latest", 42 | "prettier": "latest", 43 | "typedoc": "latest", 44 | "typescript": "latest", 45 | "zx": "latest" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/ASTSlotKind.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | export enum ASTSlotKind { 22 | Invalid, 23 | Token, 24 | Node, 25 | TokenList, 26 | NodeList, 27 | } 28 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/Diagnostic.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | export interface Diagnostic { 22 | fileName: string; 23 | startLine: number; 24 | startColumn: number; 25 | endLine: number; 26 | endColumn: number; 27 | message: string; 28 | } 29 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/SourceLocation.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | export interface SourceLocation { 22 | startLine: number; 23 | startColumn: number; 24 | endLine: number; 25 | endColumn: number; 26 | } 27 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/Unit.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { Diagnostic } from "./Diagnostic"; 22 | 23 | export interface Unit { 24 | delete(): void; 25 | parse(): Promise; 26 | getHandle(): number; 27 | getUnitHandle(): number; 28 | getDiagnostics(): Diagnostic[]; 29 | emitIR(): string; 30 | } 31 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/cxx.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import makeCxx, { CXX } from "./cxx-js"; 22 | 23 | export let cxx!: CXX; 24 | 25 | export default async ({ 26 | wasm, 27 | }: { 28 | wasm: Uint8Array | ArrayBuffer | WebAssembly.Module; 29 | }) => { 30 | cxx = await makeCxx({ wasm }); 31 | return cxx; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/cxx-frontend/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | export * from "./AST"; 22 | export * from "./ASTCursor"; 23 | export * from "./ASTKind"; 24 | export * from "./ASTSlot"; 25 | export * from "./ASTVisitor"; 26 | export * from "./Diagnostic"; 27 | export * from "./Lexer"; 28 | export * from "./Parser"; 29 | export * from "./Preprocessor"; 30 | export * from "./RecursiveASTVisitor"; 31 | export * from "./SourceLocation"; 32 | export * from "./Token"; 33 | export * from "./TokenKind"; 34 | export * from "./TranslationUnit"; 35 | export * from "./Unit"; 36 | -------------------------------------------------------------------------------- /packages/cxx-frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ES2022", 4 | "target": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "outDir": "dist/dts", 7 | "esModuleInterop": true, 8 | "emitDeclarationOnly": true, 9 | "declaration": true, 10 | "strict": true, 11 | "skipLibCheck": true 12 | }, 13 | "exclude": ["node_modules", "dist", "scripts"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "ecmaVersion": "latest", 10 | "sourceType": "module" 11 | }, 12 | "plugins": ["@typescript-eslint"], 13 | "rules": {} 14 | } 15 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Roberto Raggi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/README.md: -------------------------------------------------------------------------------- 1 | # cxx-gen-ast 2 | 3 | AST Generator 4 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-gen-ast", 3 | "version": "1.1.3", 4 | "private": true, 5 | "type": "module", 6 | "description": "Generate AST from C++ source code", 7 | "main": "./dist/gen.js", 8 | "bin": { 9 | "cxx-gen-ast": "./dist/gen.js" 10 | }, 11 | "scripts": { 12 | "postinstall": "npm run build", 13 | "build": "tsc", 14 | "watch": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": { 18 | "name": "Roberto Raggi", 19 | "email": "roberto.raggi@gmail.com" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/robertoraggi/cplusplus" 24 | }, 25 | "license": "MIT", 26 | "devDependencies": { 27 | "@types/node": "latest", 28 | "@types/yargs": "latest", 29 | "@typescript-eslint/eslint-plugin": "latest", 30 | "@typescript-eslint/parser": "latest", 31 | "eslint": "latest", 32 | "typescript": "latest" 33 | }, 34 | "dependencies": { 35 | "prettier": "latest", 36 | "yargs": "latest" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/gen_ast_kind_h.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { cpy_header } from "./cpy_header.js"; 22 | import { AST } from "./parseAST.js"; 23 | import { groupNodesByBaseType } from "./groupNodesByBaseType.js"; 24 | import * as fs from "fs"; 25 | 26 | export function gen_ast_kind_h({ ast, output }: { ast: AST; output: string }) { 27 | const code: string[] = []; 28 | const emit = (line = "") => code.push(line); 29 | 30 | const by_bases = groupNodesByBaseType(ast); 31 | 32 | const enumName = (name: string) => name.slice(0, -3); 33 | 34 | emit(`enum class ASTKind {`); 35 | 36 | by_bases.forEach((nodes, base) => { 37 | emit(); 38 | emit(` // ${base}`); 39 | nodes.forEach(({ name }) => { 40 | emit(` ${enumName(name)},`); 41 | }); 42 | }); 43 | 44 | emit(`};`); 45 | 46 | const out = `${cpy_header} 47 | 48 | #pragma once 49 | 50 | namespace cxx { 51 | 52 | ${code.join("\n")} 53 | 54 | } // namespace cxx 55 | `; 56 | 57 | fs.writeFileSync(output, out); 58 | } 59 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/gen_ast_kind_ts.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { cpy_header } from "./cpy_header.js"; 22 | import { AST } from "./parseAST.js"; 23 | import { groupNodesByBaseType } from "./groupNodesByBaseType.js"; 24 | import { format } from "prettier"; 25 | import * as fs from "fs"; 26 | 27 | export async function gen_ast_kind_ts({ 28 | ast, 29 | output, 30 | }: { 31 | ast: AST; 32 | output: string; 33 | }) { 34 | const code: string[] = []; 35 | const emit = (line = "") => code.push(line); 36 | 37 | const by_bases = groupNodesByBaseType(ast); 38 | 39 | const enumName = (name: string) => name.slice(0, -3); 40 | 41 | emit(`export enum ASTKind {`); 42 | 43 | by_bases.forEach((nodes, base) => { 44 | emit(); 45 | emit(` // ${base}`); 46 | nodes.forEach(({ name }) => { 47 | emit(` ${enumName(name)},`); 48 | }); 49 | }); 50 | 51 | emit(`}`); 52 | 53 | const out = `${cpy_header} 54 | ${code.join("\n")} 55 | `; 56 | 57 | fs.writeFileSync(output, await format(out, { parser: "typescript" })); 58 | } 59 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/gen_ast_slot_ts.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { cpy_header } from "./cpy_header.js"; 22 | import { AST } from "./parseAST.js"; 23 | import { getAllMemberSlotNames } from "./getAllMemberSlotNames.js"; 24 | import { format } from "prettier"; 25 | import * as fs from "fs"; 26 | 27 | export async function gen_ast_slot_ts({ 28 | ast, 29 | output, 30 | }: { 31 | ast: AST; 32 | output: string; 33 | }) { 34 | const code: string[] = []; 35 | const emit = (line = "") => code.push(line); 36 | 37 | const allMemberSlotNames = getAllMemberSlotNames({ ast }); 38 | 39 | emit(`export enum ASTSlot {`); 40 | 41 | allMemberSlotNames.forEach((name, nameIndex) => { 42 | emit(` ${name} = ${nameIndex},`); 43 | }); 44 | 45 | emit(`}`); 46 | 47 | const out = `${cpy_header} 48 | ${code.join("\n")} 49 | `; 50 | 51 | fs.writeFileSync(output, await format(out, { parser: "typescript" })); 52 | } 53 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/gen_keywords_kwgen.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import * as fs from "fs"; 22 | import * as tokens from "./tokens.js"; 23 | 24 | export function gen_keywords_kwgen({ output }: { output: string }) { 25 | const code: string[] = []; 26 | const emit = (line = "") => code.push(line); 27 | 28 | const isContextKeyword = (kw: string) => { 29 | return ["final", "override", "import", "module"].includes(kw); 30 | }; 31 | 32 | tokens.KEYWORDS.filter((kw) => !isContextKeyword(kw)).forEach((tk) => 33 | emit(tk), 34 | ); 35 | 36 | emit(); 37 | tokens.TOKEN_ALIASES.forEach(([tk]) => emit(tk)); 38 | 39 | const out = `%no-enums 40 | %token-prefix=cxx::TokenKind::T_ 41 | %token-type=cxx::TokenKind 42 | %toupper 43 | 44 | %% 45 | ${code.join("\n")} 46 | `; 47 | 48 | fs.writeFileSync(output, out); 49 | } 50 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/gen_tokenkind_ts.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { cpy_header } from "./cpy_header.js"; 22 | import * as fs from "fs"; 23 | import * as tokens from "./tokens.js"; 24 | 25 | export function gen_tokenkind_ts({ output }: { output: string }) { 26 | const code: string[] = []; 27 | const emit = (line = "") => code.push(line); 28 | 29 | emit("export enum TokenKind {"); 30 | tokens.BASE_TOKENS.forEach((tk) => emit(` ${tk},`)); 31 | tokens.OPERATORS.forEach(([tk]) => emit(` ${tk},`)); 32 | tokens.KEYWORDS.forEach((tk) => emit(` ${tk.toUpperCase()},`)); 33 | emit("}"); 34 | 35 | const out = `${cpy_header} 36 | ${code.join("\n")} 37 | `; 38 | 39 | fs.writeFileSync(output, out); 40 | } 41 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/src/groupNodesByBaseType.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | import { AST, Class } from "./parseAST.js"; 22 | 23 | export function groupNodesByBaseType({ nodes }: AST) { 24 | const by_base = new Map(); 25 | 26 | nodes.forEach((node) => { 27 | const nodes = by_base.get(node.base) || []; 28 | nodes.push(node); 29 | by_base.set(node.base, nodes); 30 | }); 31 | 32 | return by_base; 33 | } 34 | -------------------------------------------------------------------------------- /packages/cxx-gen-ast/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "NodeNext", 4 | "target": "ESNext", 5 | "moduleResolution": "NodeNext", 6 | "outDir": "dist", 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "sourceMap": true 10 | }, 11 | "exclude": ["node_modules"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "ecmaVersion": "latest", 10 | "sourceType": "module" 11 | }, 12 | "plugins": ["@typescript-eslint"], 13 | "rules": {} 14 | } 15 | -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | metaModel.json -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120 3 | } 4 | -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-gen-lsp", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "description": "Scripts to generate the LSP server for C++", 7 | "main": "./dist/main.js", 8 | "bin": { 9 | "cxx-gen-lsp": "./dist/main.js" 10 | }, 11 | "scripts": { 12 | "postinstall": "npm run build", 13 | "build": "tsc", 14 | "watch": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": { 18 | "name": "Roberto Raggi", 19 | "email": "roberto.raggi@gmail.com" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/robertoraggi/cplusplus" 24 | }, 25 | "license": "MIT", 26 | "devDependencies": { 27 | "@types/node": "latest", 28 | "@typescript-eslint/eslint-plugin": "latest", 29 | "@typescript-eslint/parser": "latest", 30 | "eslint": "latest", 31 | "typescript": "latest" 32 | }, 33 | "dependencies": { 34 | "prettier": "latest" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/src/copyrightHeader.ts: -------------------------------------------------------------------------------- 1 | export const copyrightHeader = `// Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE.`; 20 | -------------------------------------------------------------------------------- /packages/cxx-gen-lsp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "NodeNext", 4 | "target": "ESNext", 5 | "moduleResolution": "NodeNext", 6 | "outDir": "dist", 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "sourceMap": true 10 | }, 11 | "exclude": ["node_modules"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/cxx-storybook/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | storybook-static 4 | -------------------------------------------------------------------------------- /packages/cxx-storybook/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import type { StorybookConfig } from "@storybook/react-vite"; 2 | 3 | const config: StorybookConfig = { 4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], 5 | addons: [ 6 | "@storybook/addon-links", 7 | "@storybook/addon-essentials", 8 | "@storybook/addon-interactions", 9 | ], 10 | framework: { 11 | name: "@storybook/react-vite", 12 | options: {}, 13 | }, 14 | docs: {}, 15 | }; 16 | 17 | export default config; 18 | -------------------------------------------------------------------------------- /packages/cxx-storybook/.storybook/preview.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | 3 | .sb-main-fullscreen #storybook-root { 4 | height: 100svh; 5 | } 6 | -------------------------------------------------------------------------------- /packages/cxx-storybook/.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import type { Preview } from "@storybook/react"; 3 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 4 | import "./preview.css"; 5 | 6 | const queryClient = new QueryClient(); 7 | 8 | const preview: Preview = { 9 | parameters: { 10 | controls: { 11 | matchers: { 12 | color: /(background|color)$/i, 13 | date: /Date$/, 14 | }, 15 | }, 16 | }, 17 | decorators: [ 18 | (Story) => { 19 | return React.createElement( 20 | QueryClientProvider, 21 | { client: queryClient }, 22 | React.createElement(Story), 23 | ); 24 | }, 25 | ], 26 | }; 27 | 28 | export default preview; 29 | -------------------------------------------------------------------------------- /packages/cxx-storybook/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import globals from "globals"; 3 | import reactHooks from "eslint-plugin-react-hooks"; 4 | import reactRefresh from "eslint-plugin-react-refresh"; 5 | import tseslint from "typescript-eslint"; 6 | 7 | export default tseslint.config( 8 | { ignores: ["dist"] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ["**/*.{ts,tsx}"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | "react-hooks": reactHooks, 18 | "react-refresh": reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | "react-refresh/only-export-components": [ 23 | "warn", 24 | { allowConstantExport: true }, 25 | ], 26 | "@typescript-eslint/no-explicit-any": "off", 27 | }, 28 | } 29 | ); 30 | -------------------------------------------------------------------------------- /packages/cxx-storybook/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C++ Storybook 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/cxx-storybook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-storybook", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "lint": "eslint .", 8 | "storybook": "storybook dev -p 6006", 9 | "build-storybook": "storybook build" 10 | }, 11 | "devDependencies": { 12 | "cxx-frontend": "^1.1.27", 13 | "@chromatic-com/storybook": "latest", 14 | "@codemirror/commands": "latest", 15 | "@codemirror/lang-cpp": "latest", 16 | "@codemirror/lint": "latest", 17 | "@codemirror/state": "latest", 18 | "@codemirror/view": "latest", 19 | "@eslint/js": "latest", 20 | "@storybook/addon-essentials": "latest", 21 | "@storybook/addon-interactions": "latest", 22 | "@storybook/addon-onboarding": "latest", 23 | "@storybook/blocks": "latest", 24 | "@storybook/react-vite": "latest", 25 | "@storybook/react": "latest", 26 | "@storybook/test": "latest", 27 | "@tailwindcss/vite": "latest", 28 | "@tanstack/react-query": "latest", 29 | "@types/react-dom": "latest", 30 | "@types/react-window": "latest", 31 | "@types/react": "latest", 32 | "@vitejs/plugin-react": "latest", 33 | "clsx": "latest", 34 | "codemirror": "latest", 35 | "eslint-plugin-react-hooks": "latest", 36 | "eslint-plugin-react-refresh": "latest", 37 | "eslint-plugin-storybook": "latest", 38 | "eslint": "latest", 39 | "globals": "latest", 40 | "react-dom": "latest", 41 | "react-virtualized-auto-sizer": "latest", 42 | "react-window": "latest", 43 | "react": "latest", 44 | "storybook": "latest", 45 | "tailwindcss": "latest", 46 | "typescript-eslint": "latest", 47 | "typescript": "latest", 48 | "vite": "latest" 49 | }, 50 | "eslintConfig": { 51 | "extends": [ 52 | "plugin:storybook/recommended" 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/cxx-storybook/src/CxxFrontendClient.tsx: -------------------------------------------------------------------------------- 1 | import wasmBinaryUrl from "cxx-frontend/dist/wasm/cxx-js.wasm?url"; 2 | import { Parser } from "cxx-frontend"; 3 | 4 | export class CxxFrontendClient { 5 | async load(signal?: AbortSignal) { 6 | const response = await fetch(wasmBinaryUrl, { signal }); 7 | if (!response.ok) throw new Error("failed to load cxx-js.wasm"); 8 | if (signal?.aborted) throw new Error("aborted"); 9 | const wasm = await response.arrayBuffer(); 10 | await Parser.init({ wasm }); 11 | return true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/cxx-storybook/src/CxxFrontendProvider.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { CxxFrontendClient } from "./CxxFrontendClient"; 3 | 4 | interface CxxFrontendProviderProps { 5 | client: CxxFrontendClient; 6 | fallback?: React.ReactNode; 7 | children: React.ReactNode; 8 | } 9 | 10 | export function CxxFrontendProvider({ 11 | client, 12 | fallback, 13 | children, 14 | }: CxxFrontendProviderProps) { 15 | const [isLoaded, setIsLoaded] = React.useState(false); 16 | 17 | React.useEffect(() => { 18 | if (isLoaded) return; 19 | setIsLoaded(false); 20 | const controller = new AbortController(); 21 | client.load(controller.signal).then(() => setIsLoaded(true)); 22 | return () => controller.abort(); 23 | }, [client, isLoaded]); 24 | 25 | return isLoaded ? <>{children} : fallback; 26 | } 27 | -------------------------------------------------------------------------------- /packages/cxx-storybook/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/cxx-storybook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /packages/cxx-storybook/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/cxx-storybook/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | export default defineConfig({ 6 | plugins: [react(), tailwindcss()], 7 | }); 8 | -------------------------------------------------------------------------------- /patches/utfcpp.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index f24f9b6..0ad6e6f 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -7,15 +7,19 @@ project (utf8cpp 6 | LANGUAGES CXX 7 | DESCRIPTION "C++ portable library for working with utf-8 encoding") 8 | 9 | -add_library(${PROJECT_NAME} INTERFACE) 10 | +option(UTFCPP_INSTALL "Generate the install target" OFF) 11 | 12 | -include(GNUInstallDirs) 13 | +add_library(${PROJECT_NAME} INTERFACE) 14 | 15 | target_include_directories(utf8cpp INTERFACE 16 | "$" 17 | $ 18 | ) 19 | 20 | +if (UTFCPP_INSTALL) 21 | + 22 | +include(GNUInstallDirs) 23 | + 24 | include(CMakePackageConfigHelpers) 25 | write_basic_package_version_file( 26 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 27 | @@ -51,3 +55,6 @@ install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 28 | install(FILES ${PROJECT_SOURCE_DIR}/source/utf8.h DESTINATION include/utf8cpp) 29 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/source/utf8 DESTINATION 30 | include/utf8cpp) 31 | + 32 | +endif() 33 | + 34 | -------------------------------------------------------------------------------- /scripts/cxx-wasmtime.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | 3 | // Copyright (c) 2025 Roberto Raggi 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import "zx/globals"; 24 | 25 | const workspacePath = path.join(__dirname, "../"); 26 | const cxxWasiPrefixPath = path.join(workspacePath, "build.wasi/install"); 27 | 28 | const wasmtime = await which("wasmtime"); 29 | 30 | const cxxArgs = [ 31 | "-W", 32 | "threads=y", 33 | "-S", 34 | "threads=y", 35 | `--dir=${cxxWasiPrefixPath}/usr::/usr`, 36 | `--dir=${process.cwd()}::/`, 37 | `${cxxWasiPrefixPath}/usr/bin/cxx.wasm`, 38 | ]; 39 | 40 | try { 41 | const result = await $`${wasmtime} ${cxxArgs} ${process.argv.slice( 42 | 3 43 | )}`.quiet(); 44 | 45 | echo`${result}`; 46 | } catch (e) { 47 | if (e instanceof ProcessOutput) { 48 | echo`${e}`; 49 | process.exit(e.status); 50 | } else { 51 | process.exit(1); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /scripts/devcontainer-post-create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | npm ci 6 | 7 | pipx install lit==18.1.8 8 | pipx install filecheck==0.0.24 9 | -------------------------------------------------------------------------------- /scripts/setup-venv.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | 3 | // Copyright (c) 2025 Roberto Raggi 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import "zx/globals"; 24 | 25 | const workspacePath = path.join(__dirname, "../"); 26 | 27 | const venvPath = path.join(workspacePath, ".venv"); 28 | 29 | const pip = path.join(venvPath, "bin/pip"); 30 | 31 | const requirements = path.join( 32 | workspacePath, 33 | "tests/unit_tests/requirements.txt" 34 | ); 35 | 36 | await spinner("Setting up virtual environment", async () => { 37 | await $`python3 -m venv ${venvPath}`; 38 | }); 39 | 40 | await spinner("Installing requirements", async () => { 41 | await $`${pip} install -r ${requirements}`; 42 | }); 43 | -------------------------------------------------------------------------------- /scripts/update-launch-configs.mjs: -------------------------------------------------------------------------------- 1 | import { $, path, fs, glob } from "zx"; 2 | import { parse, printParseErrorCode, modify, applyEdits } from "jsonc-parser"; 3 | 4 | $.verbose = true; 5 | 6 | const workspacePath = path.join(__dirname, "../"); 7 | console.log(`workspace path: ${workspacePath}`); 8 | 9 | const unitTestsPath = path.join(workspacePath, "tests/unit_tests"); 10 | 11 | const ccFiles = await glob(`${unitTestsPath}/**/*.cc`); 12 | console.log(ccFiles); 13 | 14 | function makeLaunchConfig({ file }) { 15 | const kind = path.basename(path.dirname(file)); 16 | const name = path.basename(file); 17 | 18 | return { 19 | name: `${name} [${kind}]`, 20 | type: "lldb-dap", 21 | request: "launch", 22 | program: "${workspaceRoot}/build/src/frontend/cxx", 23 | args: [path.relative(workspacePath, file)], 24 | env: [], 25 | cwd: "${workspaceRoot}", 26 | }; 27 | } 28 | 29 | const testLaunchConfigs = ccFiles.map((file) => makeLaunchConfig({ file })); 30 | 31 | console.log(testLaunchConfigs); 32 | 33 | const launchConfigPath = path.join(workspacePath, ".vscode/launch.json"); 34 | const launchConfigContent = await fs.readFile(launchConfigPath, "utf-8"); 35 | 36 | // Parse JSON with comments 37 | let errors = []; 38 | const launchConfig = parse(launchConfigContent, errors, { 39 | allowTrailingComma: true, 40 | }); 41 | 42 | if (errors.length > 0) { 43 | errors.forEach((error) => { 44 | console.error( 45 | `Error: ${printParseErrorCode(error.error)} at offset ${error.offset}` 46 | ); 47 | }); 48 | throw new Error("Failed to parse launch.json"); 49 | } 50 | 51 | // Filter out old test configurations 52 | const existingConfigs = launchConfig.configurations || []; 53 | const filteredConfigs = existingConfigs.filter( 54 | (config) => !config.name.match(/ \[.*\]$/) 55 | ); 56 | 57 | // Append new configurations 58 | const updatedConfigs = filteredConfigs.concat(testLaunchConfigs); 59 | 60 | const edits = modify(launchConfigContent, ["configurations"], updatedConfigs, { 61 | formattingOptions: {}, 62 | }); 63 | const updatedLaunchConfigContent = applyEdits(launchConfigContent, edits); 64 | 65 | // Write back to launch.json 66 | await fs.writeFile(launchConfigPath, updatedLaunchConfigContent); 67 | 68 | console.log("Updated launch.json with new test configurations."); 69 | -------------------------------------------------------------------------------- /scripts/update-predefined-macros.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | 3 | // Copyright (c) 2025 Roberto Raggi 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import "zx/globals"; 24 | 25 | async function main() { 26 | const predefinedMacros = String( 27 | // await $`${gcc} -E -dM -x c++ -std=${std} - < /dev/null`.quiet() 28 | await $`wasm32-clang++ -target wasm32-wasi -xc++ -std=c++26 -E -dM - < /dev/null`.quiet() 29 | ); 30 | 31 | const out = []; 32 | const emit = (s) => out.push(s); 33 | 34 | const toolchain = "Wasm32WasiToolchain"; 35 | 36 | emit(`void ${toolchain}::addPredefinedMacros() {`); 37 | 38 | predefinedMacros.split("\n").forEach((line) => { 39 | const m = /^#define (\w+(?:\([^)]+\))?) (.*)/.exec(line); 40 | if (!m) return; 41 | const macro = m[1]; 42 | const value = m[2].replace(/"/g, '\\"'); 43 | emit(` defineMacro("${macro}", "${value}");`); 44 | }); 45 | 46 | emit(`}`); 47 | 48 | const text = out.join("\n") + "\n"; 49 | 50 | if (argv.output) { 51 | await fs.writeFile(argv.output, text); 52 | } else { 53 | console.log(text); 54 | } 55 | } 56 | 57 | main().catch((e) => { 58 | console.error("failed", e); 59 | process.exit(1); 60 | }); 61 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_subdirectory(lib) 21 | add_subdirectory(parser) 22 | add_subdirectory(lsp) 23 | add_subdirectory(js) 24 | 25 | if (CXX_ENABLE_MLIR) 26 | add_subdirectory(mlir) 27 | endif() 28 | 29 | add_subdirectory(frontend) 30 | -------------------------------------------------------------------------------- /src/js/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | if (NOT EMSCRIPTEN) 21 | return() 22 | endif() 23 | 24 | aux_source_directory(cxx SOURCES) 25 | 26 | add_executable(cxx-js ${SOURCES}) 27 | 28 | target_link_libraries(cxx-js cxx-parser embind) 29 | 30 | if (CXX_ENABLE_MLIR) 31 | target_link_libraries(cxx-js cxx-mlir) 32 | endif() 33 | 34 | target_link_options(cxx-js PUBLIC 35 | "SHELL:-s ENVIRONMENT=web" 36 | "SHELL:-s MINIMAL_RUNTIME" 37 | "SHELL:-s EXPORT_ES6=1" 38 | "SHELL:-s WASM_ASYNC_COMPILATION=1" 39 | "SHELL:-s MODULARIZE=1" 40 | "SHELL:-s MALLOC=emmalloc" 41 | "SHELL:-s ALLOW_MEMORY_GROWTH=1" 42 | "SHELL:-s FILESYSTEM=0" 43 | "SHELL:-s NO_DYNAMIC_EXECUTION=1" 44 | "SHELL:-s WASM_BIGINT=1" 45 | "SHELL:-s INCOMING_MODULE_JS_API=[]" 46 | "SHELL:-s POLYFILL=0" 47 | ) 48 | 49 | if(CXX_INTERPROCEDURAL_OPTIMIZATION) 50 | set_target_properties(cxx-js PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) 51 | endif() 52 | -------------------------------------------------------------------------------- /src/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_subdirectory(cxx) 21 | 22 | if (CXX_INSTALL_WASI_SYSROOT) 23 | install( 24 | DIRECTORY ${wasi_sysroot_SOURCE_DIR}/ 25 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/wasi-sysroot) 26 | endif() 27 | -------------------------------------------------------------------------------- /src/lib/cxx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | file(GLOB_RECURSE HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*") 21 | 22 | install( 23 | FILES ${HEADER_FILES} 24 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cxx/include 25 | ) 26 | -------------------------------------------------------------------------------- /src/lib/cxx/include/stdarg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __GNUC_VA_LIST 4 | #define __GNUC_VA_LIST 1 5 | typedef __builtin_va_list __gnuc_va_list; 6 | #endif 7 | 8 | typedef __builtin_va_list va_list; 9 | 10 | #define va_start(ap, param) __builtin_va_start(ap, param) 11 | #define va_end(ap) __builtin_va_end(ap) 12 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 13 | 14 | #define __va_copy(d, s) __builtin_va_copy(d, s) 15 | #define va_copy(dest, src) __builtin_va_copy(dest, src) 16 | -------------------------------------------------------------------------------- /src/lib/cxx/include/stddef.h: -------------------------------------------------------------------------------- 1 | #if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \ 2 | !defined(__need_wchar_t) && !defined(__need_NULL) && \ 3 | !defined(__need_STDDEF_H_misc) 4 | #define __need_ptrdiff_t 5 | #define __need_size_t 6 | #define __need_wchar_t 7 | #define __need_NULL 8 | #define __need_STDDEF_H_misc 9 | #endif 10 | 11 | #ifdef __need_ptrdiff_t 12 | #undef __need_ptrdiff_t 13 | typedef long int ptrdiff_t; 14 | #endif /* __need_ptrdiff_t */ 15 | 16 | #ifdef __need_size_t 17 | #undef __need_size_t 18 | typedef long unsigned int size_t; 19 | #endif /* __need_size_t */ 20 | 21 | #ifdef __need_wchar_t 22 | #undef __need_wchar_t 23 | #endif /* __need_wchar_t */ 24 | 25 | #ifdef __need_NULL 26 | #undef __need_NULL 27 | #undef NULL 28 | #define NULL 0 29 | #endif /* __need_NULL */ 30 | 31 | #ifdef __need_STDDEF_H_misc 32 | #undef __need_STDDEF_H_misc 33 | typedef long unsigned int rsize_t; 34 | 35 | typedef struct { 36 | long long __clang_max_align_nonce1 37 | __attribute__((__aligned__(__alignof__(long long)))); 38 | 39 | long double __clang_max_align_nonce2 40 | __attribute__((__aligned__(__alignof__(long double)))); 41 | } max_align_t; 42 | 43 | #endif /* __need_STDDEF_H_misc */ 44 | 45 | #ifdef __need_wint_t 46 | #undef __need_wint_t 47 | 48 | #ifdef __WINT_TYPE__ 49 | typedef __WINT_TYPE__ wint_t; 50 | #else 51 | typedef int wint_t; 52 | #endif 53 | 54 | #endif /* __need_wint_t */ 55 | 56 | #if !defined(offsetof) 57 | #define offsetof(t, d) __builtin_offsetof(t, d) 58 | #endif 59 | -------------------------------------------------------------------------------- /src/lsp/cxx/lsp/lsp.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "fwd.h" 26 | 27 | #if __cpp_exceptions 28 | #include 29 | #endif 30 | 31 | namespace cxx::lsp { 32 | 33 | [[noreturn]] void lsp_runtime_error(const std::string& msg) { 34 | #if __cpp_exceptions 35 | throw std::runtime_error(msg); 36 | #else 37 | std::cerr << std::format("lsp_runtime_error: {}\n", msg); 38 | std::abort(); 39 | #endif 40 | } 41 | 42 | } // namespace cxx::lsp 43 | -------------------------------------------------------------------------------- /src/lsp/cxx/lsp/sync_queue.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include "sync_queue.h" 22 | 23 | #ifndef CXX_NO_THREADS 24 | 25 | namespace cxx::lsp { 26 | 27 | auto SyncQueue::closed() -> bool { 28 | std::unique_lock lock(m_mutex); 29 | return m_closed; 30 | } 31 | 32 | void SyncQueue::close() { 33 | std::unique_lock lock(m_mutex); 34 | m_closed = true; 35 | m_cv.notify_all(); 36 | } 37 | 38 | void SyncQueue::push(std::function task) { 39 | std::unique_lock lock(m_mutex); 40 | m_queue.push_back(std::move(task)); 41 | m_cv.notify_one(); 42 | } 43 | 44 | auto SyncQueue::pop() -> std::function { 45 | std::unique_lock lock(m_mutex); 46 | 47 | m_cv.wait(lock, [this] { return !m_queue.empty(); }); 48 | 49 | auto message = m_queue.front(); 50 | m_queue.pop_front(); 51 | 52 | return message; 53 | } 54 | 55 | } // namespace cxx::lsp 56 | 57 | #endif -------------------------------------------------------------------------------- /src/lsp/cxx/lsp/sync_queue.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #ifndef CXX_NO_THREADS 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace cxx::lsp { 31 | 32 | class SyncQueue { 33 | public: 34 | SyncQueue() = default; 35 | ~SyncQueue() = default; 36 | 37 | [[nodiscard]] auto closed() -> bool; 38 | [[nodiscard]] auto pop() -> std::function; 39 | 40 | void push(std::function task); 41 | void close(); 42 | 43 | private: 44 | std::mutex m_mutex; 45 | std::condition_variable m_cv; 46 | std::deque> m_queue; 47 | bool m_closed = false; 48 | }; 49 | 50 | } // namespace cxx::lsp 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/lsp/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (NOT CXX_BUILD_TESTS) 2 | return() 3 | endif() 4 | 5 | aux_source_directory(. SOURCES) 6 | add_executable(test_lsp ${SOURCES}) 7 | 8 | target_link_libraries(test_lsp 9 | GTest::gtest_main 10 | cxx-lsp) 11 | 12 | gtest_discover_tests(test_lsp DISCOVERY_MODE PRE_TEST) 13 | -------------------------------------------------------------------------------- /src/mlir/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(POLICY CMP0116) 3 | cmake_policy(SET CMP0116 NEW) 4 | endif() 5 | 6 | find_package(MLIR REQUIRED CONFIG) 7 | 8 | LIST(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}" "${LLVM_CMAKE_DIR}") 9 | 10 | include(AddMLIR) 11 | include(AddLLVM) 12 | include(TableGen) 13 | include(HandleLLVMOptions) 14 | 15 | SET(CXX_MLIR_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 16 | SET(CXX_MLIR_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) 17 | 18 | add_subdirectory(cxx/mlir) 19 | -------------------------------------------------------------------------------- /src/mlir/cxx/mlir/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include_directories(${MLIR_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) # for tablegen 3 | add_mlir_dialect(CxxOps cxx) 4 | 5 | aux_source_directory(. SOURCES) 6 | add_library(cxx-mlir ${SOURCES}) 7 | 8 | llvm_update_compile_flags(cxx-mlir) 9 | 10 | target_include_directories(cxx-mlir 11 | PUBLIC ${CXX_MLIR_SOURCE_DIR} ${CXX_MLIR_BINARY_DIR} 12 | ${MLIR_INCLUDE_DIRS} 13 | ${LLVM_INCLUDE_DIRS} 14 | ) 15 | 16 | target_link_libraries(cxx-mlir PUBLIC 17 | cxx-parser 18 | MLIRIR 19 | MLIRFuncDialect 20 | MLIRControlFlowDialect 21 | MLIRSCFDialect 22 | ) 23 | 24 | target_compile_definitions(cxx-mlir PUBLIC CXX_WITH_MLIR) 25 | 26 | add_dependencies(cxx-mlir MLIRCxxOpsIncGen) 27 | 28 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") 29 | target_compile_options(cxx-mlir PRIVATE 30 | -Wno-unused-variable 31 | -Wno-covered-switch-default 32 | -Wno-unused-but-set-variable 33 | ) 34 | endif() 35 | -------------------------------------------------------------------------------- /src/mlir/cxx/mlir/cxx_dialect.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | // mlir 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace mlir::cxx { 32 | 33 | void CxxDialect::initialize() { 34 | addOperations< 35 | #define GET_OP_LIST 36 | #include 37 | >(); 38 | 39 | addTypes< 40 | #define GET_TYPEDEF_LIST 41 | #include 42 | >(); 43 | } 44 | 45 | } // namespace mlir::cxx 46 | 47 | #define GET_TYPEDEF_CLASSES 48 | #include 49 | 50 | #define GET_OP_CLASSES 51 | #include 52 | #include 53 | -------------------------------------------------------------------------------- /src/mlir/cxx/mlir/cxx_dialect.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | #define GET_TYPEDEF_CLASSES 28 | #include 29 | 30 | #define GET_OP_CLASSES 31 | #include 32 | -------------------------------------------------------------------------------- /src/parser/cxx/arena.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace cxx { 29 | 30 | class Arena : public std::pmr::monotonic_buffer_resource { 31 | public: 32 | using monotonic_buffer_resource::monotonic_buffer_resource; 33 | }; 34 | 35 | struct Managed { 36 | auto operator new(std::size_t size, Arena* arena) noexcept -> void* { 37 | return arena->allocate(size); 38 | } 39 | void operator delete(void* ptr, std::size_t) {} 40 | void operator delete(void* ptr, Arena*) noexcept {} 41 | }; 42 | 43 | } // namespace cxx 44 | -------------------------------------------------------------------------------- /src/parser/cxx/ast_cursor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace cxx { 30 | 31 | class ASTCursor { 32 | public: 33 | struct Node { 34 | std::variant*> node; 35 | std::string_view name; 36 | }; 37 | 38 | ASTCursor() = default; 39 | ~ASTCursor(); 40 | 41 | ASTCursor(const ASTCursor&) = default; 42 | ASTCursor& operator=(const ASTCursor&) = default; 43 | 44 | ASTCursor(ASTCursor&&) = default; 45 | ASTCursor& operator=(ASTCursor&&) = default; 46 | 47 | ASTCursor(AST* root, std::string_view name); 48 | 49 | explicit operator bool() const { return !empty(); } 50 | 51 | [[nodiscard]] auto empty() const -> bool { return stack_.empty(); } 52 | 53 | [[nodiscard]] auto operator*() const -> const Node& { return stack_.back(); } 54 | 55 | void step(); 56 | 57 | auto operator++() -> ASTCursor& { 58 | step(); 59 | return *this; 60 | } 61 | 62 | private: 63 | std::deque stack_; 64 | }; 65 | 66 | } // namespace cxx -------------------------------------------------------------------------------- /src/parser/cxx/base_classes.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | -------------------------------------------------------------------------------- /src/parser/cxx/builtins.kwgen: -------------------------------------------------------------------------------- 1 | %no-enums 2 | %token-prefix=cxx::BuiltinTypeTraitKind::T_ 3 | %token-type=cxx::BuiltinTypeTraitKind 4 | %classifier=isBuiltin 5 | %toupper 6 | 7 | %% 8 | __has_unique_object_representations 9 | __has_virtual_destructor 10 | __is_abstract 11 | __is_aggregate 12 | __is_arithmetic 13 | __is_array 14 | __is_assignable 15 | __is_base_of 16 | __is_bounded_array 17 | __is_class 18 | __is_compound 19 | __is_const 20 | __is_empty 21 | __is_enum 22 | __is_final 23 | __is_floating_point 24 | __is_function 25 | __is_fundamental 26 | __is_integral 27 | __is_layout_compatible 28 | __is_literal_type 29 | __is_lvalue_reference 30 | __is_member_function_pointer 31 | __is_member_object_pointer 32 | __is_member_pointer 33 | __is_null_pointer 34 | __is_object 35 | __is_pod 36 | __is_pointer 37 | __is_polymorphic 38 | __is_reference 39 | __is_rvalue_reference 40 | __is_same_as 41 | __is_same 42 | __is_scalar 43 | __is_scoped_enum 44 | __is_signed 45 | __is_standard_layout 46 | __is_swappable_with 47 | __is_trivial 48 | __is_unbounded_array 49 | __is_union 50 | __is_unsigned 51 | __is_void 52 | __is_volatile 53 | -------------------------------------------------------------------------------- /src/parser/cxx/const_value.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | namespace cxx {} -------------------------------------------------------------------------------- /src/parser/cxx/const_value.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | namespace cxx { 30 | 31 | using ConstValue = 32 | std::variant; 34 | 35 | template 36 | struct ArithmeticConversion { 37 | auto operator()(const StringLiteral* value) const -> ConstValue { 38 | return ConstValue(value); 39 | } 40 | 41 | auto operator()(auto value) const -> ConstValue { 42 | return ConstValue(static_cast(value)); 43 | } 44 | }; 45 | 46 | template 47 | struct ArithmeticCast { 48 | auto operator()(const StringLiteral*) const -> T { 49 | cxx_runtime_error("invalid artihmetic cast"); 50 | return T{}; 51 | } 52 | 53 | auto operator()(auto value) const -> T { return static_cast(value); } 54 | }; 55 | 56 | } // namespace cxx -------------------------------------------------------------------------------- /src/parser/cxx/cxx.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #if __cpp_exceptions 28 | #include 29 | #endif 30 | 31 | namespace cxx { 32 | 33 | [[noreturn]] void cxx_runtime_error(const std::string& msg) { 34 | #if __cpp_exceptions 35 | throw std::runtime_error(msg); 36 | #else 37 | std::cerr << std::format("cxx_runtime_error: {}\n", msg); 38 | std::abort(); 39 | #endif 40 | } 41 | 42 | } // namespace cxx 43 | -------------------------------------------------------------------------------- /src/parser/cxx/cxx_fwd.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace cxx { 26 | 27 | class Arena; 28 | class Control; 29 | class TranslationUnit; 30 | 31 | [[noreturn]] void cxx_runtime_error(const std::string& msg); 32 | 33 | } // namespace cxx 34 | -------------------------------------------------------------------------------- /src/parser/cxx/diagnostic.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | #include 23 | 24 | namespace cxx { 25 | 26 | Diagnostic::Diagnostic(Severity severity, const Token& token, 27 | std::string message) 28 | : message_(std::move(message)), token_(token), severity_(severity) {} 29 | 30 | } // namespace cxx 31 | -------------------------------------------------------------------------------- /src/parser/cxx/diagnostic.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace cxx { 28 | 29 | enum class Severity { Message, Warning, Error, Fatal }; 30 | 31 | class Diagnostic { 32 | std::string message_; 33 | Token token_; 34 | Severity severity_ = Severity::Message; 35 | 36 | public: 37 | Diagnostic() = default; 38 | 39 | Diagnostic(const Diagnostic&) = default; 40 | auto operator=(const Diagnostic&) -> Diagnostic& = default; 41 | 42 | Diagnostic(Diagnostic&&) = default; 43 | auto operator=(Diagnostic&&) -> Diagnostic& = default; 44 | 45 | Diagnostic(Severity severity, const Token& token, std::string message); 46 | 47 | [[nodiscard]] auto severity() const -> Severity { return severity_; } 48 | 49 | [[nodiscard]] auto token() const -> const Token& { return token_; } 50 | 51 | [[nodiscard]] auto message() const -> const std::string& { return message_; } 52 | }; 53 | 54 | } // namespace cxx 55 | -------------------------------------------------------------------------------- /src/parser/cxx/external_name_encoder.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace cxx { 30 | 31 | class ExternalNameEncoder { 32 | public: 33 | ExternalNameEncoder(); 34 | 35 | [[nodiscard]] auto encode(Symbol* symbol) -> std::string; 36 | [[nodiscard]] auto encode(const Type* type) -> std::string; 37 | 38 | private: 39 | void out(std::string_view s); 40 | 41 | struct NameVisitor; 42 | struct TypeVisitor; 43 | struct SymbolVisitor; 44 | 45 | private: 46 | std::string externalName_; 47 | }; 48 | 49 | } // namespace cxx -------------------------------------------------------------------------------- /src/parser/cxx/gcc_linux_toolchain.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace cxx { 29 | 30 | class GCCLinuxToolchain final : public Toolchain { 31 | public: 32 | explicit GCCLinuxToolchain(Preprocessor* preprocessor, 33 | std::string arch = "x86_64"); 34 | 35 | [[nodiscard]] auto version() const -> std::optional { return version_; } 36 | 37 | void addSystemIncludePaths() override; 38 | void addSystemCppIncludePaths() override; 39 | void addPredefinedMacros() override; 40 | 41 | void addCommonMacros(); 42 | void addAmd64Macros(); 43 | void addArm64Macros(); 44 | 45 | private: 46 | std::optional version_; 47 | std::string arch_; 48 | }; 49 | 50 | } // namespace cxx 51 | -------------------------------------------------------------------------------- /src/parser/cxx/keywords.kwgen: -------------------------------------------------------------------------------- 1 | %no-enums 2 | %token-prefix=cxx::TokenKind::T_ 3 | %token-type=cxx::TokenKind 4 | %toupper 5 | 6 | %% 7 | alignas 8 | alignof 9 | asm 10 | auto 11 | bool 12 | break 13 | case 14 | catch 15 | char 16 | char16_t 17 | char32_t 18 | char8_t 19 | class 20 | co_await 21 | co_return 22 | co_yield 23 | concept 24 | const_cast 25 | const 26 | consteval 27 | constexpr 28 | constinit 29 | continue 30 | decltype 31 | default 32 | delete 33 | do 34 | double 35 | dynamic_cast 36 | else 37 | enum 38 | explicit 39 | export 40 | extern 41 | false 42 | float 43 | for 44 | friend 45 | goto 46 | if 47 | inline 48 | int 49 | long 50 | mutable 51 | namespace 52 | new 53 | noexcept 54 | nullptr 55 | operator 56 | private 57 | protected 58 | public 59 | reinterpret_cast 60 | requires 61 | return 62 | short 63 | signed 64 | sizeof 65 | static_assert 66 | static_cast 67 | static 68 | struct 69 | switch 70 | template 71 | this 72 | thread_local 73 | throw 74 | true 75 | try 76 | typedef 77 | typeid 78 | typename 79 | union 80 | unsigned 81 | using 82 | virtual 83 | void 84 | volatile 85 | wchar_t 86 | while 87 | __attribute__ 88 | __builtin_bit_cast 89 | __builtin_offsetof 90 | __builtin_va_arg 91 | __builtin_va_list 92 | __complex__ 93 | __extension__ 94 | __float128 95 | __float80 96 | __imag__ 97 | __int128 98 | __int64 99 | __real__ 100 | __restrict__ 101 | __thread 102 | __underlying_type 103 | _Atomic 104 | _Complex 105 | 106 | and_eq 107 | and 108 | bitand 109 | bitor 110 | compl 111 | not_eq 112 | not 113 | or_eq 114 | or 115 | xor_eq 116 | xor 117 | __alignof__ 118 | __alignof 119 | __asm__ 120 | __asm 121 | __attribute 122 | __decltype__ 123 | __decltype 124 | __inline__ 125 | __inline 126 | __restrict 127 | __typeof__ 128 | __typeof 129 | __volatile__ 130 | __volatile 131 | _Alignof 132 | _Static_assert 133 | -------------------------------------------------------------------------------- /src/parser/cxx/literals_fwd.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | namespace cxx { 24 | 25 | class Literal; 26 | 27 | class IntegerLiteral; 28 | class FloatLiteral; 29 | class StringLiteral; 30 | class WideStringLiteral; 31 | class Utf8StringLiteral; 32 | class Utf16StringLiteral; 33 | class Utf32StringLiteral; 34 | class CharLiteral; 35 | class CommentLiteral; 36 | 37 | } // namespace cxx 38 | -------------------------------------------------------------------------------- /src/parser/cxx/macos_toolchain.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace cxx { 28 | 29 | class MacOSToolchain final : public Toolchain { 30 | public: 31 | using Toolchain::Toolchain; 32 | 33 | explicit MacOSToolchain(Preprocessor* preprocessor); 34 | 35 | [[nodiscard]] auto arch() const -> std::string { return arch_; } 36 | void setArch(std::string arch) { arch_ = std::move(arch); } 37 | 38 | void addSystemIncludePaths() override; 39 | void addSystemCppIncludePaths() override; 40 | void addPredefinedMacros() override; 41 | 42 | void addCommonMacros(); 43 | void addCxx20Macros(); 44 | void addCxx23Macros(); 45 | void addCxx26Macros(); 46 | void addArm64Macros(); 47 | void addAmd64Macros(); 48 | 49 | private: 50 | std::string platformPath_; 51 | std::string toolchainPath_; 52 | std::string arch_{"aarch64"}; 53 | }; 54 | 55 | } // namespace cxx 56 | -------------------------------------------------------------------------------- /src/parser/cxx/names_fwd.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace cxx { 32 | 33 | #define CXX_FOR_EACH_NAME(V) \ 34 | V(Identifier) \ 35 | V(OperatorId) \ 36 | V(DestructorId) \ 37 | V(LiteralOperatorId) \ 38 | V(ConversionFunctionId) \ 39 | V(TemplateId) 40 | 41 | #define PROCESS_NAME(N) k##N, 42 | enum class NameKind { CXX_FOR_EACH_NAME(PROCESS_NAME) }; 43 | #undef PROCESS_NAME 44 | 45 | class Name; 46 | 47 | #define PROCESS_NAME(N) class N; 48 | CXX_FOR_EACH_NAME(PROCESS_NAME) 49 | #undef PROCESS_NAME 50 | 51 | class Symbol; 52 | 53 | using TemplateArgument = 54 | std::variant; 55 | 56 | enum class IdentifierInfoKind { 57 | kTypeTrait, 58 | }; 59 | 60 | class IdentifierInfo; 61 | class TypeTraitIdentifierInfo; 62 | 63 | auto to_string(const Name* name) -> std::string; 64 | 65 | } // namespace cxx 66 | -------------------------------------------------------------------------------- /src/parser/cxx/parser_fwd.h: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) 2025 Roberto Raggi 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace cxx { 32 | 33 | class Parser; 34 | 35 | struct UnqualifiedCompletionContext { 36 | Scope* scope = nullptr; 37 | }; 38 | 39 | struct MemberCompletionContext { 40 | const Type* objectType = nullptr; 41 | TokenKind accessOp = TokenKind::T_DOT; 42 | }; 43 | 44 | using CodeCompletionContext = 45 | std::variant; 46 | 47 | struct ParserConfiguration { 48 | bool checkTypes = false; 49 | bool fuzzyTemplateResolution = false; 50 | bool templateInstantiation = true; 51 | bool reflect = true; 52 | std::function stopParsingPredicate; 53 | std::function complete; 54 | }; 55 | 56 | } // namespace cxx 57 | -------------------------------------------------------------------------------- /src/parser/cxx/pp_keywords.kwgen: -------------------------------------------------------------------------------- 1 | %token-prefix=PreprocessorDirectiveKind::T_ 2 | %token-type=PreprocessorDirectiveKind 3 | %classifier=classifyDirective 4 | %toupper 5 | 6 | %% 7 | 8 | define 9 | elif 10 | elifdef 11 | elifndef 12 | else 13 | endif 14 | error 15 | if 16 | ifdef 17 | ifndef 18 | include 19 | include_next 20 | line 21 | pragma 22 | undef 23 | warning 24 | -------------------------------------------------------------------------------- /src/parser/cxx/source_location.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | -------------------------------------------------------------------------------- /src/parser/cxx/symbol_chain_view.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | // cxx 24 | #include 25 | 26 | namespace cxx { 27 | 28 | auto SymbolChainView::Generator::operator++() -> Generator& { 29 | auto name = symbol_->name(); 30 | do { 31 | symbol_ = symbol_->next(); 32 | } while (symbol_ && symbol_->name() != name); 33 | return *this; 34 | } 35 | 36 | } // namespace cxx -------------------------------------------------------------------------------- /src/parser/cxx/toolchain.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | // cxx 24 | #include 25 | #include 26 | 27 | namespace cxx { 28 | 29 | Toolchain::Toolchain(Preprocessor* preprocessor) : preprocessor_(preprocessor) { 30 | setMemoryLayout(std::make_unique(64)); 31 | } 32 | 33 | Toolchain::~Toolchain() = default; 34 | 35 | void Toolchain::setMemoryLayout(std::unique_ptr memoryLayout) { 36 | memoryLayout_ = std::move(memoryLayout); 37 | } 38 | 39 | void Toolchain::defineMacro(const std::string& name, 40 | const std::string& definition) { 41 | preprocessor_->defineMacro(name, definition); 42 | } 43 | 44 | void Toolchain::addSystemIncludePath(std::string path) { 45 | preprocessor_->addSystemIncludePath(std::move(path)); 46 | } 47 | 48 | } // namespace cxx 49 | -------------------------------------------------------------------------------- /src/parser/cxx/type_checker.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace cxx { 28 | 29 | class TranslationUnit; 30 | 31 | class TypeChecker { 32 | public: 33 | explicit TypeChecker(TranslationUnit* unit); 34 | 35 | [[nodiscard]] auto translationUnit() const -> TranslationUnit* { 36 | return unit_; 37 | } 38 | 39 | [[nodiscard]] auto reportErrors() const -> bool { return reportErrors_; } 40 | void setReportErrors(bool reportErrors) { reportErrors_ = reportErrors; } 41 | 42 | void setScope(Scope* scope) { scope_ = scope; } 43 | 44 | void operator()(ExpressionAST* ast); 45 | 46 | void check(ExpressionAST* ast); 47 | 48 | private: 49 | struct Visitor; 50 | 51 | TranslationUnit* unit_; 52 | Scope* scope_ = nullptr; 53 | bool reportErrors_ = false; 54 | }; 55 | 56 | } // namespace cxx 57 | -------------------------------------------------------------------------------- /src/parser/cxx/type_traits.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | namespace cxx {} // namespace cxx 24 | -------------------------------------------------------------------------------- /src/parser/cxx/types.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | // cxx 24 | #include 25 | 26 | namespace cxx { 27 | 28 | auto EnumType::underlyingType() const -> const Type* { 29 | return symbol()->underlyingType(); 30 | } 31 | 32 | auto ScopedEnumType::underlyingType() const -> const Type* { 33 | return symbol()->underlyingType(); 34 | } 35 | 36 | auto ClassType::isComplete() const -> bool { return symbol()->isComplete(); } 37 | 38 | auto ClassType::isUnion() const -> bool { return symbol()->isUnion(); } 39 | 40 | } // namespace cxx 41 | -------------------------------------------------------------------------------- /src/parser/cxx/util.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include 22 | 23 | namespace cxx { 24 | 25 | auto align_to(int n, int align) -> int { 26 | return (n + align - 1) / align * align; 27 | } 28 | 29 | } // namespace cxx 30 | -------------------------------------------------------------------------------- /src/parser/cxx/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace cxx { 26 | 27 | auto align_to(int n, int align) -> int; 28 | 29 | template 30 | void hash_combine(std::size_t &seed, const T &val) { 31 | seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 32 | } 33 | 34 | } // namespace cxx -------------------------------------------------------------------------------- /src/parser/cxx/wasm32_wasi_toolchain.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace cxx { 29 | 30 | class Wasm32WasiToolchain final : public Toolchain { 31 | public: 32 | explicit Wasm32WasiToolchain(Preprocessor* preprocessor); 33 | 34 | const std::string& appdir() const; 35 | void setAppdir(std::string appdir); 36 | 37 | const std::string& sysroot() const; 38 | void setSysroot(std::string sysroot); 39 | 40 | void addSystemIncludePaths() override; 41 | void addSystemCppIncludePaths() override; 42 | void addPredefinedMacros() override; 43 | 44 | private: 45 | std::string appdir_; 46 | std::string sysroot_; 47 | std::optional version_; 48 | }; 49 | 50 | } // namespace cxx 51 | -------------------------------------------------------------------------------- /src/parser/cxx/windows_toolchain.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Roberto Raggi 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace cxx { 28 | 29 | class WindowsToolchain final : public Toolchain { 30 | public: 31 | using Toolchain::Toolchain; 32 | 33 | void setVctoolsdir(std::string path); 34 | void setWinsdkdir(std::string path); 35 | 36 | void setWinsdkversion(std::string version); 37 | 38 | void addSystemIncludePaths() override; 39 | void addSystemCppIncludePaths() override; 40 | void addPredefinedMacros() override; 41 | 42 | private: 43 | std::string vctoolsdir_; 44 | std::string winsdkdir_; 45 | std::string winsdkversion_; 46 | }; 47 | 48 | } // namespace cxx 49 | -------------------------------------------------------------------------------- /templates/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-browser-esm-vite", 3 | "private": true, 4 | "version": "1.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "typescript": "latest", 13 | "vite": "latest" 14 | }, 15 | "dependencies": { 16 | "cxx-frontend": "^1.1.27" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /templates/cxx-browser-esm-vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src"] 23 | } 24 | -------------------------------------------------------------------------------- /templates/cxx-parse-esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-parse-esm", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "description": "Dump C++ AST to the standard output", 7 | "main": "index.js", 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": { 13 | "name": "Roberto Raggi", 14 | "email": "roberto.raggi@gmail.com" 15 | }, 16 | "license": "MIT", 17 | "dependencies": { 18 | "cxx-frontend": "^1.1.27" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /templates/cxx-parse/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@robertoraggi/cxx-parse", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "commonjs", 6 | "description": "Dump C++ AST to the standard output", 7 | "main": "index.js", 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": { 13 | "name": "Roberto Raggi", 14 | "email": "roberto.raggi@gmail.com" 15 | }, 16 | "license": "MIT", 17 | "dependencies": { 18 | "cxx-frontend": "^1.1.27" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(unit_tests) 2 | add_subdirectory(api_tests) 3 | -------------------------------------------------------------------------------- /tests/api_tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | if (CMAKE_SYSTEM_NAME STREQUAL "WASI") 22 | return() 23 | endif() 24 | 25 | add_executable(test_api 26 | test_control.cc 27 | test_external_names.cc 28 | test_rewriter.cc 29 | test_substitution.cc 30 | test_type_printer.cc 31 | ) 32 | 33 | target_link_libraries(test_api 34 | GTest::gtest_main 35 | cxx-parser) 36 | 37 | gtest_discover_tests(test_api DISCOVERY_MODE PRE_TEST) 38 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME ast 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/access_declaration_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | class SimpleClass { 4 | private: 5 | protected: 6 | public: 7 | }; 8 | 9 | // clang-format off 10 | // CHECK:translation-unit 11 | // CHECK-NEXT: declaration-list 12 | // CHECK-NEXT: simple-declaration 13 | // CHECK-NEXT: decl-specifier-list 14 | // CHECK-NEXT: class-specifier 15 | // CHECK-NEXT: class-key: class 16 | // CHECK-NEXT: unqualified-id: name-id 17 | // CHECK-NEXT: identifier: SimpleClass 18 | // CHECK-NEXT: declaration-list 19 | // CHECK-NEXT: access-declaration 20 | // CHECK-NEXT: access-specifier: private 21 | // CHECK-NEXT: access-declaration 22 | // CHECK-NEXT: access-specifier: protected 23 | // CHECK-NEXT: access-declaration 24 | // CHECK-NEXT: access-specifier: public 25 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/bitfield_declaration_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | struct Bits { 4 | int value : 32; 5 | }; 6 | 7 | // clang-format off 8 | // CHECK:translation-unit 9 | // CHECK-NEXT: declaration-list 10 | // CHECK-NEXT: simple-declaration 11 | // CHECK-NEXT: decl-specifier-list 12 | // CHECK-NEXT: class-specifier 13 | // CHECK-NEXT: class-key: struct 14 | // CHECK-NEXT: unqualified-id: name-id 15 | // CHECK-NEXT: identifier: Bits 16 | // CHECK-NEXT: declaration-list 17 | // CHECK-NEXT: simple-declaration 18 | // CHECK-NEXT: decl-specifier-list 19 | // CHECK-NEXT: integral-type-specifier 20 | // CHECK-NEXT: specifier: int 21 | // CHECK-NEXT: init-declarator-list 22 | // CHECK-NEXT: init-declarator 23 | // CHECK-NEXT: declarator: declarator 24 | // CHECK-NEXT: core-declarator: bitfield-declarator 25 | // CHECK-NEXT: unqualified-id: name-id 26 | // CHECK-NEXT: identifier: value 27 | // CHECK-NEXT: size-expression: int-literal-expression [prvalue int] 28 | // CHECK-NEXT: literal: 32 29 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/bool_literals_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | const bool ok = true; 4 | const bool ko = false; 5 | 6 | // clang-format off 7 | // CHECK:translation-unit 8 | // CHECK-NEXT: declaration-list 9 | // CHECK-NEXT: simple-declaration 10 | // CHECK-NEXT: decl-specifier-list 11 | // CHECK-NEXT: const-qualifier 12 | // CHECK-NEXT: integral-type-specifier 13 | // CHECK-NEXT: specifier: bool 14 | // CHECK-NEXT: init-declarator-list 15 | // CHECK-NEXT: init-declarator 16 | // CHECK-NEXT: declarator: declarator 17 | // CHECK-NEXT: core-declarator: id-declarator 18 | // CHECK-NEXT: unqualified-id: name-id 19 | // CHECK-NEXT: identifier: ok 20 | // CHECK-NEXT: initializer: equal-initializer [prvalue bool] 21 | // CHECK-NEXT: expression: bool-literal-expression [prvalue bool] 22 | // CHECK-NEXT: is-true: true 23 | // CHECK-NEXT: simple-declaration 24 | // CHECK-NEXT: decl-specifier-list 25 | // CHECK-NEXT: const-qualifier 26 | // CHECK-NEXT: integral-type-specifier 27 | // CHECK-NEXT: specifier: bool 28 | // CHECK-NEXT: init-declarator-list 29 | // CHECK-NEXT: init-declarator 30 | // CHECK-NEXT: declarator: declarator 31 | // CHECK-NEXT: core-declarator: id-declarator 32 | // CHECK-NEXT: unqualified-id: name-id 33 | // CHECK-NEXT: identifier: ko 34 | // CHECK-NEXT: initializer: equal-initializer [prvalue bool] 35 | // CHECK-NEXT: expression: bool-literal-expression [prvalue bool] 36 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/complex_type_specifier_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | __complex__ float a; 4 | __complex__ double b; 5 | 6 | // clang-format off 7 | // CHECK:translation-unit 8 | // CHECK-NEXT: declaration-list 9 | // CHECK-NEXT: simple-declaration 10 | // CHECK-NEXT: decl-specifier-list 11 | // CHECK-NEXT: complex-type-specifier 12 | // CHECK-NEXT: floating-point-type-specifier 13 | // CHECK-NEXT: specifier: float 14 | // CHECK-NEXT: init-declarator-list 15 | // CHECK-NEXT: init-declarator 16 | // CHECK-NEXT: declarator: declarator 17 | // CHECK-NEXT: core-declarator: id-declarator 18 | // CHECK-NEXT: unqualified-id: name-id 19 | // CHECK-NEXT: identifier: a 20 | // CHECK-NEXT: simple-declaration 21 | // CHECK-NEXT: decl-specifier-list 22 | // CHECK-NEXT: complex-type-specifier 23 | // CHECK-NEXT: floating-point-type-specifier 24 | // CHECK-NEXT: specifier: double 25 | // CHECK-NEXT: init-declarator-list 26 | // CHECK-NEXT: init-declarator 27 | // CHECK-NEXT: declarator: declarator 28 | // CHECK-NEXT: core-declarator: id-declarator 29 | // CHECK-NEXT: unqualified-id: name-id 30 | // CHECK-NEXT: identifier: b 31 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/consteval_if_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | auto main() -> int { 4 | if consteval { 5 | } 6 | 7 | if !consteval { 8 | } 9 | 10 | if consteval { 11 | } else { 12 | } 13 | 14 | if !consteval { 15 | } else { 16 | } 17 | } 18 | 19 | // clang-format off 20 | // CHECK:translation-unit 21 | // CHECK-NEXT: declaration-list 22 | // CHECK-NEXT: function-definition 23 | // CHECK-NEXT: decl-specifier-list 24 | // CHECK-NEXT: auto-type-specifier 25 | // CHECK-NEXT: declarator: declarator 26 | // CHECK-NEXT: core-declarator: id-declarator 27 | // CHECK-NEXT: unqualified-id: name-id 28 | // CHECK-NEXT: identifier: main 29 | // CHECK-NEXT: declarator-chunk-list 30 | // CHECK-NEXT: function-declarator-chunk 31 | // CHECK-NEXT: trailing-return-type: trailing-return-type 32 | // CHECK-NEXT: type-id: type-id 33 | // CHECK-NEXT: type-specifier-list 34 | // CHECK-NEXT: integral-type-specifier 35 | // CHECK-NEXT: specifier: int 36 | // CHECK-NEXT: function-body: compound-statement-function-body 37 | // CHECK-NEXT: statement: compound-statement 38 | // CHECK-NEXT: statement-list 39 | // CHECK-NEXT: consteval-if-statement 40 | // CHECK-NEXT: statement: compound-statement 41 | // CHECK-NEXT: consteval-if-statement 42 | // CHECK-NEXT: is-not: true 43 | // CHECK-NEXT: statement: compound-statement 44 | // CHECK-NEXT: consteval-if-statement 45 | // CHECK-NEXT: statement: compound-statement 46 | // CHECK-NEXT: else-statement: compound-statement 47 | // CHECK-NEXT: consteval-if-statement 48 | // CHECK-NEXT: is-not: true 49 | // CHECK-NEXT: statement: compound-statement 50 | // CHECK-NEXT: else-statement: compound-statement 51 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/equal_initializer_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | const int values[] = { 4 | 1, 5 | 2, 6 | 3, 7 | }; 8 | 9 | // clang-format off 10 | // CHECK:translation-unit 11 | // CHECK-NEXT: declaration-list 12 | // CHECK-NEXT: simple-declaration 13 | // CHECK-NEXT: decl-specifier-list 14 | // CHECK-NEXT: const-qualifier 15 | // CHECK-NEXT: integral-type-specifier 16 | // CHECK-NEXT: specifier: int 17 | // CHECK-NEXT: init-declarator-list 18 | // CHECK-NEXT: init-declarator 19 | // CHECK-NEXT: declarator: declarator 20 | // CHECK-NEXT: core-declarator: id-declarator 21 | // CHECK-NEXT: unqualified-id: name-id 22 | // CHECK-NEXT: identifier: values 23 | // CHECK-NEXT: declarator-chunk-list 24 | // CHECK-NEXT: array-declarator-chunk 25 | // CHECK-NEXT: initializer: equal-initializer 26 | // CHECK-NEXT: expression: braced-init-list 27 | // CHECK-NEXT: expression-list 28 | // CHECK-NEXT: int-literal-expression [prvalue int] 29 | // CHECK-NEXT: literal: 1 30 | // CHECK-NEXT: int-literal-expression [prvalue int] 31 | // CHECK-NEXT: literal: 2 32 | // CHECK-NEXT: int-literal-expression [prvalue int] 33 | // CHECK-NEXT: literal: 3 34 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/for_range_statement_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | int main() { 4 | for (int i : {10, 20, 30}) { 5 | } 6 | } 7 | 8 | // clang-format off 9 | // CHECK:translation-unit 10 | // CHECK-NEXT: declaration-list 11 | // CHECK-NEXT: function-definition 12 | // CHECK-NEXT: decl-specifier-list 13 | // CHECK-NEXT: integral-type-specifier 14 | // CHECK-NEXT: specifier: int 15 | // CHECK-NEXT: declarator: declarator 16 | // CHECK-NEXT: core-declarator: id-declarator 17 | // CHECK-NEXT: unqualified-id: name-id 18 | // CHECK-NEXT: identifier: main 19 | // CHECK-NEXT: declarator-chunk-list 20 | // CHECK-NEXT: function-declarator-chunk 21 | // CHECK-NEXT: function-body: compound-statement-function-body 22 | // CHECK-NEXT: statement: compound-statement 23 | // CHECK-NEXT: statement-list 24 | // CHECK-NEXT: for-range-statement 25 | // CHECK-NEXT: range-declaration: simple-declaration 26 | // CHECK-NEXT: decl-specifier-list 27 | // CHECK-NEXT: integral-type-specifier 28 | // CHECK-NEXT: specifier: int 29 | // CHECK-NEXT: init-declarator-list 30 | // CHECK-NEXT: init-declarator 31 | // CHECK-NEXT: declarator: declarator 32 | // CHECK-NEXT: core-declarator: id-declarator 33 | // CHECK-NEXT: unqualified-id: name-id 34 | // CHECK-NEXT: identifier: i 35 | // CHECK-NEXT: range-initializer: braced-init-list 36 | // CHECK-NEXT: expression-list 37 | // CHECK-NEXT: int-literal-expression [prvalue int] 38 | // CHECK-NEXT: literal: 10 39 | // CHECK-NEXT: int-literal-expression [prvalue int] 40 | // CHECK-NEXT: literal: 20 41 | // CHECK-NEXT: int-literal-expression [prvalue int] 42 | // CHECK-NEXT: literal: 30 43 | // CHECK-NEXT: statement: compound-statement 44 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/if_statement_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | auto main() -> int { 4 | if (false) 5 | 6 | // expected-error@1 {{expected a statement}} 7 | } 8 | 9 | // clang-format off 10 | // CHECK:translation-unit 11 | // CHECK-NEXT: declaration-list 12 | // CHECK-NEXT: function-definition 13 | // CHECK-NEXT: decl-specifier-list 14 | // CHECK-NEXT: auto-type-specifier 15 | // CHECK-NEXT: declarator: declarator 16 | // CHECK-NEXT: core-declarator: id-declarator 17 | // CHECK-NEXT: unqualified-id: name-id 18 | // CHECK-NEXT: identifier: main 19 | // CHECK-NEXT: declarator-chunk-list 20 | // CHECK-NEXT: function-declarator-chunk 21 | // CHECK-NEXT: trailing-return-type: trailing-return-type 22 | // CHECK-NEXT: type-id: type-id 23 | // CHECK-NEXT: type-specifier-list 24 | // CHECK-NEXT: integral-type-specifier 25 | // CHECK-NEXT: specifier: int 26 | // CHECK-NEXT: function-body: compound-statement-function-body 27 | // CHECK-NEXT: statement: compound-statement 28 | // CHECK-NEXT: statement-list 29 | // CHECK-NEXT: if-statement 30 | // CHECK-NEXT: condition: bool-literal-expression [prvalue bool] 31 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/namespace_definition_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | namespace {} 4 | 5 | inline namespace {} 6 | 7 | namespace ns1 {} 8 | 9 | inline namespace ns1 {} 10 | 11 | namespace n2::n3 {} 12 | 13 | namespace n2::inline n4::n5 {} 14 | 15 | namespace n2::inline n4::inline n6 {} 16 | 17 | // clang-format off 18 | // CHECK:translation-unit 19 | // CHECK-NEXT: declaration-list 20 | // CHECK-NEXT: namespace-definition 21 | // CHECK-NEXT: namespace-definition 22 | // CHECK-NEXT: is-inline: true 23 | // CHECK-NEXT: namespace-definition 24 | // CHECK-NEXT: identifier: ns1 25 | // CHECK-NEXT: namespace-definition 26 | // CHECK-NEXT: identifier: ns1 27 | // CHECK-NEXT: is-inline: true 28 | // CHECK-NEXT: namespace-definition 29 | // CHECK-NEXT: identifier: n3 30 | // CHECK-NEXT: nested-namespace-specifier-list 31 | // CHECK-NEXT: nested-namespace-specifier 32 | // CHECK-NEXT: identifier: n2 33 | // CHECK-NEXT: namespace-definition 34 | // CHECK-NEXT: identifier: n5 35 | // CHECK-NEXT: nested-namespace-specifier-list 36 | // CHECK-NEXT: nested-namespace-specifier 37 | // CHECK-NEXT: identifier: n2 38 | // CHECK-NEXT: nested-namespace-specifier 39 | // CHECK-NEXT: identifier: n4 40 | // CHECK-NEXT: is-inline: true 41 | // CHECK-NEXT: namespace-definition 42 | // CHECK-NEXT: identifier: n6 43 | // CHECK-NEXT: is-inline: true 44 | // CHECK-NEXT: nested-namespace-specifier-list 45 | // CHECK-NEXT: nested-namespace-specifier 46 | // CHECK-NEXT: identifier: n2 47 | // CHECK-NEXT: nested-namespace-specifier 48 | // CHECK-NEXT: identifier: n4 49 | // CHECK-NEXT: is-inline: true 50 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/struct_alias_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | using Pair = struct { 4 | int a, b; 5 | }; 6 | 7 | // clang-format off 8 | // CHECK:translation-unit 9 | // CHECK-NEXT: declaration-list 10 | // CHECK-NEXT: alias-declaration 11 | // CHECK-NEXT: identifier: Pair 12 | // CHECK-NEXT: type-id: type-id 13 | // CHECK-NEXT: type-specifier-list 14 | // CHECK-NEXT: class-specifier 15 | // CHECK-NEXT: class-key: struct 16 | // CHECK-NEXT: declaration-list 17 | // CHECK-NEXT: simple-declaration 18 | // CHECK-NEXT: decl-specifier-list 19 | // CHECK-NEXT: integral-type-specifier 20 | // CHECK-NEXT: specifier: int 21 | // CHECK-NEXT: init-declarator-list 22 | // CHECK-NEXT: init-declarator 23 | // CHECK-NEXT: declarator: declarator 24 | // CHECK-NEXT: core-declarator: id-declarator 25 | // CHECK-NEXT: unqualified-id: name-id 26 | // CHECK-NEXT: identifier: a 27 | // CHECK-NEXT: init-declarator 28 | // CHECK-NEXT: declarator: declarator 29 | // CHECK-NEXT: core-declarator: id-declarator 30 | // CHECK-NEXT: unqualified-id: name-id 31 | // CHECK-NEXT: identifier: b 32 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/template_type_parameter_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | template class C> 4 | struct S { 5 | template 6 | struct S2 {}; 7 | }; 8 | 9 | // clang-format off 10 | // CHECK:translation-unit 11 | // CHECK-NEXT: declaration-list 12 | // CHECK-NEXT: template-declaration 13 | // CHECK-NEXT: template-parameter-list 14 | // CHECK-NEXT: typename-type-parameter 15 | // CHECK-NEXT: depth: 0 16 | // CHECK-NEXT: index: 0 17 | // CHECK-NEXT: identifier: T 18 | // CHECK-NEXT: template-type-parameter 19 | // CHECK-NEXT: depth: 0 20 | // CHECK-NEXT: index: 1 21 | // CHECK-NEXT: identifier: C 22 | // CHECK-NEXT: template-parameter-list 23 | // CHECK-NEXT: typename-type-parameter 24 | // CHECK-NEXT: depth: 1 25 | // CHECK-NEXT: index: 0 26 | // CHECK-NEXT: identifier: U 27 | // CHECK-NEXT: declaration: simple-declaration 28 | // CHECK-NEXT: decl-specifier-list 29 | // CHECK-NEXT: class-specifier 30 | // CHECK-NEXT: class-key: struct 31 | // CHECK-NEXT: unqualified-id: name-id 32 | // CHECK-NEXT: identifier: S 33 | // CHECK-NEXT: declaration-list 34 | // CHECK-NEXT: template-declaration 35 | // CHECK-NEXT: template-parameter-list 36 | // CHECK-NEXT: typename-type-parameter 37 | // CHECK-NEXT: depth: 1 38 | // CHECK-NEXT: index: 0 39 | // CHECK-NEXT: identifier: K 40 | // CHECK-NEXT: declaration: simple-declaration 41 | // CHECK-NEXT: decl-specifier-list 42 | // CHECK-NEXT: class-specifier 43 | // CHECK-NEXT: class-key: struct 44 | // CHECK-NEXT: unqualified-id: name-id 45 | // CHECK-NEXT: identifier: S2 46 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/underlying_type_specifier_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | enum class fruit { orange, apple }; 4 | 5 | using I = __underlying_type(fruit); 6 | 7 | // clang-format off 8 | // CHECK:translation-unit 9 | // CHECK-NEXT: declaration-list 10 | // CHECK-NEXT: simple-declaration 11 | // CHECK-NEXT: decl-specifier-list 12 | // CHECK-NEXT: enum-specifier 13 | // CHECK-NEXT: unqualified-id: name-id 14 | // CHECK-NEXT: identifier: fruit 15 | // CHECK-NEXT: enumerator-list 16 | // CHECK-NEXT: enumerator 17 | // CHECK-NEXT: identifier: orange 18 | // CHECK-NEXT: enumerator 19 | // CHECK-NEXT: identifier: apple 20 | // CHECK-NEXT: alias-declaration 21 | // CHECK-NEXT: identifier: I 22 | // CHECK-NEXT: type-id: type-id 23 | // CHECK-NEXT: type-specifier-list 24 | // CHECK-NEXT: underlying-type-specifier 25 | // CHECK-NEXT: type-id: type-id 26 | // CHECK-NEXT: type-specifier-list 27 | // CHECK-NEXT: named-type-specifier 28 | // CHECK-NEXT: unqualified-id: name-id 29 | // CHECK-NEXT: identifier: fruit 30 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/using_enum_declaration_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | enum class fruit { orange, apple }; 4 | 5 | struct S { 6 | using enum fruit; 7 | }; 8 | 9 | // clang-format off 10 | // CHECK:translation-unit 11 | // CHECK-NEXT: declaration-list 12 | // CHECK-NEXT: simple-declaration 13 | // CHECK-NEXT: decl-specifier-list 14 | // CHECK-NEXT: enum-specifier 15 | // CHECK-NEXT: unqualified-id: name-id 16 | // CHECK-NEXT: identifier: fruit 17 | // CHECK-NEXT: enumerator-list 18 | // CHECK-NEXT: enumerator 19 | // CHECK-NEXT: identifier: orange 20 | // CHECK-NEXT: enumerator 21 | // CHECK-NEXT: identifier: apple 22 | // CHECK-NEXT: simple-declaration 23 | // CHECK-NEXT: decl-specifier-list 24 | // CHECK-NEXT: class-specifier 25 | // CHECK-NEXT: class-key: struct 26 | // CHECK-NEXT: unqualified-id: name-id 27 | // CHECK-NEXT: identifier: S 28 | // CHECK-NEXT: declaration-list 29 | // CHECK-NEXT: using-enum-declaration 30 | // CHECK-NEXT: enum-type-specifier: elaborated-type-specifier 31 | // CHECK-NEXT: class-key: enum 32 | // CHECK-NEXT: unqualified-id: name-id 33 | // CHECK-NEXT: identifier: fruit 34 | -------------------------------------------------------------------------------- /tests/unit_tests/ast/variadic_function_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -ast-dump %s | %filecheck %s --match-full-lines 2 | 3 | void print_like(const char* fmt, ...); 4 | 5 | // clang-format off 6 | // CHECK:translation-unit 7 | // CHECK-NEXT: declaration-list 8 | // CHECK-NEXT: simple-declaration 9 | // CHECK-NEXT: decl-specifier-list 10 | // CHECK-NEXT: void-type-specifier 11 | // CHECK-NEXT: init-declarator-list 12 | // CHECK-NEXT: init-declarator 13 | // CHECK-NEXT: declarator: declarator 14 | // CHECK-NEXT: core-declarator: id-declarator 15 | // CHECK-NEXT: unqualified-id: name-id 16 | // CHECK-NEXT: identifier: print_like 17 | // CHECK-NEXT: declarator-chunk-list 18 | // CHECK-NEXT: function-declarator-chunk 19 | // CHECK-NEXT: parameter-declaration-clause: parameter-declaration-clause 20 | // CHECK-NEXT: is-variadic: true 21 | // CHECK-NEXT: parameter-declaration-list 22 | // CHECK-NEXT: parameter-declaration 23 | // CHECK-NEXT: identifier: fmt 24 | // CHECK-NEXT: type-specifier-list 25 | // CHECK-NEXT: const-qualifier 26 | // CHECK-NEXT: integral-type-specifier 27 | // CHECK-NEXT: specifier: char 28 | // CHECK-NEXT: declarator: declarator 29 | // CHECK-NEXT: ptr-op-list 30 | // CHECK-NEXT: pointer-operator 31 | // CHECK-NEXT: core-declarator: id-declarator 32 | // CHECK-NEXT: unqualified-id: name-id 33 | // CHECK-NEXT: identifier: fmt 34 | -------------------------------------------------------------------------------- /tests/unit_tests/lit.cfg.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | import os 21 | 22 | import lit.util 23 | import lit.formats 24 | 25 | config.name = "C++" 26 | 27 | config.test_format = lit.formats.ShTest() 28 | 29 | config.suffixes = [".cc", ".yml"] 30 | 31 | config.test_source_root = os.path.dirname(__file__) 32 | 33 | config.substitutions.append(("%cxx", config.cxx)) 34 | config.substitutions.append(("%filecheck", config.filecheck)) 35 | -------------------------------------------------------------------------------- /tests/unit_tests/lit.site.cfg.py.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | config.cxx = "@CXX_FRONTEND_TARGET_FILE@" 21 | 22 | config.filecheck = "@FILECHECK_EXECUTABLE@" 23 | 24 | config.cxx_unit_tests_root = "@CMAKE_CURRENT_SOURCE_DIR@" 25 | 26 | lit_config.load_config( 27 | config, os.path.join(config.cxx_unit_tests_root, "lit.cfg.py")) 28 | -------------------------------------------------------------------------------- /tests/unit_tests/lsp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME lsp 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/lsp/code_completion_01.yml: -------------------------------------------------------------------------------- 1 | # RUN: %cxx -lsp-test < %s | %filecheck %s 2 | 3 | { "method": "initialize", "id": 0 } 4 | 5 | # CHECK: "id": 0 6 | 7 | { "method": "textDocument/didOpen", "id": 1, "params": { "textDocument": { "uri": "test:///source.cc", "version": 0, "text": "struct P { int x, y; }; void ff() { P p; p.\n\n\n}" } } } 8 | 9 | { "method": "$/setTrace", "id": 2, "params": { "value": "verbose" } } 10 | 11 | { "method": "textDocument/completion", "id": 3, "params": { "textDocument": { "uri": "test:///source.cc" }, "position": { "line": 2, "character": 1 } } } 12 | 13 | # CHECK: "message": "Did receive CompletionRequest" 14 | # CHECK: "id": 3 15 | # CHECK: "result": 16 | # CHECK: "label": "x" 17 | # CHECK: "label": "y" 18 | 19 | { "method": "shutdown", "id": 4 } 20 | 21 | { "method": "exit" } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/unit_tests/lsp/document_01.yml: -------------------------------------------------------------------------------- 1 | # RUN: %cxx -lsp-test < %s | %filecheck %s 2 | 3 | { "method": "initialize", "id": 0 } 4 | 5 | { "method": "textDocument/didOpen", "id": 1, "params": { "textDocument": { "uri": "test:///source.cc", "version": 0, "text": "auto main() -> int;" } } } 6 | 7 | # CHECK: "method": "textDocument/publishDiagnostics" 8 | # CHECK: "params": 9 | # CHECK: "diagnostics": [] 10 | # CHECK: "uri": "test:///source.cc" 11 | # CHECK: "version": 0 12 | 13 | { "method": "shutdown", "id": 2 } 14 | 15 | { "method": "exit" } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/unit_tests/lsp/document_symbols.yml: -------------------------------------------------------------------------------- 1 | # RUN: %cxx -lsp-test < %s | %filecheck %s 2 | 3 | { "method": "initialize", "id": 0 } 4 | 5 | # CHECK: "id": 0 6 | 7 | { "method": "textDocument/didOpen", "id": 1, "params": { "textDocument": { "uri": "test:///source.cc", "version": 0, "text": "#include \nauto main() -> int;" } } } 8 | 9 | { "method": "$/setTrace", "id": 2, "params": { "value": "verbose" } } 10 | 11 | { "method": "textDocument/documentSymbol", "id": 3, "params": { "textDocument": { "uri": "test:///source.cc" } } } 12 | 13 | # CHECK: "message": "Did receive DocumentSymbolRequest" 14 | # CHECK: "id": 3 15 | 16 | { "method": "shutdown", "id": 4 } 17 | 18 | { "method": "exit" } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/unit_tests/lsp/lifecycle_01.yml: -------------------------------------------------------------------------------- 1 | # RUN: %cxx -lsp-test < %s | %filecheck %s 2 | 3 | { "method": "initialize", "id": 0 } 4 | 5 | # CHECK: "result": 6 | # CHECK: "capabilities": 7 | # CHECK: "textDocumentSync": 8 | 9 | # CHECK: "serverInfo": 10 | # CHECK: "name": 11 | # CHECK: "version": 12 | 13 | { "method": "shutdown", "id": 1 } 14 | 15 | { "method": "exit" } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/unit_tests/parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME parser 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/parser/postfix_expr_conflicts.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify %s 2 | 3 | auto incr(int x) -> int { return x++; } 4 | auto decr(int x) -> int { return x--; } 5 | auto call(int (*f)(int, int), int x) { return (f)(x, x); } 6 | auto subscript(int a[], int n) -> int { return a[n]; } 7 | 8 | auto incr_1(int x) -> int { return (x)++; } 9 | auto decr_1(int x) -> int { return (x)--; } 10 | 11 | auto subscript_1(int a[], int n) -> int { return (a)[n]; } 12 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME preprocessor 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/bol_001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | // clang-format off 4 | aa 5 | #if 0 6 | unreachable 7 | #endif 8 | /**/bb 9 | cc 10 | 11 | // CHECK: {{^}}aa{{$}} 12 | // CHECK: {{^}} bb{{$}} 13 | // CHECK: {{^}}cc{{$}} 14 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/counter.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | #define CONCAT_HELPER(a, b) a##b 4 | 5 | #define CONCAT(a, b) CONCAT_HELPER(a, b) 6 | 7 | #define id(x) CONCAT(x, CONCAT(_, __COUNTER__)) 8 | 9 | const int id(a) = 0; 10 | // CHECK: {{^}}const int a_0 = 0;{{$}} 11 | 12 | const int id(b) = 1; 13 | // CHECK: {{^}}const int b_1 = 1;{{$}} 14 | 15 | const int id(c) = 2; 16 | // CHECK: {{^}}const int c_2 = 2;{{$}} 17 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/define.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -E %s -o - | %filecheck %s 2 | 3 | #define RESULT 0 4 | 5 | int main() { 6 | int result = RESULT; 7 | return result; 8 | } 9 | 10 | // CHECK: int result = 0 ; -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/define.002.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | #define RESULT 0 4 | 5 | #define RESULT 1 // expected-warning {{'RESULT' macro redefined}} 6 | 7 | int main() { 8 | int result = RESULT; 9 | return result; 10 | } 11 | 12 | // CHECK: int result = 1 ; -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/define.003.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | #define FOR_EACH(V) \ 4 | V(aa) \ 5 | V(bb) \ 6 | V(cc) 7 | 8 | #define DECLARE_VAR(v) int v; 9 | 10 | int main() { FOR_EACH(DECLARE_VAR) } 11 | 12 | // CHECK: int aa ; int bb ; int cc ; 13 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/define.004.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | #define WANTS_CC 1 4 | 5 | #define WANTS_CC 1 6 | 7 | static_assert(WANTS_CC == 1); 8 | 9 | // CHECK: {{^}}static_assert(1 == 1);{{$}} 10 | 11 | #define WANTS_CC 2 // expected-warning {{'WANTS_CC' macro redefined}} 12 | 13 | static_assert(WANTS_CC == 2); 14 | 15 | // CHECK: {{^}}static_assert(2 == 2);{{$}} 16 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/elifdef_001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -E %s -o - | %filecheck %s 2 | 3 | #define B 4 | 5 | #ifdef A 6 | int a_not_reachable; 7 | #elifdef B 8 | int b_reachable; 9 | #elifdef C 10 | int c_not_reachable; 11 | #else 12 | int else_not_reachable; 13 | #endif 14 | 15 | // CHECK: b_reachable; 16 | 17 | #ifdef AA 18 | int aa_not_reachable; 19 | #elifndef BB 20 | int bb_reachable; 21 | #elifndef CC 22 | int cc_not_reachable; 23 | #elifdef DD 24 | int dd_not_reachable; 25 | #else 26 | int else_not_reachable; 27 | #endif 28 | 29 | // CHECK: bb_reachable; 30 | 31 | #ifdef AAA 32 | int aaa_not_reachable; 33 | #elifdef BBB 34 | int bbb_not_reachable; 35 | #elifdef CCC 36 | int ccc_not_reachable; 37 | #else 38 | int else_reachable; 39 | #endif 40 | 41 | // CHECK: else_reachable; 42 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/file.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | const char* file = __FILE__; 4 | 5 | // CHECK: {{^}}const char* file = "{{.*}}file.001.cc";{{$}} 6 | 7 | #include "file.001.h" 8 | 9 | // CHECK: {{^}}const char* file_h = "{{.*}}file.001.h";{{$}} 10 | 11 | const char* file_cc = __FILE__; 12 | 13 | // CHECK: {{^}}const char* file_cc = "{{.*}}file.001.cc";{{$}} 14 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/file.001.h: -------------------------------------------------------------------------------- 1 | 2 | const char* file_h = __FILE__; 3 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/line.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | const bool line_3 = __LINE__ == 3; 4 | 5 | // CHECK: {{^}}const bool line_3 = 3 == 3;{{$}} 6 | 7 | const bool line_7 = __LINE__ == 7; 8 | 9 | // CHECK: {{^}}const bool line_7 = 7 == 7;{{$}} 10 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/merge_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E -P %s -o - | %filecheck %s 2 | 3 | #define STR(prefix) prefix##"/*%empty*/" 4 | 5 | auto cstr = STR(); 6 | auto wstr = STR(L); 7 | auto ustr = STR(U); 8 | 9 | // CHECK: auto cstr = "/*%empty*/"; 10 | // CHECK: auto wstr = L"/*%empty*/"; 11 | // CHECK: auto ustr = U"/*%empty*/"; -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/va_args_001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -E -P %s -o - | %filecheck %s 2 | 3 | #define declare(type, ...) __VA_OPT__(type) __VA_ARGS__ __VA_OPT__(;) 4 | 5 | // clang-format off 6 | 7 | declare(int, a, b, c) 8 | 9 | // CHECK: int a, b, c; 10 | 11 | declare() 12 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/va_args_002.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -E -P %s -o - | %filecheck %s 2 | 3 | // clang-format off 4 | 5 | #define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_I(text) 6 | #define BOOST_PP_STRINGIZE_I(...) #__VA_ARGS__ 7 | 8 | auto fn = BOOST_PP_STRINGIZE_I(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER); 9 | 10 | // CHECK: auto fn = "boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER"; 11 | -------------------------------------------------------------------------------- /tests/unit_tests/preprocessor/warning.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -E %s -o - | %filecheck %s 2 | 3 | #ifndef PLATFORM 4 | #warning "undefined platform" // expected-warning {{#warning "undefined platform"}} 5 | #endif 6 | 7 | #define PLATFORM "linux" 8 | 9 | #ifdef PLATFORM 10 | const char* platform = PLATFORM; 11 | #endif 12 | 13 | // CHECK: const char* platform = "linux" ; 14 | -------------------------------------------------------------------------------- /tests/unit_tests/requirements.txt: -------------------------------------------------------------------------------- 1 | lit==18.1.8 2 | filecheck==0.0.24 3 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME sema 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/address_op_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct X { 4 | int m{}; 5 | const int ci{}; 6 | const volatile int cvi{}; 7 | 8 | void f(); 9 | void g(int a, const void* ptr) const; 10 | }; 11 | 12 | auto main() -> int { 13 | static_assert(__is_same(decltype(&X::m), int X::*)); 14 | static_assert(__is_same(decltype(&X::ci), const int X::*)); 15 | static_assert(__is_same(decltype(&X::cvi), const volatile int X::*)); 16 | static_assert(__is_same(decltype(&X::f), void (X::*)())); 17 | static_assert( 18 | __is_same(decltype(&X::g), void (X::*)(int, const void*) const)); 19 | 20 | char ch{}; 21 | static_assert(__is_same(decltype(&ch), char*)); 22 | 23 | int i{}; 24 | static_assert(__is_same(decltype(&i), int*)); 25 | 26 | const void* p = nullptr; 27 | static_assert(__is_same(decltype(&p), const void**)); 28 | 29 | int a[2]; 30 | static_assert(__is_same(decltype(&a), int(*)[2])); 31 | 32 | X x; 33 | static_assert(__is_same(decltype(&x), X*)); 34 | static_assert(__is_same(decltype(*&x), X&)); 35 | 36 | const X cx; 37 | static_assert(__is_same(decltype(&cx), const X*)); 38 | static_assert(__is_same(decltype(*&cx), const X&)); 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/alignof_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -toolchain wasm32 -verify -fcheck %s 2 | 3 | static_assert(alignof(bool) == 1); 4 | static_assert(alignof(signed char) == 1); 5 | static_assert(alignof(unsigned char) == 1); 6 | static_assert(alignof(short) == 2); 7 | static_assert(alignof(unsigned short) == 2); 8 | static_assert(alignof(int) == 4); 9 | static_assert(alignof(unsigned int) == 4); 10 | static_assert(alignof(long long) == 8); 11 | static_assert(alignof(unsigned long long) == 8); 12 | static_assert(alignof(float) == 4); 13 | static_assert(alignof(double) == 8); 14 | static_assert(alignof(char) == 1); 15 | static_assert(alignof(wchar_t) == 4); 16 | static_assert(alignof(char8_t) == 1); 17 | static_assert(alignof(char16_t) == 2); 18 | static_assert(alignof(char32_t) == 4); 19 | 20 | #ifdef __wasm32__ 21 | static_assert(alignof(long) == 4); 22 | static_assert(alignof(unsigned long) == 4); 23 | static_assert(alignof(long double) == 16); 24 | #endif 25 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/bitwise_not_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | static_assert(__is_same(decltype(~'a'), int)); 5 | static_assert(__is_same(decltype(~1), int)); 6 | static_assert(__is_same(decltype(~1l), long)); 7 | static_assert(__is_same(decltype(~1ll), long long)); 8 | static_assert(__is_same(decltype(~1ul), unsigned long)); 9 | static_assert(__is_same(decltype(~1ull), unsigned long long)); 10 | 11 | short x{}; 12 | static_assert(__is_same(decltype(~x), int)); 13 | 14 | short& y = x; 15 | static_assert(__is_same(decltype(~y), int)); 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/class_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct X { 4 | void f() { 5 | static_assert(__is_same(decltype(this), X*)); 6 | static_assert(__is_same(decltype(*this), X&)); 7 | } 8 | 9 | void f() const { 10 | static_assert(__is_same(decltype(this), const X*)); 11 | static_assert(__is_same(decltype(*this), const X&)); 12 | } 13 | 14 | void f() volatile { 15 | static_assert(__is_same(decltype(this), volatile X*)); 16 | static_assert(__is_same(decltype(*this), volatile X&)); 17 | } 18 | 19 | void f() const volatile { 20 | static_assert(__is_same(decltype(this), const volatile X*)); 21 | static_assert(__is_same(decltype(*this), const volatile X&)); 22 | } 23 | 24 | void g(); 25 | void g() const; 26 | void g() volatile; 27 | void g() const volatile; 28 | }; 29 | 30 | void X::g() { 31 | static_assert(__is_same(decltype(this), X*)); 32 | static_assert(__is_same(decltype(*this), X&)); 33 | 34 | X* self = this; 35 | static_assert(__is_same(decltype(self), X*)); 36 | static_assert(__is_same(decltype(*self), X&)); 37 | 38 | X*& x = self; 39 | static_assert(__is_same(decltype(x), X*&)); 40 | static_assert(__is_same(decltype(*x), X&)); 41 | } 42 | 43 | void X::g() const { 44 | static_assert(__is_same(decltype(this), const X*)); 45 | static_assert(__is_same(decltype(*this), const X&)); 46 | } 47 | 48 | void X::g() volatile { 49 | static_assert(__is_same(decltype(this), volatile X*)); 50 | static_assert(__is_same(decltype(*this), volatile X&)); 51 | } 52 | 53 | void X::g() const volatile { 54 | static_assert(__is_same(decltype(this), const volatile X*)); 55 | static_assert(__is_same(decltype(*this), const volatile X&)); 56 | } 57 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/constant_expression_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | static_assert('0'); 4 | static_assert(('0')); 5 | static_assert('0' + 1); 6 | static_assert(1 && 2); 7 | static_assert(0 || "ciao"); 8 | static_assert(1 + 0); 9 | static_assert(1 - 0 + 1 == 2); 10 | 11 | enum E { A = 123 }; 12 | static_assert(A == 122 + 1); 13 | 14 | static_assert(1 & 1); 15 | static_assert(0b1 | 0b10 == 0b11); 16 | static_assert(1 ^ 1 == 0); 17 | static_assert(1 + 1 != 2 - 1); 18 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/ctor_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct C { 4 | struct bar {}; 5 | 6 | C() {} 7 | C(int); 8 | C(bar); 9 | 10 | C* next; 11 | }; 12 | 13 | C::C(bar b) {} 14 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/decltype_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | static_assert(__is_null_pointer(decltype(nullptr))); 4 | 5 | static_assert(__is_floating_point(decltype(0.1))); 6 | static_assert(__is_floating_point(decltype(0.1f))); 7 | 8 | static_assert(__is_integral(decltype('x'))); 9 | static_assert(__is_integral(decltype(u8'x'))); 10 | static_assert(__is_integral(decltype(0))); 11 | static_assert(__is_integral(decltype(0U))); 12 | static_assert(__is_unsigned(decltype(0U))); 13 | static_assert(__is_signed(decltype(0))); 14 | 15 | static_assert(__is_fundamental(decltype(true))); 16 | static_assert(__is_arithmetic(decltype(true))); 17 | static_assert(__is_unsigned(decltype(true))); 18 | 19 | static_assert(__is_lvalue_reference(decltype("ciao"))); 20 | static_assert(__is_lvalue_reference(decltype(("ciao")))); 21 | 22 | static_assert(__is_same(decltype(nullptr), decltype(nullptr))); 23 | static_assert(__is_same(unsigned, unsigned int)); 24 | static_assert(__is_same(unsigned int, decltype(0U))); 25 | static_assert(__is_same(int, decltype(0))); 26 | static_assert(__is_same(unsigned long, decltype(0ul))); 27 | static_assert(__is_same(unsigned long long, decltype(0ull))); 28 | 29 | static_assert(__is_same(decltype(true), decltype(false))); 30 | static_assert(__is_same(decltype(true), bool)); 31 | static_assert(__is_same(decltype('c'), char)); 32 | static_assert(__is_same(decltype(u8'c'), char8_t)); 33 | static_assert(__is_same(decltype(u'c'), char16_t)); 34 | static_assert(__is_same(decltype(U'c'), char32_t)); 35 | static_assert(__is_same(decltype(L'c'), wchar_t)); 36 | 37 | static_assert(__is_same(int (*)(), int (*)())); 38 | 39 | static_assert(__is_same(decltype("ciao"), const char (&)[5])); 40 | 41 | // expected-error@1 {{static assert failed}} 42 | static_assert(__is_same(char, unsigned char)); 43 | 44 | // expected-error@1 {{static assert failed}} 45 | static_assert(__is_same(char, signed char)); 46 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/function_params_01.cc: -------------------------------------------------------------------------------- 1 | // clang-format off 2 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 3 | // clang-format on 4 | 5 | struct C { 6 | void aa() const; 7 | void bb() volatile; 8 | void cc() const volatile; 9 | void dd() &; 10 | void ee() &&; 11 | void ff() const volatile& noexcept; 12 | }; 13 | 14 | // clang-format off 15 | // CHECK: class C 16 | // CHECK: function void aa() const 17 | // CHECK: function void bb() volatile 18 | // CHECK: function void cc() const volatile 19 | // CHECK: function void dd() & 20 | // CHECK: function void ee() && 21 | // CHECK: function void ff() const volatile & noexcept -------------------------------------------------------------------------------- /tests/unit_tests/sema/fwd_class_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | namespace cxx { 4 | class BasicBlock; 5 | class ExpressionAST; 6 | } // namespace cxx 7 | 8 | namespace cxx::ir { 9 | class BasicBlock; 10 | } 11 | 12 | namespace cxx { 13 | struct Codegen { 14 | void cg_condition(ExpressionAST* ast, ir::BasicBlock* iftrue, 15 | ir::BasicBlock* iffalse); 16 | }; 17 | } // namespace cxx 18 | 19 | // clang-format off 20 | // CHECK:namespace 21 | // CHECK: namespace cxx 22 | // CHECK: class BasicBlock 23 | // CHECK: class ExpressionAST 24 | // CHECK: namespace ir 25 | // CHECK: class BasicBlock 26 | // CHECK: class Codegen 27 | // CHECK: function void cg_condition(cxx::ExpressionAST*, ir::BasicBlock*, ir::BasicBlock*) 28 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/incr_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | char c{}; 5 | static_assert(__is_same(decltype(++c), char&)); 6 | static_assert(__is_same(decltype(--c), char&)); 7 | static_assert(__is_lvalue_reference(decltype(++c))); 8 | static_assert(__is_lvalue_reference(decltype(--c))); 9 | 10 | int x{}; 11 | static_assert(__is_same(decltype(++x), int&)); 12 | static_assert(__is_same(decltype(--x), int&)); 13 | static_assert(__is_lvalue_reference(decltype(++x))); 14 | static_assert(__is_lvalue_reference(decltype(--x))); 15 | 16 | float f{}; 17 | static_assert(__is_same(decltype(++f), float&)); 18 | static_assert(__is_same(decltype(--f), float&)); 19 | static_assert(__is_lvalue_reference(decltype(++f))); 20 | static_assert(__is_lvalue_reference(decltype(--f))); 21 | 22 | double d{}; 23 | static_assert(__is_same(decltype(++d), double&)); 24 | static_assert(__is_same(decltype(--d), double&)); 25 | static_assert(__is_lvalue_reference(decltype(++d))); 26 | static_assert(__is_lvalue_reference(decltype(--d))); 27 | 28 | char* p{}; 29 | static_assert(__is_same(decltype(++p), char*&)); 30 | static_assert(__is_same(decltype(--p), char*&)); 31 | static_assert(__is_lvalue_reference(decltype(++p))); 32 | static_assert(__is_lvalue_reference(decltype(--p))); 33 | 34 | char*& pr = p; 35 | static_assert(__is_same(decltype(++pr), char*&)); 36 | static_assert(__is_same(decltype(--pr), char*&)); 37 | static_assert(__is_lvalue_reference(decltype(++pr))); 38 | static_assert(__is_lvalue_reference(decltype(--pr))); 39 | 40 | // clang-format off 41 | 42 | int a[10]; 43 | 44 | ++(+a); // expected-error {{cannot increment an rvalue of type 'int*'}} 45 | 46 | ++a; // expected-error {{cannot increment a value of type 'int [10]'}} 47 | 48 | --(+a); // expected-error {{cannot decrement an rvalue of type 'int*'}} 49 | 50 | --a; // expected-error {{cannot decrement a value of type 'int [10]'}} 51 | 52 | // clang-format on 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/is_base_of_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct Base; 4 | struct OtherBase; 5 | struct Derived; 6 | struct AlsoDerived; 7 | 8 | using BaseAlias = Base; 9 | using OtherBaseAlias = OtherBase; 10 | using DerivedAlias = Derived; 11 | using AlsoDerivedAlias = AlsoDerived; 12 | 13 | struct Base {}; 14 | struct OtherBase {}; 15 | struct Derived : Base, OtherBase {}; 16 | struct AlsoDerived : BaseAlias, OtherBaseAlias {}; 17 | 18 | static_assert(__is_base_of(Base, Derived)); 19 | static_assert(__is_base_of(Base, DerivedAlias)); 20 | static_assert(__is_base_of(BaseAlias, Derived)); 21 | static_assert(__is_base_of(BaseAlias, DerivedAlias)); 22 | 23 | static_assert(__is_base_of(OtherBase, Derived)); 24 | static_assert(__is_base_of(OtherBase, DerivedAlias)); 25 | static_assert(__is_base_of(OtherBaseAlias, Derived)); 26 | static_assert(__is_base_of(OtherBaseAlias, DerivedAlias)); 27 | 28 | static_assert(__is_base_of(Base, AlsoDerived)); 29 | static_assert(__is_base_of(Base, AlsoDerivedAlias)); 30 | static_assert(__is_base_of(BaseAlias, AlsoDerived)); 31 | static_assert(__is_base_of(BaseAlias, AlsoDerivedAlias)); 32 | 33 | static_assert(__is_base_of(const Base, const AlsoDerived)); 34 | static_assert(__is_base_of(const Base, const AlsoDerivedAlias)); 35 | static_assert(__is_base_of(const BaseAlias, const AlsoDerived)); 36 | static_assert(__is_base_of(const BaseAlias, const AlsoDerivedAlias)); 37 | 38 | static_assert(__is_base_of(Derived, Derived)); 39 | 40 | Base base; 41 | 42 | struct C : decltype(base) {}; 43 | 44 | static_assert(__is_base_of(Base, C)); 45 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/is_final_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct C {}; 4 | 5 | struct F final {}; 6 | 7 | static_assert(__is_final(F)); 8 | static_assert(__is_final(const F)); 9 | 10 | static_assert(__is_final(C) == false); -------------------------------------------------------------------------------- /tests/unit_tests/sema/logical_neg_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | static_assert(__is_same(decltype(!true), bool)); 5 | static_assert(__is_same(decltype(!!true), bool)); 6 | 7 | static_assert(__is_same(decltype(!1), bool)); 8 | static_assert(__is_same(decltype(!1.0), bool)); 9 | 10 | const void* p = nullptr; 11 | static_assert(__is_same(decltype(!p), bool)); 12 | 13 | static_assert(__is_same(decltype(!main), bool)); 14 | 15 | const int a[2] = {1, 2}; 16 | static_assert(__is_same(decltype(!a), bool)); 17 | 18 | int x{}, &y = x; 19 | 20 | static_assert(__is_same(decltype(!x), bool)); 21 | static_assert(__is_same(decltype(!y), bool)); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/member_access_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | // clang-format off 4 | 5 | auto main() -> int { 6 | using i32 = int; 7 | using u32 = unsigned int; 8 | 9 | int i; 10 | const int ci = 0; 11 | int& ri = i; 12 | const int& cri = ci; 13 | 14 | i.~i32(); 15 | ci.~i32(); 16 | ri.~i32(); 17 | cri.~i32(); 18 | 19 | i.~u32(); // expected-error {{the type of object expression does not match the type being destroyed}} 20 | 21 | int* pi = nullptr; 22 | 23 | pi->~i32(); 24 | pi->~u32(); // expected-error {{the type of object expression does not match the type being destroyed}} 25 | 26 | using nullptr_t = decltype(nullptr); 27 | 28 | (nullptr).~nullptr_t(); 29 | 30 | using int_ptr = i32*; 31 | 32 | int_ptr ip = nullptr; 33 | ip.~int_ptr(); 34 | ip.~nullptr_t(); // expected-error {{the type of object expression does not match the type being destroyed}} 35 | 36 | ip->~i32(); 37 | ip->~u32(); // expected-error {{the type of object expression does not match the type being destroyed}} 38 | 39 | static_assert(__is_same(decltype(i.~i32()), void)); 40 | 41 | return 0; 42 | } 43 | 44 | // clang-format on 45 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/member_access_02.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -freport-missing-types %s 2 | 3 | struct X { 4 | enum E { kValue = 0 }; 5 | 6 | static int s_value; 7 | }; 8 | 9 | struct W { 10 | int& r; 11 | const int& cr; 12 | 13 | const int const_k = 0; 14 | int k = 0; 15 | 16 | mutable int m = 0; 17 | }; 18 | 19 | auto main() -> int { 20 | X x; 21 | static_assert(__is_reference(decltype(x.kValue)) == false); 22 | static_assert(__is_same(decltype(x.kValue), X::E)); 23 | 24 | X& xr = x; 25 | static_assert(__is_reference(decltype(xr.kValue)) == false); 26 | static_assert(__is_same(decltype(xr.kValue), X::E)); 27 | 28 | const X& cxr = x; 29 | static_assert(__is_reference(decltype(cxr.kValue)) == false); 30 | static_assert(__is_same(decltype(cxr.kValue), X::E)); 31 | 32 | X* px = &x; 33 | 34 | static_assert(__is_reference(decltype(px->kValue)) == false); 35 | static_assert(__is_same(decltype(px->kValue), X::E)); 36 | 37 | static_assert(__is_reference(decltype(px->s_value)) == false); 38 | static_assert(__is_same(decltype(px->s_value), int)); 39 | 40 | int i; 41 | 42 | // clang-format off 43 | W w{i, i}; // expected-warning {{untyped expression of kind 'braced-init-list'}} 44 | // clang-format on 45 | 46 | static_assert(__is_lvalue_reference(decltype(w.r))); 47 | static_assert(__is_same(decltype(w.r), int&)); 48 | 49 | static_assert(__is_lvalue_reference(decltype(w.cr))); 50 | static_assert(__is_same(decltype(w.cr), const int&)); 51 | 52 | static_assert(__is_same(decltype((w.const_k)), const int&)); 53 | static_assert(__is_same(decltype((w.k)), int&)); 54 | 55 | // clang-format off 56 | const W cw{i, i}; // expected-warning {{untyped expression of kind 'braced-init-list'}} 57 | // clang-format on 58 | 59 | static_assert(__is_same(decltype(cw.const_k), const int)); 60 | static_assert(__is_same(decltype(cw.k), int)); 61 | 62 | static_assert(__is_same(decltype((cw.const_k)), const int&)); 63 | static_assert(__is_same(decltype((cw.k)), const int&)); 64 | static_assert(__is_same(decltype((cw.m)), int&)); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/sizeof_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -toolchain wasm32 -verify -fcheck %s 2 | 3 | static_assert(sizeof(bool) == 1); 4 | static_assert(sizeof(signed char) == 1); 5 | static_assert(sizeof(unsigned char) == 1); 6 | static_assert(sizeof(short) == 2); 7 | static_assert(sizeof(unsigned short) == 2); 8 | static_assert(sizeof(int) == 4); 9 | static_assert(sizeof(unsigned int) == 4); 10 | static_assert(sizeof(long long) == 8); 11 | static_assert(sizeof(unsigned long long) == 8); 12 | static_assert(sizeof(float) == 4); 13 | static_assert(sizeof(double) == 8); 14 | static_assert(sizeof(char) == 1); 15 | static_assert(sizeof(wchar_t) == 4); 16 | static_assert(sizeof(char8_t) == 1); 17 | static_assert(sizeof(char16_t) == 2); 18 | static_assert(sizeof(char32_t) == 4); 19 | 20 | #ifdef __wasm32__ 21 | static_assert(sizeof(long) == 4); 22 | static_assert(sizeof(unsigned long) == 4); 23 | static_assert(sizeof(long double) == 16); 24 | #endif 25 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/static_assert_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | static_assert(true); 4 | static_assert('a'); 5 | static_assert(1); 6 | static_assert(0.1); 7 | static_assert(0.1f); 8 | static_assert("hello"); 9 | 10 | // expected-error@1 {{static assert failed}} 11 | static_assert(false); 12 | 13 | // expected-error@1 {{static assert failed}} 14 | static_assert(0); 15 | 16 | // expected-error@1 {{static assert failed}} 17 | static_assert(0.0); 18 | 19 | // expected-error@1 {{static assert failed}} 20 | static_assert('\0'); 21 | 22 | // expected-error@1 {{"it will fail"}} 23 | static_assert(false, "it will fail"); 24 | 25 | int a = 0; 26 | 27 | // clang-format off 28 | // expected-error@1 {{static assertion expression is not an integral constant expression}} 29 | static_assert(a); 30 | 31 | // clang-format on 32 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/static_cast_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | struct X {}; 4 | 5 | using F = int(); 6 | 7 | int f() { return 0; } 8 | 9 | auto main() -> int { 10 | X x; 11 | 12 | F&& rf = f; 13 | 14 | // prvalue 15 | static_assert(__is_reference(decltype(static_cast(x))) == false); 16 | 17 | // lvalue if lvalue reference to object type 18 | static_assert(__is_lvalue_reference(decltype(static_cast(x)))); 19 | 20 | // rvalue if rvalue reference to object type 21 | static_assert(__is_rvalue_reference(decltype(static_cast(x)))); 22 | 23 | // prvalue 24 | static_assert(__is_reference(decltype(static_cast(f))) == false); 25 | 26 | // lvalue if lvalue reference to function type 27 | static_assert(__is_lvalue_reference(decltype(static_cast(f)))); 28 | 29 | // lvalue if rvalue reference to function type 30 | static_assert(__is_lvalue_reference(decltype(static_cast(f)))); 31 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/static_cast_02.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -freport-missing-types %s 2 | 3 | // clang-format off 4 | 5 | struct B {}; 6 | struct D : B {}; 7 | 8 | auto main() -> int { 9 | B b; 10 | const B cb; 11 | 12 | // check casts to void 13 | static_cast(b); 14 | static_cast(b); 15 | static_cast(b); 16 | static_cast(123); 17 | static_cast(cb); 18 | 19 | // check casts to derived class 20 | D& d = static_cast(b); 21 | const D& cd1 = static_cast(b); 22 | const D& cd2 = static_cast(cb); 23 | const volatile D& cd3 = static_cast(cb); 24 | 25 | D& d = static_cast(cb); // expected-error {{invalid static_cast of 'const ::B' to '::D'}} 26 | 27 | return 0; 28 | } 29 | 30 | // clang-format on 31 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/subtraction_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | char* p; 5 | const char* cp; 6 | void* vp; 7 | int i = 0; 8 | short s = 0; 9 | 10 | static_assert(__is_same(int, decltype('a' - '0'))); 11 | static_assert(__is_same(int, decltype('a' - 0))); 12 | static_assert(__is_same(int, decltype('a' - s))); 13 | static_assert(__is_same(long, decltype('a' - 1l))); 14 | static_assert(__is_same(unsigned, decltype('a' - 1u))); 15 | 16 | static_assert(__is_same(decltype(p), decltype(p - 0))); 17 | static_assert(__is_same(decltype(p), decltype(p - i))); 18 | 19 | static_assert(__is_same(long, decltype(p - p))); 20 | static_assert(__is_same(long, decltype(p - cp))); 21 | 22 | // clang-format off 23 | 24 | // expected-error@1 {{'char*' and 'void*' are not pointers to compatible types}} 25 | p - vp; 26 | 27 | // expected-error@1 {{invalid operands to binary expression 'int' and 'char*'}} 28 | 0 - p; 29 | 30 | // clang-format on 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/template_alias_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | template 4 | using Pointer = T*; 5 | 6 | using IntPointer = Pointer; 7 | 8 | // clang-format off 9 | // CHECK:namespace 10 | // CHECK-NEXT:template typealias T* Pointer 11 | // CHECK-NEXT: parameter typename<0, 0> T 12 | // CHECK-NEXT: typealias int* IntPointer 13 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/template_alias_02.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | template 4 | struct HashMap { 5 | using iterator = Value*; 6 | }; 7 | 8 | struct Name; 9 | struct Symbol; 10 | 11 | struct Scope { 12 | using Table = HashMap; 13 | using MemberIterator = Table::iterator; 14 | }; 15 | 16 | // clang-format off 17 | // CHECK:namespace 18 | // CHECK: template class HashMap 19 | // CHECK: parameter typename<0, 0> Key 20 | // CHECK: parameter typename<1, 0> Value 21 | // CHECK: typealias Value* iterator 22 | // CHECK: [specializations] 23 | // CHECK: class HashMap 24 | // CHECK: typealias ::Symbol** iterator 25 | // CHECK: class Name 26 | // CHECK: class Symbol 27 | // CHECK: class Scope 28 | // CHECK: typealias ::HashMap Table 29 | // CHECK: typealias ::Symbol** MemberIterator 30 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/template_class_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | template 4 | struct A { 5 | T a; 6 | A* next; 7 | 8 | auto get_a() -> T; 9 | void set_a(const T& a); 10 | 11 | using type = T; 12 | using reference = T&; 13 | }; 14 | 15 | A a1; 16 | A a2; 17 | 18 | // clang-format off 19 | // CHECK:namespace 20 | // CHECK-NEXT: template class A 21 | // CHECK-NEXT: parameter typename<0, 0> T 22 | // CHECK-NEXT: field T a 23 | // CHECK-NEXT: field A* next 24 | // CHECK-NEXT: function T get_a() 25 | // CHECK-NEXT: function void set_a(const T&) 26 | // CHECK-NEXT: typealias T type 27 | // CHECK-NEXT: typealias T& reference 28 | // CHECK-NEXT: [specializations] 29 | // CHECK-NEXT: class A 30 | // CHECK-NEXT: field int a 31 | // CHECK-NEXT: field ::A* next 32 | // CHECK-NEXT: function int get_a() 33 | // CHECK-NEXT: function void set_a(const int&) 34 | // CHECK-NEXT: typealias int type 35 | // CHECK-NEXT: typealias int& reference 36 | // CHECK-NEXT: class A 37 | // CHECK-NEXT: field void* a 38 | // CHECK-NEXT: field ::A* next 39 | // CHECK-NEXT: function void* get_a() 40 | // CHECK-NEXT: function void set_a(void* const&) 41 | // CHECK-NEXT: typealias void* type 42 | // CHECK-NEXT: typealias void*& reference 43 | // CHECK-NEXT: variable ::A a1 44 | // CHECK-NEXT: variable ::A a2 -------------------------------------------------------------------------------- /tests/unit_tests/sema/template_class_03.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | template 4 | struct X { 5 | X(); 6 | X(int); 7 | 8 | auto self() const -> const X*; 9 | auto self() -> X*; 10 | }; 11 | 12 | template 13 | X::X() {} 14 | 15 | template 16 | X::X(int) {} 17 | 18 | template 19 | auto X::self() const -> const X* { 20 | return this; 21 | } 22 | 23 | template 24 | auto X::self() -> X* { 25 | return this; 26 | } 27 | 28 | // clang-format off 29 | // CHECK:namespace 30 | // CHECK-NEXT: template class X 31 | // CHECK-NEXT: parameter typename<0, 0> T 32 | // CHECK-NEXT: constructor X() 33 | // CHECK-NEXT: block 34 | // CHECK-NEXT: constructor X(int) 35 | // CHECK-NEXT: parameters 36 | // CHECK-NEXT: parameter int 37 | // CHECK-NEXT: block 38 | // CHECK-NEXT: function const ::X* self() const 39 | // CHECK-NEXT: block 40 | // CHECK-NEXT: function ::X* self() 41 | // CHECK-NEXT: block -------------------------------------------------------------------------------- /tests/unit_tests/sema/template_class_04.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | template 4 | struct X { 5 | Key key; 6 | Value value; 7 | 8 | void check() { static_assert(sizeof(*this)); } 9 | }; 10 | 11 | auto main() -> int { 12 | using U = X; 13 | U u; 14 | 15 | static_assert(sizeof(U) == 8); 16 | static_assert(sizeof(u) == 8); 17 | 18 | static_assert(__builtin_offsetof(U, key) == 0); 19 | static_assert(__builtin_offsetof(U, value) == 4); 20 | 21 | static_assert(sizeof(X::key) == 1); 22 | static_assert(sizeof(X::value) == 4); 23 | 24 | static_assert(sizeof(U::key) == 1); 25 | static_assert(sizeof(U::value) == 4); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/trailing_return_type_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | struct list { 4 | using value_type = int; 5 | 6 | struct iterator {}; 7 | 8 | auto begin() -> iterator; 9 | auto at(value_type) -> value_type; 10 | }; 11 | 12 | auto list::begin() -> iterator { return {}; } 13 | auto list::at(value_type) -> value_type { return 0; } 14 | 15 | // clang-format off 16 | // CHECK:namespace 17 | // CHECK-NEXT: class list 18 | // CHECK-NEXT: typealias int value_type 19 | // CHECK-NEXT: class iterator 20 | // CHECK-NEXT: function ::list::iterator begin() 21 | // CHECK-NEXT: block 22 | // CHECK-NEXT: function int at(int) 23 | // CHECK-NEXT: parameters 24 | // CHECK-NEXT: parameter int 25 | // CHECK-NEXT: block -------------------------------------------------------------------------------- /tests/unit_tests/sema/trailing_return_type_02.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | auto f(int x) -> decltype(x); 4 | auto g(int x, decltype(x)* y) -> decltype(y); 5 | auto k(int x) -> decltype((x)); 6 | 7 | // clang-format off 8 | // CHECK:namespace 9 | // CHECK-NEXT: function int f(int) 10 | // CHECK-NEXT: function int* g(int, int*) 11 | // CHECK-NEXT: function int& k(int) -------------------------------------------------------------------------------- /tests/unit_tests/sema/unary_minus_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | static_assert(__is_same(decltype(-'a'), int)); 5 | static_assert(__is_same(decltype(-1), int)); 6 | static_assert(__is_same(decltype(-1l), long)); 7 | static_assert(__is_same(decltype(-1ll), long long)); 8 | static_assert(__is_same(decltype(-1ul), unsigned long)); 9 | static_assert(__is_same(decltype(-1ull), unsigned long long)); 10 | static_assert(__is_same(decltype(-1.0f), float)); 11 | static_assert(__is_same(decltype(-1.0), double)); 12 | 13 | short x{}; 14 | static_assert(__is_same(decltype(-x), int)); 15 | 16 | short& y = x; 17 | static_assert(__is_same(decltype(-y), int)); 18 | 19 | unsigned u{}; 20 | static_assert(__is_same(decltype(-u), unsigned)); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/unary_plus_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -fcheck %s 2 | 3 | auto main() -> int { 4 | static_assert(__is_same(decltype(+'a'), int)); 5 | static_assert(__is_same(decltype(+1), int)); 6 | static_assert(__is_same(decltype(+1.0f), float)); 7 | static_assert(__is_same(decltype(+1.0), double)); 8 | 9 | short x{}; 10 | static_assert(__is_same(decltype(+x), int)); 11 | 12 | short& y = x; 13 | static_assert(__is_same(decltype(+y), int)); 14 | 15 | int a[2]; 16 | static_assert(__is_same(decltype(+a), int*)); 17 | 18 | void (*f)() = nullptr; 19 | static_assert(__is_same(decltype(+f), void (*)())); 20 | 21 | const void* p = nullptr; 22 | static_assert(__is_same(decltype(+p), const void*)); 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /tests/unit_tests/sema/using_decl_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -fcheck -dump-symbols %s | %filecheck %s 2 | 3 | int printf(const char*, ...); 4 | 5 | namespace std { 6 | using ::printf; 7 | } 8 | 9 | struct Base { 10 | operator bool() const; 11 | 12 | void f(); 13 | }; 14 | 15 | struct Derived : Base { 16 | using Base::operator bool; 17 | using Base::f; 18 | }; 19 | 20 | namespace std { 21 | using nullptr_t = decltype(nullptr); 22 | } // namespace std 23 | 24 | auto main() -> int { 25 | using std::nullptr_t; 26 | return 0; 27 | } 28 | 29 | // clang-format off 30 | // CHECK:namespace 31 | // CHECK-NEXT: function int printf(const char*...) 32 | // CHECK-NEXT: namespace std 33 | // CHECK-NEXT: using int printf(const char*...) 34 | // CHECK-NEXT: typealias decltype(nullptr) nullptr_t 35 | // CHECK-NEXT: class Base 36 | // CHECK-NEXT: function operator bool() const 37 | // CHECK-NEXT: function void f() 38 | // CHECK-NEXT: class Derived 39 | // CHECK-NEXT: base class Base 40 | // CHECK-NEXT: using operator bool() const 41 | // CHECK-NEXT: using void f() 42 | // CHECK-NEXT: function int main() 43 | // CHECK-NEXT: block 44 | // CHECK-NEXT: using decltype(nullptr) nullptr_t 45 | -------------------------------------------------------------------------------- /tests/unit_tests/sema/wasm_stdlib_01.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -toolchain wasm32 -fcheck %s 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | -------------------------------------------------------------------------------- /tests/unit_tests/tokens/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | add_test(NAME tokens 21 | COMMAND lit::tool --config-prefix $.lit -v ${CMAKE_CURRENT_BINARY_DIR}) 22 | -------------------------------------------------------------------------------- /tests/unit_tests/tokens/raw_string.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -dump-tokens %s -o - | %filecheck %s 2 | 3 | R"_(\-?(0|[1-9][0-9]*)(\.[0-9]+)?((e|E)(\+|\-)[0-9]+)?)_"; 4 | 5 | // clang-format off 6 | 7 | // CHECK: STRING_LITERAL 'R"_(\-?(0|[1-9][0-9]*)(\.[0-9]+)?((e|E)(\+|\-)[0-9]+)?)_"' 8 | // CHECK: SEMICOLON ';' 9 | -------------------------------------------------------------------------------- /tests/unit_tests/tokens/string.001.cc: -------------------------------------------------------------------------------- 1 | // RUN: %cxx -verify -dump-tokens %s -o - | %filecheck %s 2 | 3 | // clang-format off 4 | 5 | "string1" 6 | // CHECK: STRING_LITERAL '"string1"' [start-of-line] 7 | 8 | L"string2" 9 | // CHECK: WIDE_STRING_LITERAL 'L"string2"' [start-of-line] 10 | 11 | u8"string3" 12 | // CHECK: UTF8_STRING_LITERAL 'u8"string3"' [start-of-line] 13 | 14 | u"string4" 15 | // CHECK: UTF16_STRING_LITERAL 'u"string4"' [start-of-line] 16 | 17 | U"string15" 18 | // CHECK: UTF32_STRING_LITERAL 'U"string15"' [start-of-line] 19 | -------------------------------------------------------------------------------- /tools/kwgen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Roberto Raggi 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | cmake_minimum_required(VERSION 3.16) 21 | 22 | project(kwgen) 23 | 24 | if (KWGEN_EXECUTABLE) 25 | message(STATUS "Using KWGEN_EXECUTABLE: ${KWGEN_EXECUTABLE}") 26 | add_executable(kwgen IMPORTED) 27 | set_target_properties(kwgen PROPERTIES IMPORTED_LOCATION ${KWGEN_EXECUTABLE}) 28 | return() 29 | endif() 30 | 31 | set(CMAKE_CXX_STANDARD 20) 32 | 33 | aux_source_directory(. SOURCES) 34 | add_executable(kwgen ${SOURCES}) 35 | 36 | if(EMSCRIPTEN) 37 | target_link_options(kwgen PUBLIC 38 | "SHELL:-s EXIT_RUNTIME=1" 39 | "SHELL:-s NODERAWFS=1" 40 | "SHELL:-s ALLOW_MEMORY_GROWTH=1" 41 | ) 42 | endif() 43 | --------------------------------------------------------------------------------